2021-09-10 17:06:07 -04:00
|
|
|
#include "world.hpp"
|
2021-10-25 14:47:37 -04:00
|
|
|
#include <iostream>
|
2021-09-10 17:06:07 -04:00
|
|
|
|
|
|
|
|
util::IdVector World::get_visible_union(int64_t actor_id, World *master) {
|
|
|
|
|
return util::sort_union_id_vectors(
|
|
|
|
|
master->get_near_unsorted(actor_id, RadiusVisibility, true),
|
|
|
|
|
get_near_unsorted(actor_id, RadiusVisibility, true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t World::patch_actor(StreamBuffer *sb) {
|
|
|
|
|
int64_t actor_id = sb->read_int64();
|
|
|
|
|
Tangible *s_actor = tangible_get(actor_id);
|
|
|
|
|
if (s_actor == nullptr) {
|
|
|
|
|
s_actor = tangible_make(nullptr, actor_id, "", false);
|
|
|
|
|
s_actor->id_player_pool_.deserialize(sb);
|
|
|
|
|
s_actor->anim_queue_.deserialize(sb);
|
2021-11-14 15:57:18 -05:00
|
|
|
s_actor->print_buffer_.deserialize(sb);
|
2021-09-10 17:06:07 -04:00
|
|
|
} else {
|
|
|
|
|
s_actor->id_player_pool_.patch(sb);
|
|
|
|
|
s_actor->anim_queue_.patch(sb);
|
2021-11-14 15:57:18 -05:00
|
|
|
s_actor->print_buffer_.patch(sb);
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|
|
|
|
|
s_actor->update_plane_item();
|
|
|
|
|
return actor_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_actor(int64_t actor_id, World *master, StreamBuffer *xsb) {
|
|
|
|
|
StreamBuffer tsb;
|
|
|
|
|
|
|
|
|
|
// Get the actor in both models. s_actor may be nil.
|
|
|
|
|
const Tangible *s_actor = tangible_get(actor_id);
|
|
|
|
|
const Tangible *m_actor = master->tangible_get(actor_id);
|
|
|
|
|
assert(m_actor != nullptr);
|
|
|
|
|
|
|
|
|
|
// Calculate diffs.
|
|
|
|
|
tsb.write_int64(actor_id);
|
|
|
|
|
if (s_actor == nullptr) {
|
|
|
|
|
m_actor->id_player_pool_.serialize(&tsb);
|
|
|
|
|
m_actor->anim_queue_.serialize(&tsb);
|
2021-11-14 15:57:18 -05:00
|
|
|
m_actor->print_buffer_.serialize(&tsb);
|
2021-09-10 17:06:07 -04:00
|
|
|
} else {
|
|
|
|
|
s_actor->id_player_pool_.diff(m_actor->id_player_pool_, &tsb);
|
|
|
|
|
s_actor->anim_queue_.diff(m_actor->anim_queue_, &tsb);
|
2021-11-14 15:57:18 -05:00
|
|
|
s_actor->print_buffer_.diff(m_actor->print_buffer_, &tsb);
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Forward to client, and apply to server-synchronous.
|
|
|
|
|
tsb.copy_into(xsb);
|
|
|
|
|
patch_actor(&tsb);
|
2021-10-07 14:58:20 -04:00
|
|
|
assert(tsb.empty());
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::patch_visible(StreamBuffer *sb) {
|
|
|
|
|
// Receive create messages.
|
|
|
|
|
int count = sb->read_int32();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
int64_t id = sb->read_int64();
|
|
|
|
|
Tangible *t = tangible_make(state(), id, "", false);
|
|
|
|
|
t->anim_queue_.deserialize(sb);
|
|
|
|
|
t->update_plane_item();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Receive delete messages
|
|
|
|
|
count = sb->read_int32();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
int64_t id = sb->read_int64();
|
|
|
|
|
tangible_delete(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Receive update messages
|
|
|
|
|
count = sb->read_int32();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
int64_t id = sb->read_int64();
|
|
|
|
|
Tangible *t = tangible_get(id);
|
|
|
|
|
assert(t != nullptr);
|
|
|
|
|
t->anim_queue_.patch(sb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_visible(const util::IdVector &visible, World *master, StreamBuffer *xsb) {
|
|
|
|
|
StreamBuffer tsb;
|
|
|
|
|
|
|
|
|
|
// Get the specified tangibles in both models.
|
|
|
|
|
// Some tangibles may be missing in the master, some may be missing in the sync.
|
|
|
|
|
TanVector mvis = master->tangible_get_all(visible);
|
|
|
|
|
TanVector svis = tangible_get_all(visible);
|
|
|
|
|
assert(mvis.size() == svis.size());
|
|
|
|
|
|
|
|
|
|
// For each tangible that exists in the master, but not
|
|
|
|
|
// in the synchronous model, send a create message.
|
|
|
|
|
tsb.write_int32(0);
|
|
|
|
|
int count_pos = tsb.total_writes();
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = 0; i < int(svis.size()); i++) {
|
|
|
|
|
const Tangible *mt = mvis[i];
|
|
|
|
|
const Tangible *st = svis[i];
|
|
|
|
|
if ((st == nullptr) && (mt != nullptr)) {
|
|
|
|
|
count += 1;
|
|
|
|
|
tsb.write_int64(mt->id());
|
|
|
|
|
mt->anim_queue_.serialize(&tsb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tsb.overwrite_int32(count_pos, count);
|
|
|
|
|
|
|
|
|
|
// For each tangible present in the synchronous model that doesn't
|
|
|
|
|
// exist in the master model, send command to delete it.
|
|
|
|
|
tsb.write_int32(0);
|
|
|
|
|
count_pos = tsb.total_writes();
|
|
|
|
|
count = 0;
|
|
|
|
|
for (int i = 0; i < int(svis.size()); i++) {
|
|
|
|
|
const Tangible *mt = mvis[i];
|
|
|
|
|
const Tangible *st = svis[i];
|
|
|
|
|
if ((mt == nullptr) && (st != nullptr)) {
|
|
|
|
|
count += 1;
|
|
|
|
|
tsb.write_int64(st->id());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tsb.overwrite_int32(count_pos, count);
|
|
|
|
|
|
|
|
|
|
// For each tangible present in both models, compare
|
|
|
|
|
// the animation queues.
|
|
|
|
|
tsb.write_int32(0);
|
|
|
|
|
count_pos = tsb.total_writes();
|
|
|
|
|
count = 0;
|
|
|
|
|
for (int i = 0; i < int(svis.size()); i++) {
|
|
|
|
|
const Tangible *mt = mvis[i];
|
|
|
|
|
const Tangible *st = svis[i];
|
|
|
|
|
if ((mt != nullptr) && (st != nullptr)) {
|
|
|
|
|
if (st->anim_queue_.need_patch(mt->anim_queue_)) {
|
|
|
|
|
count++;
|
|
|
|
|
tsb.write_int64(st->id());
|
|
|
|
|
st->anim_queue_.diff(mt->anim_queue_, &tsb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tsb.overwrite_int32(count_pos, count);
|
|
|
|
|
|
|
|
|
|
// Forward to client, and apply to server-synchronous.
|
|
|
|
|
tsb.copy_into(xsb);
|
|
|
|
|
patch_visible(&tsb);
|
2021-10-07 14:58:20 -04:00
|
|
|
assert(tsb.empty());
|
2021-09-10 17:06:07 -04:00
|
|
|
|
|
|
|
|
// Copy the version number from master animqueue to synch animqueue.
|
|
|
|
|
for (int i = 0; i < int(mvis.size()); i++) {
|
|
|
|
|
const Tangible *m_tan = mvis[i];
|
|
|
|
|
if (m_tan != nullptr) {
|
|
|
|
|
Tangible *s_tan = const_cast<Tangible *>(svis[i]);
|
|
|
|
|
if (s_tan == nullptr) {
|
|
|
|
|
s_tan = tangible_get(m_tan->id());
|
|
|
|
|
assert(s_tan != nullptr);
|
|
|
|
|
}
|
|
|
|
|
s_tan->anim_queue_.update_version(m_tan->anim_queue_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::patch_luatabs(StreamBuffer *sb) {
|
|
|
|
|
int64_t actor_id = sb->read_int64();
|
|
|
|
|
util::HashValue closehash = sb->read_hashvalue();
|
|
|
|
|
int ncreate = sb->read_int32();
|
|
|
|
|
util::IdVector closetans = get_near(actor_id, RadiusClose, true);
|
|
|
|
|
assert(closehash == util::hash_id_vector(closetans));
|
|
|
|
|
number_lua_tables(closetans);
|
|
|
|
|
create_new_tables(ncreate);
|
|
|
|
|
patch_tangible_databases(sb);
|
|
|
|
|
patch_numbered_tables(sb);
|
|
|
|
|
unnumber_lua_tables();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_luatabs(int64_t actor_id, World *master, StreamBuffer *xsb) {
|
|
|
|
|
StreamBuffer tsb;
|
|
|
|
|
|
|
|
|
|
// Calculate the set of close tangibles.
|
|
|
|
|
util::IdVector closetans = master->get_near(actor_id, RadiusClose, true);
|
|
|
|
|
assert(get_near(actor_id, RadiusClose, true) == closetans);
|
|
|
|
|
util::HashValue closehash = util::hash_id_vector(closetans);
|
|
|
|
|
|
|
|
|
|
// Number and pair tables in the synchronous and master model.
|
|
|
|
|
number_lua_tables(closetans);
|
|
|
|
|
pair_lua_tables(closetans, master->state());
|
|
|
|
|
int ncreate = number_remaining_tables(closetans, master->state());
|
|
|
|
|
create_new_tables(ncreate);
|
|
|
|
|
|
|
|
|
|
// Difference transmit.
|
|
|
|
|
tsb.write_int64(actor_id);
|
|
|
|
|
tsb.write_hashvalue(closehash);
|
|
|
|
|
tsb.write_int32(ncreate);
|
|
|
|
|
diff_tangible_databases(closetans, master->state(), &tsb);
|
|
|
|
|
diff_numbered_tables(master->state(), &tsb);
|
|
|
|
|
|
|
|
|
|
// Forward to client, and apply to server-synchronous.
|
|
|
|
|
tsb.copy_into(xsb);
|
|
|
|
|
assert(tsb.read_int64() == actor_id);
|
|
|
|
|
assert(tsb.read_hashvalue() == closehash);
|
|
|
|
|
assert(tsb.read_int32() == ncreate);
|
|
|
|
|
patch_tangible_databases(&tsb);
|
|
|
|
|
patch_numbered_tables(&tsb);
|
|
|
|
|
unnumber_lua_tables();
|
2021-10-07 14:58:20 -04:00
|
|
|
assert(tsb.empty());
|
2021-09-10 17:06:07 -04:00
|
|
|
|
|
|
|
|
// Unnumber tables in both models.
|
|
|
|
|
unnumber_lua_tables();
|
|
|
|
|
master->unnumber_lua_tables();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::patch_tanclass(StreamBuffer *sb) {
|
|
|
|
|
lua_State *L = state();
|
|
|
|
|
LuaVar tangibles, tab, meta, sclass;
|
|
|
|
|
LuaStack LS(L, tangibles, tab, meta, sclass);
|
|
|
|
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
|
|
|
|
|
|
|
|
int nmodified = sb->read_int32();
|
|
|
|
|
for (int i = 0; i < nmodified; i++) {
|
|
|
|
|
int64_t id = sb->read_int64();
|
|
|
|
|
LS.rawgeti(tab, tangibles, id);
|
|
|
|
|
assert(LS.istable(tab));
|
|
|
|
|
LS.getmetatable(meta, tab);
|
|
|
|
|
std::string name = sb->read_string();
|
|
|
|
|
if (name == "") {
|
|
|
|
|
LS.rawset(meta, "__index", LuaNil);
|
|
|
|
|
} else {
|
|
|
|
|
LS.makeclass(sclass, name);
|
|
|
|
|
LS.rawset(meta, "__index", sclass);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LS.result();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_tanclass(int64_t actor_id, World *master, StreamBuffer *xsb) {
|
|
|
|
|
StreamBuffer tsb;
|
|
|
|
|
|
|
|
|
|
LuaVar stangibles, mtangibles, stab, mtab, smeta, mmeta, sclass, mclass;
|
|
|
|
|
LuaStack SLS(state(), stangibles, stab, smeta, sclass);
|
|
|
|
|
LuaStack MLS(master->state(), mtangibles, mtab, mmeta, mclass);
|
|
|
|
|
SLS.rawget(stangibles, LuaRegistry, "tangibles");
|
|
|
|
|
MLS.rawget(mtangibles, LuaRegistry, "tangibles");
|
|
|
|
|
|
|
|
|
|
// Calculate the set of close tangibles.
|
|
|
|
|
// TODO: we've already calculated this in an earlier function. This is wasteful.
|
|
|
|
|
util::IdVector closetans = master->get_near(actor_id, RadiusClose, true);
|
|
|
|
|
|
|
|
|
|
tsb.write_int32(0);
|
|
|
|
|
int write_count_after = tsb.total_writes();
|
|
|
|
|
int nmodified = 0;
|
|
|
|
|
for (int64_t id : closetans) {
|
|
|
|
|
MLS.rawgeti(mtab, mtangibles, id);
|
|
|
|
|
SLS.rawgeti(stab, stangibles, id);
|
|
|
|
|
MLS.getmetatable(mmeta, mtab);
|
|
|
|
|
SLS.getmetatable(smeta, stab);
|
|
|
|
|
MLS.rawget(mclass, mmeta, "__index");
|
|
|
|
|
SLS.rawget(sclass, smeta, "__index");
|
|
|
|
|
std::string mname = MLS.classname(mclass);
|
|
|
|
|
std::string sname = SLS.classname(sclass);
|
|
|
|
|
if (mname != sname) {
|
|
|
|
|
tsb.write_int64(id);
|
|
|
|
|
tsb.write_string(mname);
|
|
|
|
|
nmodified += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tsb.overwrite_int32(write_count_after, nmodified);
|
|
|
|
|
SLS.result();
|
|
|
|
|
MLS.result();
|
|
|
|
|
|
|
|
|
|
// Forward to client, and apply to server-synchronous.
|
|
|
|
|
tsb.copy_into(xsb);
|
|
|
|
|
patch_tanclass(&tsb);
|
2021-10-07 14:58:20 -04:00
|
|
|
assert(tsb.empty());
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 12:40:21 -04:00
|
|
|
void World::patch_source(StreamBuffer *sb) {
|
2021-10-25 14:47:37 -04:00
|
|
|
bool modified = source_db_.patch(sb);
|
|
|
|
|
if (modified) {
|
|
|
|
|
std::string errs = source_db_.rebuild();
|
|
|
|
|
// TODO: I don't currently have any good place to send the
|
|
|
|
|
// error messages. This is a stopgap.
|
|
|
|
|
std::cerr << errs;
|
|
|
|
|
}
|
2021-09-23 12:40:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_source(World *master, StreamBuffer *sb) {
|
|
|
|
|
source_db_.diff(master->source_db_, sb);
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 16:27:39 -05:00
|
|
|
int64_t World::patch_everything(StreamBuffer *sb) {
|
|
|
|
|
int64_t actor_id = patch_actor(sb);
|
2021-09-10 17:06:07 -04:00
|
|
|
patch_visible(sb);
|
|
|
|
|
patch_luatabs(sb);
|
|
|
|
|
patch_tanclass(sb);
|
2021-09-23 12:40:21 -04:00
|
|
|
patch_source(sb);
|
2021-11-09 16:27:39 -05:00
|
|
|
return actor_id;
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::diff_everything(int64_t actor_id, World *master, StreamBuffer *sb) {
|
|
|
|
|
diff_actor(actor_id, master, sb);
|
|
|
|
|
util::IdVector visible = get_visible_union(actor_id, master);
|
|
|
|
|
diff_visible(visible, master, sb);
|
|
|
|
|
diff_luatabs(actor_id, master, sb);
|
|
|
|
|
diff_tanclass(actor_id, master, sb);
|
2021-09-23 12:40:21 -04:00
|
|
|
diff_source(master, sb);
|
2021-09-10 17:06:07 -04:00
|
|
|
}
|