Working on redirect/connect/etc

This commit is contained in:
2026-06-05 17:52:46 -04:00
parent 8a46788512
commit 8d88c88fa0
5 changed files with 117 additions and 106 deletions

View File

@@ -152,9 +152,7 @@ void Tangible::serialize(StreamBuffer *sb) {
anim_queue_.serialize(sb);
id_player_pool_.serialize(sb);
print_buffer_.serialize(sb);
sb->write_bool(can_be_controlled_);
sb->write_bool(is_controlled_);
sb->write_bool(force_disconnect_);
sb->write_bool(delete_on_disconnect_);
}
@@ -162,9 +160,7 @@ void Tangible::deserialize(StreamBuffer *sb) {
anim_queue_.deserialize(sb);
id_player_pool_.deserialize(sb);
print_buffer_.deserialize(sb);
can_be_controlled_ = sb->read_bool();
is_controlled_ = sb->read_bool();
force_disconnect_ = sb->read_bool();
delete_on_disconnect_ = sb->read_bool();
update_plane_item();
}
@@ -220,9 +216,7 @@ Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_
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.
@@ -302,6 +296,12 @@ void World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool
get_near(scan, into);
}
void World::connection_prepare(Tangible *tan) {
tan->configure_id_pool_for_actor();
tan->print_buffer_.clear();
}
int64_t World::connection_create() {
assert(stack_is_clear());
int64_t id = id_global_pool_.get_one();
@@ -312,17 +312,14 @@ int64_t World::connection_create() {
// 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.getmetatable(mt, database);
LS.rawset(mt, "__index", classtab);
tan->configure_id_pool_for_actor();
tan->print_buffer_.clear();
connection_prepare(tan);
if (is_authoritative()) {
LS.rawget(func, classtab, "init");
@@ -336,46 +333,63 @@ int64_t World::connection_create() {
return id;
}
eng::string World::connection_delete(int64_t client_id) {
void World::connection_delete(int64_t client_id) {
auto iter = connections_.find(client_id);
if (iter == connections_.end()) return "no such 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;
tan->force_disconnect_ = false;
if (tan->delete_on_disconnect_) {
util::dprintf("Deleted actor: %lld\n", actor_id);
tangible_delete(actor_id);
}
return "";
}
int64_t World::connection_get_actor(int64_t client_id) const {
auto iter = connections_.find(client_id);
if (iter == connections_.end()) return 0;
return iter->second;
if (iter != connections_.end()) return iter->second;
return 0;
}
int64_t World::connection_get_client(int64_t actor_id) const {
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;
if (pair.second == actor->id()) return pair.first;
}
return 0;
}
eng::string World::connection_redirect(int64_t client_id, int64_t new_id) {
Tangible *newtan = tangible_get(new_id);
if (newtan == nullptr) return "no such target tangible";
if (newtan->is_controlled_) return "target tangible is already controlled";
if (!newtan->can_be_controlled_) return "target tangible is not a potential actor";
eng::string delresult = connection_delete(client_id);
if (!delresult.empty()) return delresult;
newtan->is_controlled_ = true;
newtan->force_disconnect_ = false;
connections_[client_id] = new_id;
eng::string World::connection_redirect(Tangible *actor1, Tangible *actor2) {
if (actor1 == actor2) return "";
if (!actor1->is_controlled_) {
return "actor1 is not logged in, cannot redirect";
}
// 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);
}
int64_t client_id1 = connection_get_client(actor1);
actor1->is_controlled_ = false;
connections_.erase(client_id1);
if (actor1->delete_on_disconnect_) {
tangible_delete(actor1->id());
}
if (actor2 != nullptr) {
connection_prepare(actor2);
actor2->is_controlled_ = true;
connections_[client_id1] = actor2->id();
}
return "";
}
@@ -781,8 +795,9 @@ HttpServerResponse World::http_serve(const HttpParser &request) {
void World::invoke(int64_t client_id, const Invocation &inv) {
if (client_id != 0) {
int64_t actor_id = connection_get_actor(client_id);
if (actor_id == 0) return;
auto iter = connections_.find(client_id);
if (iter == connections_.end()) return;
int64_t actor_id = iter->second;
if (inv.actor() != actor_id) return;
if (!Invocation::is_valid_network_kind(inv.kind())) return;
}