More work on redirect
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
class Client : public eng::opnew {
|
||||
public:
|
||||
int64_t client_id_;
|
||||
int64_t actor_id_;
|
||||
SharedChannel channel_;
|
||||
UniqueWorld sync_;
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
world_->expose_world_to_driver(wrapper_);
|
||||
|
||||
// Create the admin actor. Note: there isn't any 'init' function yet.
|
||||
actor_id_ = world_->create_login_actor();
|
||||
actor_id_ = world_->connection_create();
|
||||
|
||||
// Print out admin ID for debugging purposes.
|
||||
util::dprint("Admin actor id = ", actor_id_);
|
||||
@@ -73,12 +74,13 @@ public:
|
||||
}
|
||||
|
||||
void delete_client(UniqueClient &client) {
|
||||
util::dprint("Client closed: actor id=", client->actor_id_);
|
||||
world_->disconnected(client->actor_id_);
|
||||
util::dprint("Client closed: client_id=", client->client_id_, " actor_id=", client->actor_id_);
|
||||
world_->connection_delete(client->client_id_);
|
||||
client.reset();
|
||||
}
|
||||
|
||||
void send_diffs(UniqueClient &client, bool full) {
|
||||
client->actor_id_ = world_->connection_get_actor(client->client_id_);
|
||||
StreamBuffer *sb = client->channel_->out();
|
||||
sb->write_uint8(util::MSG_DIFF);
|
||||
sb->write_uint32(0);
|
||||
@@ -89,27 +91,6 @@ public:
|
||||
sb->overwrite_int32(tw_1, tw_2 - tw_1);
|
||||
}
|
||||
|
||||
void redirect(int64_t id1, int64_t id2) {
|
||||
for (auto &client : clients_) {
|
||||
if (client->actor_id_ == id1) {
|
||||
bool ok = world_->redirected(id1, id2);
|
||||
if (!ok) delete_client(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redirection is touchy: almost any world->invoke could
|
||||
// call tangible.redirect. After that point, the world is
|
||||
// relying on us not to control the wrong character.
|
||||
void process_redirects() {
|
||||
if (world_->have_redirects()) {
|
||||
World::Redirects redirects = world_->fetch_redirects();
|
||||
for (const auto &pair : redirects) {
|
||||
redirect(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_invocation(UniqueClient &client) {
|
||||
if (client == nullptr) return false;
|
||||
StreamBuffer *sb = client->channel_->in();
|
||||
@@ -131,18 +112,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the user sent an invalid kind, log them out.
|
||||
if (!Invocation::is_valid_network_kind(inv.kind())) {
|
||||
delete_client(client);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acknowledge the invocation.
|
||||
client->channel_->out()->write_uint8(util::MSG_ACK);
|
||||
client->channel_->out()->write_uint32(0);
|
||||
|
||||
// Execute the invocation with the sync model.
|
||||
client->sync_->invoke(inv);
|
||||
client->sync_->invoke(0, inv);
|
||||
client->async_diff_ = true;
|
||||
|
||||
// Process the invocation in the master model.
|
||||
@@ -152,8 +127,7 @@ public:
|
||||
// who may not know their new actor_id yet.
|
||||
//
|
||||
if (inv.actor() == client->actor_id_) {
|
||||
world_->invoke(inv);
|
||||
process_redirects();
|
||||
world_->invoke(client->client_id_, inv);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -210,7 +184,7 @@ public:
|
||||
// come from the local command line. We just feed
|
||||
// these directly into the master model.
|
||||
for (const Invocation &inv : delayed_invocations_) {
|
||||
world_->invoke(inv);
|
||||
world_->invoke(0, inv);
|
||||
}
|
||||
delayed_invocations_.clear();
|
||||
|
||||
@@ -220,7 +194,8 @@ public:
|
||||
if (chan == nullptr) break;
|
||||
if (chan->port() == 8085) {
|
||||
Client *client = new Client;
|
||||
client->actor_id_ = world_->create_login_actor();
|
||||
client->actor_id_ = world_->connection_create();
|
||||
client->client_id_ = client->actor_id_;
|
||||
// TODO: initialize the login actor on the master.
|
||||
client->channel_ = std::move(chan);
|
||||
client->async_diff_ = true;
|
||||
@@ -229,7 +204,7 @@ public:
|
||||
client->sync_.reset(new World(WORLD_TYPE_PREDICTIVE));
|
||||
// This login actor is never used, it is just to preserve the invariant that
|
||||
// the client model and the server synchronous model are identical.
|
||||
client->sync_->create_login_actor();
|
||||
client->sync_->connection_create();
|
||||
clients_.emplace_back(client);
|
||||
util::dprint("New client: actor id=", client->actor_id_);
|
||||
} else if (chan->port() == 8080) {
|
||||
@@ -241,7 +216,7 @@ public:
|
||||
|
||||
// If the clock has advanced far enough, tick the master model.
|
||||
if (clock >= next_tick_) {
|
||||
world_->invoke(Invocation(AccessKind::INVOKE_TICK, 0, 0, ""));
|
||||
world_->invoke(0, Invocation(AccessKind::INVOKE_TICK, 0, 0, ""));
|
||||
for (UniqueClient &client : clients_) {
|
||||
client->async_diff_ = true;
|
||||
}
|
||||
@@ -249,11 +224,6 @@ public:
|
||||
if (next_tick_ < clock + 0.3) next_tick_ = clock + 0.3;
|
||||
}
|
||||
|
||||
// This handles any redirects triggered from the server command
|
||||
// line or by the tick function.
|
||||
process_redirects();
|
||||
util::remove_nullptrs(clients_);
|
||||
|
||||
// Traverse all existing channels, process any communication.
|
||||
for (UniqueClient &client : clients_) {
|
||||
if (client->channel_->closed()) {
|
||||
|
||||
Reference in New Issue
Block a user