More work on client and server
This commit is contained in:
@@ -2,25 +2,128 @@
|
||||
|
||||
#include "world.hpp"
|
||||
#include "drivenengine.hpp"
|
||||
#include "luaconsole.hpp"
|
||||
#include "util.hpp"
|
||||
#include "printbuffer.hpp"
|
||||
#include <memory>
|
||||
|
||||
class ServerClient {
|
||||
public:
|
||||
int64_t actor_id_;
|
||||
Channel *channel_;
|
||||
UniqueChannel channel_;
|
||||
UniqueWorld sync_;
|
||||
};
|
||||
using UniqueServerClient = std::unique_ptr<ServerClient>;
|
||||
using ServerClientVector = std::vector<UniqueServerClient>;
|
||||
|
||||
class LpxServer : public DrivenEngine {
|
||||
public:
|
||||
UniqueWorld master_;
|
||||
std::vector<std::unique_ptr<ServerClient>> clients_;
|
||||
LuaConsole console_;
|
||||
ServerClientVector clients_;
|
||||
PrintChanneler print_channeler_;
|
||||
int64_t admin_id_;
|
||||
|
||||
public:
|
||||
virtual void event_init(int argc, char *argv[]) {
|
||||
// Create the master world model.
|
||||
master_.reset(new World(util::WORLD_TYPE_MASTER));
|
||||
|
||||
// Create an actor for administrative commands.
|
||||
admin_id_ = master_->create_login_actor();
|
||||
|
||||
// Print out admin ID for debugging purposes.
|
||||
stdostream() << "Admin actor id = " << admin_id_ << std::endl;
|
||||
|
||||
// Enable listening on port 8085.
|
||||
listen_port(8085);
|
||||
|
||||
// Set the console prompt.
|
||||
get_stdio_channel()->set_prompt(console_.get_prompt());
|
||||
}
|
||||
|
||||
void do_lua_command(const util::StringVec &words) {
|
||||
if (words.size() != 2) {
|
||||
stdostream() << "lua command (lua) takes a single string" << std::endl;
|
||||
return;
|
||||
}
|
||||
const std::string &exp = words[1];
|
||||
InvocationData dummyresult;
|
||||
Invocation inv(Invocation::KIND_LUA, admin_id_, admin_id_, exp, dummyresult);
|
||||
master_->invoke(inv);
|
||||
}
|
||||
|
||||
void do_syntax_command(const util::StringVec &words) {
|
||||
stdostream() << "Syntax Error: ";
|
||||
for (int i = 1; i < int(words.size()); i++) {
|
||||
stdostream() << words[i] << " ";
|
||||
}
|
||||
stdostream() << std::endl;
|
||||
}
|
||||
|
||||
void do_quit_command(const util::StringVec &words) {
|
||||
if (words.size() != 1) {
|
||||
stdostream() << "quit command takes no arguments" << std::endl;
|
||||
return;
|
||||
}
|
||||
stop_driver();
|
||||
}
|
||||
|
||||
void do_command(const util::StringVec &words) {
|
||||
if (words.empty()) return;
|
||||
else if (words[0] == "lua") do_lua_command(words);
|
||||
else if (words[0] == "syntax") do_syntax_command(words);
|
||||
else if (words[0] == "quit") do_quit_command(words);
|
||||
else {
|
||||
stdostream() << "Unknown command: " << words[0] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_invocation(ServerClient *sclient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
// Check for keyboard input on stdin.
|
||||
while (true) {
|
||||
std::string line = get_stdio_channel()->in()->readline();
|
||||
if (line == "") break;
|
||||
console_.add(line);
|
||||
get_stdio_channel()->set_prompt(console_.get_prompt());
|
||||
do_command(console_.get_command());
|
||||
}
|
||||
|
||||
// Anything in the administrator printbuffer should go to stdostream.
|
||||
if (print_channeler_.channel(master_->get_printbuffer(admin_id_), stdostream())) {
|
||||
master_->invoke(print_channeler_.invocation(admin_id_));
|
||||
}
|
||||
|
||||
// Check for new incoming channels, set up client structures.
|
||||
while (true) {
|
||||
UniqueChannel chan = new_incoming_channel();
|
||||
if (chan == nullptr) break;
|
||||
ServerClient *client = new ServerClient;
|
||||
client->actor_id_ = master_->create_login_actor();
|
||||
client->channel_ = std::move(chan);
|
||||
client->sync_.reset(new World(util::WORLD_TYPE_S_SYNC));
|
||||
client->sync_->create_login_actor();
|
||||
clients_.emplace_back(client);
|
||||
stdostream() << "New client: actor id=" << client->actor_id_ << std::endl;
|
||||
}
|
||||
|
||||
// Traverse all existing channels, process any communication.
|
||||
ServerClientVector keep;
|
||||
for (UniqueServerClient &client : clients_) {
|
||||
if (client->channel_->closed()) {
|
||||
stdostream() << "Client closed: actor id=" << client->actor_id_ << std::endl;
|
||||
continue;
|
||||
}
|
||||
// Check for received invocations.
|
||||
while (handle_invocation(client.get()));
|
||||
// Transfer the client to the keep vector.
|
||||
keep.emplace_back(std::move(client));
|
||||
}
|
||||
clients_ = std::move(keep);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user