Implement autodeletion of players on logout
This commit is contained in:
@@ -34,7 +34,7 @@ public:
|
|||||||
// the invariant that there's always an actor. When the first difference
|
// the invariant that there's always an actor. When the first difference
|
||||||
// transmission arrives, this actor may be deleted, or it may just be
|
// transmission arrives, this actor may be deleted, or it may just be
|
||||||
// ignored, at the server's discretion.
|
// ignored, at the server's discretion.
|
||||||
actor_id_ = world_->create_login_actor(false);
|
actor_id_ = world_->create_login_actor();
|
||||||
|
|
||||||
// Clear the unack command queue.
|
// Clear the unack command queue.
|
||||||
unack_.clear();
|
unack_.clear();
|
||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
channel_.reset();
|
channel_.reset();
|
||||||
|
|
||||||
// Create the standalone actor.
|
// Create the standalone actor.
|
||||||
actor_id_ = world_->create_login_actor(true);
|
actor_id_ = world_->create_login_actor();
|
||||||
|
|
||||||
// TODO: initialize the standalone actor.
|
// TODO: initialize the standalone actor.
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
master_->update_source(srcpk);
|
master_->update_source(srcpk);
|
||||||
|
|
||||||
// Create an actor for administrative commands.
|
// Create an actor for administrative commands.
|
||||||
admin_id_ = master_->create_login_actor(true);
|
admin_id_ = master_->create_login_actor();
|
||||||
|
|
||||||
// TODO: initialize the admin actor.
|
// TODO: initialize the admin actor.
|
||||||
|
|
||||||
@@ -132,6 +132,7 @@ public:
|
|||||||
|
|
||||||
void delete_client(UniqueClient &client) {
|
void delete_client(UniqueClient &client) {
|
||||||
stdostream() << "Client closed: actor id=" << client->actor_id_ << std::endl;
|
stdostream() << "Client closed: actor id=" << client->actor_id_ << std::endl;
|
||||||
|
master_->disconnected(client->actor_id_);
|
||||||
client.reset();
|
client.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +210,7 @@ public:
|
|||||||
if (chan == nullptr) break;
|
if (chan == nullptr) break;
|
||||||
if (chan->port() == 8085) {
|
if (chan->port() == 8085) {
|
||||||
Client *client = new Client;
|
Client *client = new Client;
|
||||||
client->actor_id_ = master_->create_login_actor(true);
|
client->actor_id_ = master_->create_login_actor();
|
||||||
// TODO: initialize the login actor on the master.
|
// TODO: initialize the login actor on the master.
|
||||||
client->channel_ = std::move(chan);
|
client->channel_ = std::move(chan);
|
||||||
client->async_diff_ = true;
|
client->async_diff_ = true;
|
||||||
@@ -217,7 +218,7 @@ public:
|
|||||||
client->sync_.reset(new World(WORLD_TYPE_PREDICTIVE));
|
client->sync_.reset(new World(WORLD_TYPE_PREDICTIVE));
|
||||||
// This login actor is never used, it is just to preserve the invariant that
|
// This login actor is never used, it is just to preserve the invariant that
|
||||||
// the client model and the server synchronous model are identical.
|
// the client model and the server synchronous model are identical.
|
||||||
client->sync_->create_login_actor(false);
|
client->sync_->create_login_actor();
|
||||||
clients_.emplace_back(client);
|
clients_.emplace_back(client);
|
||||||
stdostream() << "New client: actor id=" << client->actor_id_ << std::endl;
|
stdostream() << "New client: actor id=" << client->actor_id_ << std::endl;
|
||||||
} else if (chan->port() == 8080) {
|
} else if (chan->port() == 8080) {
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_
|
|||||||
assert (t == nullptr);
|
assert (t == nullptr);
|
||||||
t.reset(new Tangible(this, id));
|
t.reset(new Tangible(this, id));
|
||||||
|
|
||||||
|
// Set the login flags.
|
||||||
|
t->can_be_controlled_ = false;
|
||||||
|
t->is_controlled_ = false;
|
||||||
|
t->force_disconnect_ = false;
|
||||||
|
t->delete_on_disconnect_ = false;
|
||||||
|
|
||||||
// AnimQueue initializes itself to a valid default state.
|
// AnimQueue initializes itself to a valid default state.
|
||||||
AnimState state;
|
AnimState state;
|
||||||
state.add_defaults(nullptr);
|
state.add_defaults(nullptr);
|
||||||
@@ -246,28 +252,51 @@ World::Redirects World::fetch_redirects() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t World::create_login_actor(bool initialize) {
|
int64_t World::create_login_actor() {
|
||||||
assert(stack_is_clear());
|
assert(stack_is_clear());
|
||||||
int64_t id = id_global_pool_.get_one();
|
int64_t id = id_global_pool_.get_one();
|
||||||
{
|
{
|
||||||
LuaVar database, classtab, mt, func;
|
LuaVar database, classtab, mt, func;
|
||||||
LuaExtStack LS(state(), database, classtab, mt, func);
|
LuaExtStack LS(state(), database, classtab, mt, func);
|
||||||
Tangible *tan = tangible_make(LS, database, id);
|
Tangible *tan = tangible_make(LS, database, id);
|
||||||
|
|
||||||
|
// Set the login flags.
|
||||||
|
if (is_authoritative()) {
|
||||||
|
tan->can_be_controlled_ = true;
|
||||||
|
tan->is_controlled_ = true;
|
||||||
|
tan->force_disconnect_ = false;
|
||||||
|
tan->delete_on_disconnect_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
LS.makeclass(classtab, "login");
|
LS.makeclass(classtab, "login");
|
||||||
LS.getmetatable(mt, database);
|
LS.getmetatable(mt, database);
|
||||||
LS.rawset(mt, "__index", classtab);
|
LS.rawset(mt, "__index", classtab);
|
||||||
tan->configure_id_pool_for_actor();
|
tan->configure_id_pool_for_actor();
|
||||||
tan->print_buffer_.clear();
|
tan->print_buffer_.clear();
|
||||||
|
|
||||||
if (initialize) {
|
if (is_authoritative()) {
|
||||||
LS.rawget(func, classtab, "initialize");
|
LS.rawget(func, classtab, "initialize");
|
||||||
spawn(LS, id, id, func, true, 0, false);
|
spawn(LS, id, id, func, true, 0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_authoritative()) {
|
||||||
run_scheduled_threads();
|
run_scheduled_threads();
|
||||||
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::disconnected(int64_t actor_id) {
|
||||||
|
Tangible *tan = tangible_get(actor_id);
|
||||||
|
assert(tan != nullptr);
|
||||||
|
assert(tan->is_controlled_);
|
||||||
|
tan->is_controlled_ = false;
|
||||||
|
tan->force_disconnect_ = false;
|
||||||
|
if (tan->delete_on_disconnect_) {
|
||||||
|
util::dprintf("Deleted actor: %lld\n", actor_id);
|
||||||
|
tangible_delete(actor_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eng::string World::probe_lua(int64_t actor_id, std::string_view lua) {
|
eng::string World::probe_lua(int64_t actor_id, std::string_view lua) {
|
||||||
assert(stack_is_clear());
|
assert(stack_is_clear());
|
||||||
lua_State *L = state();
|
lua_State *L = state();
|
||||||
|
|||||||
@@ -76,6 +76,39 @@ public:
|
|||||||
//
|
//
|
||||||
PrintBuffer print_buffer_;
|
PrintBuffer print_buffer_;
|
||||||
|
|
||||||
|
// Can-Be-Controlled flag.
|
||||||
|
//
|
||||||
|
// This flag indicates whether the tangible can be controlled
|
||||||
|
// by a client. Clients will not be allowed to attach to tangibles
|
||||||
|
// who don't have this flag. If this flag is true, the
|
||||||
|
// tangible cannot be deleted using a mere 'tangible.delete', instead,
|
||||||
|
// you have to use 'tangible.deleteplayer'.
|
||||||
|
//
|
||||||
|
bool can_be_controlled_;
|
||||||
|
|
||||||
|
// Is Controlled Flag.
|
||||||
|
//
|
||||||
|
// This flag is set to true when a client is controlling this player.
|
||||||
|
// It gets set back to false when the client logs out or attaches
|
||||||
|
// to a different player. This can only be set in master models.
|
||||||
|
//
|
||||||
|
bool is_controlled_;
|
||||||
|
|
||||||
|
// Force disconnect flag.
|
||||||
|
//
|
||||||
|
// This flag is used to force the client to log out ASAP. This flag
|
||||||
|
// can only be set in master models.
|
||||||
|
//
|
||||||
|
bool force_disconnect_;
|
||||||
|
|
||||||
|
// Delete on Logout Flag.
|
||||||
|
//
|
||||||
|
// This flag can be set on a controlled player. When the player
|
||||||
|
// disconnects, their character will be deleted. This flag can only
|
||||||
|
// be set if the is_controlled_ flag is true.
|
||||||
|
//
|
||||||
|
bool delete_on_disconnect_;
|
||||||
|
|
||||||
// constructor.
|
// constructor.
|
||||||
//
|
//
|
||||||
Tangible(World *w, int64_t id);
|
Tangible(World *w, int64_t id);
|
||||||
@@ -184,10 +217,20 @@ public:
|
|||||||
// This is used to create a temporary actor which is used during
|
// This is used to create a temporary actor which is used during
|
||||||
// the login process.
|
// the login process.
|
||||||
//
|
//
|
||||||
// If initialize is true, then the function 'login.initialize'
|
// If this is a master model, The function 'login.initialize'
|
||||||
// will be executed.
|
// called. Then, the following login flags are set:
|
||||||
|
// can_be_controlled, is_controlled, and delete_on_disconnect.
|
||||||
//
|
//
|
||||||
int64_t create_login_actor(bool initialize);
|
// In a client model, 'login.initialize' is not called,
|
||||||
|
// and the login flags are not used in client models.
|
||||||
|
//
|
||||||
|
int64_t create_login_actor();
|
||||||
|
|
||||||
|
// Log out a connected player.
|
||||||
|
//
|
||||||
|
// This is to be called after a client disconnects.
|
||||||
|
//
|
||||||
|
void disconnected(int64_t actor_id);
|
||||||
|
|
||||||
// Fetch all redirects and clear the redirects table.
|
// Fetch all redirects and clear the redirects table.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user