diff --git a/Config/DefaultEditorPerProjectUserSettings.ini b/Config/DefaultEditorPerProjectUserSettings.ini index 7b233817..73a0d865 100644 --- a/Config/DefaultEditorPerProjectUserSettings.ini +++ b/Config/DefaultEditorPerProjectUserSettings.ini @@ -13,5 +13,5 @@ RestoreOpenAssetTabsOnRestart=AlwaysRestore AutoSaveWarningInSeconds=0 [/Script/Integration.lxProjectSettings] -ActiveServer=/Game/Luprex/KnownServers/SS_Standalone.SS_Standalone +ActiveServer=/Game/Luprex/KnownServers/SS_Localhost.SS_Localhost diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index 30ecbec2..5b9de453 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -282,8 +282,6 @@ LuaDefine(tangible_getclass, "tan", LuaDefine(tangible_delete, "tan", "|Delete the specified tangible." "|" - "|This cannot be used to delete actor tangibles," - "|To delete a actor, use tangible.deleteactor" "|") { LuaArg tanobj; LuaDefStack LS(L, tanobj); @@ -293,12 +291,7 @@ LuaDefine(tangible_delete, "tan", luaL_error(L, "Not a tangible."); return 0; } - if (tan->is_controlled_) { - tan->delete_on_disconnect_ = true; - w->connection_redirect(tan, nullptr); - } else { - w->tangible_delete(tan->id()); - } + w->tangible_delete(tan->id()); return LS.result(); } @@ -324,10 +317,6 @@ LuaDefine(tangible_keepactor, "tan", LuaDefStack LS(L, tanobj); World *w = World::fetch_global_pointer(L); Tangible *tan = w->tangible_get(LS, tanobj, true); - if ((tan == nullptr) || (!tan->is_controlled_)) { - luaL_error(L, "Tangible is not an actor."); - return 0; - } tan->delete_on_disconnect_ = false; return LS.result(); } @@ -352,13 +341,11 @@ LuaDefine(tangible_redirect, "actor1, actor2", World *w = World::fetch_global_pointer(L); Tangible *actor1 = w->tangible_get(LS, lactor1, true); Tangible *actor2 = w->tangible_get(LS, lactor2, true); - eng::string error = w->connection_redirect(actor1, actor2); - if (!error.empty()) { - eng::ostringstream oss; - oss << "redirect from " << actor1->id() << " to " << actor2->id() << " failed: " << error; - luaL_error(L, "%s", oss.str().c_str()); + if (actor1->client_id_ == 0) { + luaL_error(L, "actor1 is not currently logged in."); return LS.result(); } + w->connection_redirect(actor1, actor2); return LS.result(); } @@ -371,14 +358,8 @@ LuaDefine(tangible_forcedisconnect, "actor", LuaDefStack LS(L, lactor1, lactor2); World *w = World::fetch_global_pointer(L); Tangible *actor = w->tangible_get(LS, lactor1, true); - if (actor->is_controlled_) { - eng::string error = w->connection_redirect(actor, nullptr); - if (!error.empty()) { - eng::ostringstream oss; - oss << "forcedisconnect of " << actor->id() << " failed: " << error; - luaL_error(L, "%s", oss.str().c_str()); - return LS.result(); - } + if (actor->client_id_ != 0) { + w->connection_delete(actor->client_id_); } return LS.result(); } diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 09400606..7dbddfa0 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -152,7 +152,7 @@ void Tangible::serialize(StreamBuffer *sb) { anim_queue_.serialize(sb); id_player_pool_.serialize(sb); print_buffer_.serialize(sb); - sb->write_bool(is_controlled_); + sb->write_int64(client_id_); sb->write_bool(delete_on_disconnect_); } @@ -160,7 +160,7 @@ void Tangible::deserialize(StreamBuffer *sb) { anim_queue_.deserialize(sb); id_player_pool_.deserialize(sb); print_buffer_.deserialize(sb); - is_controlled_ = sb->read_bool(); + client_id_ = sb->read_int64(); delete_on_disconnect_ = sb->read_bool(); update_plane_item(); } @@ -216,7 +216,7 @@ Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_ t.reset(new Tangible(this, id)); // Set the login flags. - t->is_controlled_ = false; + t->client_id_ = 0; t->delete_on_disconnect_ = false; // AnimQueue initializes itself to a valid default state. @@ -252,6 +252,7 @@ void World::tangible_delete(int64_t id) { if (iter == tangibles_.end()) { return; // Nothing to delete. } + Tangible *tan = iter->second.get(); // Fetch the lua side of the tangible. LS.maketan(database, id); @@ -266,6 +267,9 @@ void World::tangible_delete(int64_t id) { LS.rawset(metatab, "id", id); LS.rawset(metatab, "__metatable", false); + // If the tangible is in the connections table, remove it. + if (tan->client_id_ != 0) connections_.erase(tan->client_id_); + // Remove the C++ portion from the tangibles table. tangibles_.erase(iter); } @@ -312,7 +316,7 @@ int64_t World::connection_create() { // Set the login flags. if (is_authoritative()) { - tan->is_controlled_ = true; + tan->client_id_ = id; tan->delete_on_disconnect_ = true; } @@ -337,11 +341,11 @@ void World::connection_delete(int64_t client_id) { auto iter = connections_.find(client_id); if (iter == connections_.end()) return; int64_t actor_id = iter->second; - connections_.erase(iter); Tangible *tan = tangible_get(actor_id); assert(tan != nullptr); - assert(tan->is_controlled_); - tan->is_controlled_ = false; + assert(tan->client_id_ == client_id); + connections_.erase(iter); + tan->client_id_ = 0; if (tan->delete_on_disconnect_) { util::dprintf("Deleted actor: %lld\n", actor_id); tangible_delete(actor_id); @@ -354,32 +358,22 @@ int64_t World::connection_get_actor(int64_t client_id) const { return 0; } -int64_t World::connection_get_client(Tangible *actor) const { - if (!actor->is_controlled_) return 0; - for (const auto &pair : connections_) { - if (pair.second == actor->id()) return pair.first; - } - return 0; -} -eng::string World::connection_redirect(Tangible *actor1, Tangible *actor2) { - if (actor1 == actor2) return ""; +void World::connection_redirect(Tangible *actor1, Tangible *actor2) { + if ((actor1 == nullptr) || (actor2 == nullptr) || (actor1 == actor2)) return; - if (!actor1->is_controlled_) { - return "actor1 is not logged in, cannot redirect"; - } + int64_t client_id1 = actor1->client_id_; + if (client_id1 == 0) return; // If neccessary, bump actor2. Do not implement delete-on-disconnect, // because actor2 isn't really "disconnected" yet. - if ((actor2 != nullptr) && (actor2->is_controlled_)) { - int64_t client_id2 = connection_get_client(actor2); - actor2->is_controlled_ = false; - connections_.erase(client_id2); + if ((actor2 != nullptr) && (actor2->client_id_ != 0)) { + connections_.erase(actor2->client_id_); + actor2->client_id_ = 0; } - int64_t client_id1 = connection_get_client(actor1); - actor1->is_controlled_ = false; - connections_.erase(client_id1); + connections_.erase(actor1->client_id_); + actor1->client_id_ = 0; if (actor1->delete_on_disconnect_) { tangible_delete(actor1->id()); @@ -387,10 +381,9 @@ eng::string World::connection_redirect(Tangible *actor1, Tangible *actor2) { if (actor2 != nullptr) { connection_prepare(actor2); - actor2->is_controlled_ = true; + actor2->client_id_ = client_id1; connections_[client_id1] = actor2->id(); } - return ""; } void World::connection_close_all() { diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index 281d61f0..418f48ef 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -78,14 +78,13 @@ public: // PrintBuffer print_buffer_; - // Is Controlled Flag. + // Client ID // - // 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. If this is set, then the connections_ - // table contains a map from a client ID to this actor. + // This variable is set to nonzero when a client is controlling this + // player. If this is set, then the connections_ table contains a map + // from a client ID to this actor. // - bool is_controlled_; + int64_t client_id_ = 0; // Delete on Logout Flag. // @@ -421,23 +420,17 @@ public: // Find out what actor the given client is controlling. // // This is used by the DrivenEngine to check if the given client has - // changed actor, or if it has been forced to disconnect. + // changed actor, or if it has been forced to disconnect. Returns + // zero if the client is not controlling anything. // int64_t connection_get_actor(int64_t client_id) const; - // Connection get client. - // - // Get the ID of the client that is controlling the specified actor. - // - int64_t connection_get_client(Tangible *tan) const; - // Connection redirection. // - // This is used by lua code to force changes in connection status. - // It can be used to redirect a client, or disconnect a client - // if actor2 == nullptr. + // This is used by lua code to cause the client who is controlling + // actor1 to control actor2 instead. // - eng::string connection_redirect(Tangible *actor1, Tangible *actor2); + void connection_redirect(Tangible *actor1, Tangible *actor2); // Close all connections. //