More work on redirect
This commit is contained in:
@@ -152,12 +152,20 @@ 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_);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -294,13 +302,7 @@ void World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool
|
||||
get_near(scan, into);
|
||||
}
|
||||
|
||||
World::Redirects World::fetch_redirects() {
|
||||
World::Redirects result = std::move(redirects_);
|
||||
redirects_.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t World::create_login_actor() {
|
||||
int64_t World::connection_create() {
|
||||
assert(stack_is_clear());
|
||||
int64_t id = id_global_pool_.get_one();
|
||||
{
|
||||
@@ -327,13 +329,18 @@ int64_t World::create_login_actor() {
|
||||
spawn(LS, id, id, func, 0, false);
|
||||
}
|
||||
}
|
||||
connections_.emplace(id, id);
|
||||
if (is_authoritative()) {
|
||||
run_scheduled_threads();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void World::disconnected(int64_t actor_id) {
|
||||
eng::string World::connection_delete(int64_t client_id) {
|
||||
auto iter = connections_.find(client_id);
|
||||
if (iter == connections_.end()) return "no such client id";
|
||||
int64_t actor_id = iter->second;
|
||||
connections_.erase(iter);
|
||||
Tangible *tan = tangible_get(actor_id);
|
||||
assert(tan != nullptr);
|
||||
assert(tan->is_controlled_);
|
||||
@@ -343,16 +350,39 @@ void World::disconnected(int64_t actor_id) {
|
||||
util::dprintf("Deleted actor: %lld\n", actor_id);
|
||||
tangible_delete(actor_id);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool World::redirected(int64_t actor_id, int64_t new_id) {
|
||||
disconnected(actor_id);
|
||||
Tangible *tan = tangible_get(new_id);
|
||||
if (tan && (tan->can_be_controlled_) && (!tan->is_controlled_)) {
|
||||
tan->is_controlled_ = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
int64_t World::connection_get_client(int64_t actor_id) const {
|
||||
for (const auto &pair : connections_) {
|
||||
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;
|
||||
return "";
|
||||
}
|
||||
|
||||
void World::connection_close_all() {
|
||||
while (!connections_.empty()) {
|
||||
int64_t client_id = connections_.begin()->first;
|
||||
connection_delete(client_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,6 +594,7 @@ bool World::rebuild_sourcedb(int64_t actor_id) {
|
||||
if (actor_id != 0) lthread_prints_to_actor(actor_id);
|
||||
}
|
||||
}
|
||||
source_db_.rebuild_funcnames();
|
||||
lthread_prints_ << "Compiled " << successes << " modules successfully." << std::endl;
|
||||
if (failures > 0) {
|
||||
lthread_prints_ << "Compiled " << failures << " modules with errors." << std::endl;
|
||||
@@ -743,7 +774,13 @@ HttpServerResponse World::http_serve(const HttpParser &request) {
|
||||
return response;
|
||||
}
|
||||
|
||||
void World::invoke(const Invocation &inv) {
|
||||
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;
|
||||
if (inv.actor() != actor_id) return;
|
||||
if (!Invocation::is_valid_network_kind(inv.kind())) return;
|
||||
}
|
||||
switch (inv.kind()) {
|
||||
case AccessKind::INVOKE_LUA_CALL:
|
||||
invoke_lua_call(inv.actor(), inv.place(), inv.datapack());
|
||||
@@ -838,7 +875,7 @@ bool World::spawn(LuaCoreStack &LS0, int64_t actor_id, int64_t place_id, LuaSlot
|
||||
LS.rawset(thinfo, "isnew", true);
|
||||
LS.rawset(thinfo, "useppool", true);
|
||||
LS.rawset(thinfo, "print", print);
|
||||
|
||||
|
||||
// Store the thread into place's thread table.
|
||||
LS.rawget(threads, mt, "threads");
|
||||
if (!LS.istable(threads)) {
|
||||
@@ -1230,7 +1267,6 @@ const eng::string &World::get_global(const eng::string &gvar) {
|
||||
|
||||
void World::serialize(StreamBuffer *sb) {
|
||||
assert(stack_is_clear());
|
||||
assert(redirects_.empty());
|
||||
// int64_t wc0 = sb->total_writes();
|
||||
lua_snap_.serialize(sb);
|
||||
id_global_pool_.serialize(sb);
|
||||
@@ -1242,12 +1278,16 @@ void World::serialize(StreamBuffer *sb) {
|
||||
sb->write_int64(p.first);
|
||||
p.second->serialize(sb);
|
||||
}
|
||||
sb->write_uint32(connections_.size());
|
||||
for (const auto &p : connections_) {
|
||||
sb->write_int64(p.first);
|
||||
sb->write_int64(p.second);
|
||||
}
|
||||
assert(stack_is_clear());
|
||||
}
|
||||
|
||||
void World::deserialize(StreamBuffer *sb) {
|
||||
assert(stack_is_clear());
|
||||
redirects_.clear();
|
||||
lua_snap_.deserialize(sb);
|
||||
id_global_pool_.deserialize(sb);
|
||||
clock_ = sb->read_int64();
|
||||
@@ -1259,7 +1299,7 @@ void World::deserialize(StreamBuffer *sb) {
|
||||
}
|
||||
// Deserialize tangibles.
|
||||
size_t ntan = sb->read_uint32();
|
||||
for (size_t i = 0; i < ntan; i++) {
|
||||
for (uint32_t i = 0; i < ntan; i++) {
|
||||
int64_t id = sb->read_int64();
|
||||
UniqueTangible &t = tangibles_[id];
|
||||
if (t == nullptr) {
|
||||
@@ -1269,6 +1309,14 @@ void World::deserialize(StreamBuffer *sb) {
|
||||
}
|
||||
t->deserialize(sb);
|
||||
}
|
||||
// Deserialize connections.
|
||||
connections_.clear();
|
||||
uint32_t nconn = sb->read_uint32();
|
||||
for (uint32_t i = 0; i < nconn; i++) {
|
||||
int64_t client_id = sb->read_int64();
|
||||
int64_t actor_id = sb->read_int64();
|
||||
connections_.emplace(client_id, actor_id);
|
||||
}
|
||||
// Delete tangibles that didn't get deserialized.
|
||||
for (auto iter = tangibles_.begin(); iter != tangibles_.end(); ) {
|
||||
if (iter->second->plane_item_.id() == 0) {
|
||||
@@ -1277,8 +1325,6 @@ void World::deserialize(StreamBuffer *sb) {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
// After a save and load, http requests no longer should exist
|
||||
abort_all_http_requests(425, "http requests aborted by loading a save game");
|
||||
assert(stack_is_clear());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user