Start breaking world.cpp into multiple files
This commit is contained in:
@@ -13,13 +13,14 @@ CPP_FILES=\
|
|||||||
cpp/globaldb.cpp\
|
cpp/globaldb.cpp\
|
||||||
cpp/sched.cpp\
|
cpp/sched.cpp\
|
||||||
cpp/table.cpp\
|
cpp/table.cpp\
|
||||||
cpp/tablecmp.cpp\
|
|
||||||
cpp/gui.cpp\
|
cpp/gui.cpp\
|
||||||
cpp/luasnap.cpp\
|
cpp/luasnap.cpp\
|
||||||
cpp/animqueue.cpp\
|
cpp/animqueue.cpp\
|
||||||
cpp/streambuffer.cpp\
|
cpp/streambuffer.cpp\
|
||||||
cpp/source.cpp\
|
cpp/source.cpp\
|
||||||
cpp/world.cpp\
|
cpp/world.cpp\
|
||||||
|
cpp/world-difftab.cpp\
|
||||||
|
cpp/world-pairtab.cpp\
|
||||||
cpp/textgame.cpp\
|
cpp/textgame.cpp\
|
||||||
cpp/main.cpp
|
cpp/main.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// tablecmp -- compare two tables nonrecursively.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef TABLECMP_HPP
|
|
||||||
#define TABLECMP_HPP
|
|
||||||
|
|
||||||
#include "luastack.hpp"
|
|
||||||
#include "util.hpp"
|
|
||||||
#include "streambuffer.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
// Compare two tables, generating a diff in the specified stream buffer.
|
|
||||||
//
|
|
||||||
// The synch stack must have stnmap, stab on top.
|
|
||||||
// The master stack must have mtnmap, mtab on top.
|
|
||||||
// If cmeta is true, the metatables of the two tables are compared.
|
|
||||||
// Returns true if there were any diffs.
|
|
||||||
//
|
|
||||||
bool tablecmp_diff(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer *sb);
|
|
||||||
|
|
||||||
// Given a tablecmp_diff output, convert it to a debug string.
|
|
||||||
//
|
|
||||||
std::string tablecmp_debug_string(StreamBuffer *sb);
|
|
||||||
|
|
||||||
#endif // TABLECMP_HPP
|
|
||||||
|
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// This file contains the code to compare the contents of tables.
|
||||||
|
// The top level functions in this file are:
|
||||||
|
//
|
||||||
|
// World::diff_lua_tables
|
||||||
|
// World::diff_tangible_databases
|
||||||
|
//
|
||||||
|
// This file also contains all the support code needed to implement
|
||||||
|
// this stuff.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "streambuffer.hpp"
|
#include "streambuffer.hpp"
|
||||||
#include "tablecmp.hpp"
|
#include "world.hpp"
|
||||||
|
|
||||||
// Given a table and an tnmap, return the table number of the table.
|
// Given a table and an tnmap, return the table number of the table.
|
||||||
// Returns zero if the table doesn't have a table number.
|
// Returns zero if the table doesn't have a table number.
|
||||||
@@ -17,23 +30,6 @@ static int get_table_number(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the tangible ID of a tangible.
|
|
||||||
static int64_t get_tangible_id(const LuaStack &LS, LuaSlot tab) {
|
|
||||||
int64_t id = 0;
|
|
||||||
if (LS.istable(tab) && LS.gettabletype(tab) == LUA_TT_TANGIBLE) {
|
|
||||||
lua_State *L = LS.state();
|
|
||||||
if (lua_getmetatable(L, tab.index())) {
|
|
||||||
lua_pushstring(L, "id");
|
|
||||||
lua_rawget(L, -2);
|
|
||||||
if (lua_type(L, -1) == LUA_TNUMBER) {
|
|
||||||
id = lua_tointeger(L, -1);
|
|
||||||
}
|
|
||||||
lua_pop(L, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool equivalent_values(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap,
|
static bool equivalent_values(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap,
|
||||||
LuaStack &SLS, LuaSlot sval, LuaSlot stnmap) {
|
LuaStack &SLS, LuaSlot sval, LuaSlot stnmap) {
|
||||||
@@ -69,7 +65,7 @@ static bool equivalent_values(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap,
|
|||||||
}
|
}
|
||||||
case LUA_TT_TANGIBLE: {
|
case LUA_TT_TANGIBLE: {
|
||||||
if (SLS.xtype(sval) != LUA_TT_TANGIBLE) return false;
|
if (SLS.xtype(sval) != LUA_TT_TANGIBLE) return false;
|
||||||
return get_tangible_id(MLS, mval) == get_tangible_id(SLS, sval);
|
return World::tangible_id(MLS, mval) == World::tangible_id(SLS, sval);
|
||||||
}
|
}
|
||||||
case LUA_TT_GLOBALENV: {
|
case LUA_TT_GLOBALENV: {
|
||||||
return (SLS.xtype(sval) == LUA_TT_GLOBALENV);
|
return (SLS.xtype(sval) == LUA_TT_GLOBALENV);
|
||||||
@@ -110,7 +106,7 @@ static void transmit_value(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap, StreamBu
|
|||||||
}
|
}
|
||||||
case LUA_TT_TANGIBLE: {
|
case LUA_TT_TANGIBLE: {
|
||||||
sb->write_uint8(LUA_TT_TANGIBLE);
|
sb->write_uint8(LUA_TT_TANGIBLE);
|
||||||
sb->write_int64(get_tangible_id(MLS, mval));
|
sb->write_int64(World::tangible_id(MLS, mval));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_TT_GLOBALENV: {
|
case LUA_TT_GLOBALENV: {
|
||||||
@@ -123,7 +119,48 @@ static void transmit_value(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap, StreamBu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tablecmp_diff(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer *sb) {
|
static void transmit_value_debug_string(StreamBuffer *sb, std::ostringstream &oss) {
|
||||||
|
int kind = sb->read_uint8();
|
||||||
|
switch (kind) {
|
||||||
|
case LUA_TBOOLEAN: {
|
||||||
|
bool b = sb->read_bool();
|
||||||
|
oss << (b ? "true":"false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TNUMBER: {
|
||||||
|
oss << sb->read_double();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TSTRING: {
|
||||||
|
oss << sb->read_string();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TT_GENERAL: {
|
||||||
|
oss << "table " << sb->read_int32();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TT_CLASS: {
|
||||||
|
oss << "class " << sb->read_string();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TT_TANGIBLE: {
|
||||||
|
oss << "tan " << sb->read_int64();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TT_GLOBALENV: {
|
||||||
|
oss << "globals";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case LUA_TNIL: {
|
||||||
|
oss << "nil";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(false); // Should not get here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compare_tables(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer *sb) {
|
||||||
LuaArg mtnmap, mtab, stnmap, stab;
|
LuaArg mtnmap, mtab, stnmap, stab;
|
||||||
LuaVar skey, mkey, sval, mval, mnil;
|
LuaVar skey, mkey, sval, mval, mnil;
|
||||||
LuaStack SLS(synch, stnmap, stab, skey, sval);
|
LuaStack SLS(synch, stnmap, stab, skey, sval);
|
||||||
@@ -175,55 +212,14 @@ bool tablecmp_diff(lua_State *synch, lua_State *master, bool cmeta, StreamBuffer
|
|||||||
return (nupdates > 0);
|
return (nupdates > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tablecmp_value_debug_string(StreamBuffer *sb, std::ostringstream &oss) {
|
static std::string compare_tables_debug_string(StreamBuffer *sb) {
|
||||||
int kind = sb->read_uint8();
|
|
||||||
switch (kind) {
|
|
||||||
case LUA_TBOOLEAN: {
|
|
||||||
bool b = sb->read_bool();
|
|
||||||
oss << (b ? "true":"false");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TNUMBER: {
|
|
||||||
oss << sb->read_double();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TSTRING: {
|
|
||||||
oss << sb->read_string();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TT_GENERAL: {
|
|
||||||
oss << "table " << sb->read_int32();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TT_CLASS: {
|
|
||||||
oss << "class " << sb->read_string();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TT_TANGIBLE: {
|
|
||||||
oss << "tan " << sb->read_int64();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TT_GLOBALENV: {
|
|
||||||
oss << "globals";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_TNIL: {
|
|
||||||
oss << "nil";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
assert(false); // Should not get here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tablecmp_debug_string(StreamBuffer *sb) {
|
|
||||||
std::vector<std::string> sorted;
|
std::vector<std::string> sorted;
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
int ndiffs = sb->read_int32();
|
int ndiffs = sb->read_int32();
|
||||||
for (int i = 0; i < ndiffs; i++) {
|
for (int i = 0; i < ndiffs; i++) {
|
||||||
tablecmp_value_debug_string(sb, oss);
|
transmit_value_debug_string(sb, oss);
|
||||||
oss << "=";
|
oss << "=";
|
||||||
tablecmp_value_debug_string(sb, oss);
|
transmit_value_debug_string(sb, oss);
|
||||||
sorted.push_back(oss.str());
|
sorted.push_back(oss.str());
|
||||||
oss.str("");
|
oss.str("");
|
||||||
}
|
}
|
||||||
@@ -234,6 +230,80 @@ std::string tablecmp_debug_string(StreamBuffer *sb) {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::diff_lua_tables(lua_State *master, StreamBuffer *sb) {
|
||||||
|
lua_State *synch = state();
|
||||||
|
LuaVar sntmap, mntmap, stnmap, mtnmap;
|
||||||
|
LuaStack SLS(synch, sntmap, stnmap);
|
||||||
|
LuaStack MLS(master, mntmap, mtnmap);
|
||||||
|
SLS.rawget(sntmap, LuaRegistry, "ntmap");
|
||||||
|
MLS.rawget(mntmap, LuaRegistry, "ntmap");
|
||||||
|
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
||||||
|
MLS.rawget(mtnmap, LuaRegistry, "tnmap");
|
||||||
|
int m_ntables = MLS.rawlen(mntmap);
|
||||||
|
int s_ntables = SLS.rawlen(sntmap);
|
||||||
|
assert(m_ntables == s_ntables);
|
||||||
|
|
||||||
|
sb->write_int32(0);
|
||||||
|
int write_count_after = sb->total_writes();
|
||||||
|
int nmodified = 0;
|
||||||
|
int s_top = lua_gettop(synch);
|
||||||
|
int m_top = lua_gettop(master);
|
||||||
|
for (int id = 1; id <= m_ntables; id++) {
|
||||||
|
lua_pushvalue(master, mtnmap.index());
|
||||||
|
lua_rawgeti(master, mtnmap.index(), id);
|
||||||
|
if (lua_type(master, -1) == LUA_TTABLE) {
|
||||||
|
lua_pushvalue(synch, stnmap.index());
|
||||||
|
lua_rawgeti(synch, sntmap.index(), id);
|
||||||
|
int tw = sb->total_writes();
|
||||||
|
sb->write_int32(id);
|
||||||
|
nmodified += 1;
|
||||||
|
if (!compare_tables(synch, master, true, sb)) {
|
||||||
|
sb->unwrite_to(tw);
|
||||||
|
nmodified -= 1;
|
||||||
|
}
|
||||||
|
assert(lua_gettop(synch) == s_top);
|
||||||
|
assert(lua_gettop(master) == m_top);
|
||||||
|
} else {
|
||||||
|
lua_pop(master, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb->overwrite_int32(write_count_after, nmodified);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void World::diff_tangible_databases(const IdVector &basis, lua_State *master, StreamBuffer *sb) {
|
||||||
|
lua_State *synch = state();
|
||||||
|
LuaVar stnmap, mtnmap, stangibles, mtangibles;
|
||||||
|
LuaStack SLS(synch, stnmap, stangibles);
|
||||||
|
LuaStack MLS(master, mtnmap, mtangibles);
|
||||||
|
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
||||||
|
MLS.rawget(mtnmap, LuaRegistry, "tnmap");
|
||||||
|
SLS.rawget(stangibles, LuaRegistry, "tangibles");
|
||||||
|
MLS.rawget(mtangibles, LuaRegistry, "tangibles");
|
||||||
|
|
||||||
|
sb->write_int32(0);
|
||||||
|
int write_count_after = sb->total_writes();
|
||||||
|
int nmodified = 0;
|
||||||
|
int s_top = lua_gettop(synch);
|
||||||
|
int m_top = lua_gettop(master);
|
||||||
|
for (int64_t id : basis) {
|
||||||
|
lua_pushvalue(master, mtnmap.index());
|
||||||
|
lua_rawgeti(master, mtangibles.index(), id);
|
||||||
|
lua_pushvalue(synch, stnmap.index());
|
||||||
|
lua_rawgeti(synch, stangibles.index(), id);
|
||||||
|
int tw = sb->total_writes();
|
||||||
|
sb->write_int64(id);
|
||||||
|
nmodified += 1;
|
||||||
|
if (!compare_tables(synch, master, false, sb)) {
|
||||||
|
sb->unwrite_to(tw);
|
||||||
|
nmodified -= 1;
|
||||||
|
}
|
||||||
|
assert(lua_gettop(synch) == s_top);
|
||||||
|
assert(lua_gettop(master) == m_top);
|
||||||
|
}
|
||||||
|
sb->overwrite_int32(write_count_after, nmodified);
|
||||||
|
}
|
||||||
|
|
||||||
LuaDefine(table_diffcompare, "c") {
|
LuaDefine(table_diffcompare, "c") {
|
||||||
LuaArg mtnmap, mtab, stnmap, stab;
|
LuaArg mtnmap, mtab, stnmap, stab;
|
||||||
LuaRet dbgstring;
|
LuaRet dbgstring;
|
||||||
@@ -250,9 +320,9 @@ LuaDefine(table_diffcompare, "c") {
|
|||||||
lua_xmove(L, synch, 2);
|
lua_xmove(L, synch, 2);
|
||||||
lua_pushvalue(L, mtnmap.index());
|
lua_pushvalue(L, mtnmap.index());
|
||||||
lua_pushvalue(L, mtab.index());
|
lua_pushvalue(L, mtab.index());
|
||||||
tablecmp_diff(synch, L, true, &sb);
|
compare_tables(synch, L, true, &sb);
|
||||||
// Convert the output to a debug string.
|
// Convert the output to a debug string.
|
||||||
LS.set(dbgstring, tablecmp_debug_string(&sb));
|
LS.set(dbgstring, compare_tables_debug_string(&sb));
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
271
luprex/core/cpp/world-pairtab.cpp
Normal file
271
luprex/core/cpp/world-pairtab.cpp
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// This file contains the code to pair up tables in the synchronous
|
||||||
|
// model with tables in the master model. Here are the top-level
|
||||||
|
// routines in this file:
|
||||||
|
//
|
||||||
|
// World::number_lua_tables
|
||||||
|
// World::unnumber_lua_tables
|
||||||
|
// World::pair_lua_tables
|
||||||
|
// World::pair_new_tables
|
||||||
|
// World::create_new_tables
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "luastack.hpp"
|
||||||
|
#include "streambuffer.hpp"
|
||||||
|
#include "world.hpp"
|
||||||
|
|
||||||
|
int World::number_lua_tables(const IdVector &basis) {
|
||||||
|
// This is conceptually recursive, but we're going to use an
|
||||||
|
// explicit stack (the lua stack).
|
||||||
|
lua_State *L = state();
|
||||||
|
LuaVar tnmap, ntmap, tangibles, tab, key, val, xid;
|
||||||
|
LuaStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid);
|
||||||
|
LS.set(tnmap, LuaNewTable);
|
||||||
|
LS.set(ntmap, LuaNewTable);
|
||||||
|
LS.rawset(LuaRegistry, "tnmap", tnmap);
|
||||||
|
LS.rawset(LuaRegistry, "ntmap", ntmap);
|
||||||
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
|
int nextid = 1;
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
|
||||||
|
// Push all subtables onto the stack. Note that we may push
|
||||||
|
// the same table twice, that's OK.
|
||||||
|
for (int64_t id : basis) {
|
||||||
|
LS.rawget(tab, tangibles, id);
|
||||||
|
assert(LS.istable(tab));
|
||||||
|
// Traverse subtables.
|
||||||
|
LS.set(key, LuaNil);
|
||||||
|
while (LS.next(tab, key, val)) {
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop tables from the stack one by one. If the table is not
|
||||||
|
// already numbered, number it and push subtables onto the stack.
|
||||||
|
while (lua_gettop(L) > top) {
|
||||||
|
lua_replace(L, tab.index());
|
||||||
|
LS.rawget(xid, tnmap, tab);
|
||||||
|
if (LS.isnil(xid)) {
|
||||||
|
int id = nextid++;
|
||||||
|
LS.rawset(tnmap, tab, id);
|
||||||
|
LS.rawset(ntmap, id, tab);
|
||||||
|
// Traverse the metatable.
|
||||||
|
LS.getmetatable(val, tab);
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
// Traverse the subtables.
|
||||||
|
LS.set(key, LuaNil);
|
||||||
|
while (LS.next(tab, key, val)) {
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LS.result();
|
||||||
|
assert(stack_is_clear());
|
||||||
|
return nextid - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::unnumber_lua_tables() {
|
||||||
|
// All we have to do is remove these tables from the registry.
|
||||||
|
LuaStack LS(state());
|
||||||
|
LS.rawset(LuaRegistry, "tnmap", LuaNil);
|
||||||
|
LS.rawset(LuaRegistry, "ntmap", LuaNil);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::pair_lua_tables(const IdVector &basis, lua_State *master) {
|
||||||
|
lua_State *synch = state();
|
||||||
|
LuaVar stangibles, mtangibles, sntmap, mntmap, stnmap, mtnmap, stab, mtab, skey, mkey, sval, mval, sidx, midx;
|
||||||
|
LuaStack SLS(synch, stangibles, stab, skey, sval, sntmap, stnmap, sidx);
|
||||||
|
LuaStack MLS(master, mtangibles, mtab, mkey, mval, mntmap, mtnmap, midx);
|
||||||
|
|
||||||
|
// Fetch the tangible databases
|
||||||
|
SLS.rawget(stangibles, LuaRegistry, "tangibles");
|
||||||
|
MLS.rawget(mtangibles, LuaRegistry, "tangibles");
|
||||||
|
|
||||||
|
// Fetch the synchronous model tnmap and ntmap
|
||||||
|
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
||||||
|
SLS.rawget(sntmap, LuaRegistry, "ntmap");
|
||||||
|
assert(SLS.istable(stnmap));
|
||||||
|
assert(SLS.istable(sntmap));
|
||||||
|
|
||||||
|
// Initialize the master model tnmap and ntmap
|
||||||
|
MLS.set(mtnmap, LuaNewTable);
|
||||||
|
MLS.set(mntmap, LuaNewTable);
|
||||||
|
MLS.rawset(LuaRegistry, "tnmap", mtnmap);
|
||||||
|
MLS.rawset(LuaRegistry, "ntmap", mntmap);
|
||||||
|
int s_ntables = SLS.rawlen(sntmap);
|
||||||
|
for (int i = 1; i <= s_ntables; i++) {
|
||||||
|
MLS.rawset(mntmap, i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of which tables are already paired
|
||||||
|
std::vector<bool> paired;
|
||||||
|
paired.assign(s_ntables + 1, false);
|
||||||
|
|
||||||
|
// This records the top of the stack.
|
||||||
|
int mtop = lua_gettop(master);
|
||||||
|
|
||||||
|
for (int64_t id : basis) {
|
||||||
|
MLS.rawget(mtab, mtangibles, id);
|
||||||
|
SLS.rawget(stab, stangibles, id);
|
||||||
|
assert(MLS.istable(mtab));
|
||||||
|
assert(SLS.istable(stab));
|
||||||
|
MLS.set(mkey, LuaNil);
|
||||||
|
while (MLS.next(mtab, mkey, mval)) {
|
||||||
|
if (!MLS.issortablekey(mkey)) continue;
|
||||||
|
if (!MLS.istable(mval)) continue;
|
||||||
|
MLS.movesortablekey(mkey, SLS, skey);
|
||||||
|
SLS.rawget(sval, stab, skey);
|
||||||
|
if (!SLS.istable(sval)) continue;
|
||||||
|
lua_checkstack(master, 20);
|
||||||
|
lua_checkstack(synch, 20);
|
||||||
|
lua_pushvalue(master, mval.index());
|
||||||
|
lua_pushvalue(synch, sval.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lua_gettop(master) > mtop) {
|
||||||
|
lua_replace(master, mtab.index());
|
||||||
|
lua_replace(synch, stab.index());
|
||||||
|
// If the master table is not a general table, skip.
|
||||||
|
if (MLS.gettabletype(mtab) != LUA_TT_GENERAL) continue;
|
||||||
|
// If the master table is already paired, skip.
|
||||||
|
MLS.rawget(midx, mtnmap, mtab);
|
||||||
|
if (MLS.isnumber(midx)) continue;
|
||||||
|
// If the synch table is not a table, skip.
|
||||||
|
if (!SLS.istable(stab)) continue;
|
||||||
|
// If the synch table doesn't have a number, skip.
|
||||||
|
SLS.rawget(sidx, stnmap, stab);
|
||||||
|
if (!SLS.isnumber(sidx)) continue;
|
||||||
|
int idx = SLS.ckinteger(sidx);
|
||||||
|
assert((idx >= 1) && (idx <= s_ntables));
|
||||||
|
// Pair the tables.
|
||||||
|
MLS.rawset(mtnmap, mtab, idx);
|
||||||
|
MLS.rawset(mntmap, idx, mtab);
|
||||||
|
paired[idx] = true;
|
||||||
|
// Potentially pair the metatables.
|
||||||
|
MLS.getmetatable(mval, mtab);
|
||||||
|
if (MLS.istable(mval)) {
|
||||||
|
SLS.getmetatable(sval, stab);
|
||||||
|
if (SLS.istable(sval)) {
|
||||||
|
lua_pushvalue(master, mval.index());
|
||||||
|
lua_pushvalue(synch, sval.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Pair the subtables.
|
||||||
|
MLS.set(mkey, LuaNil);
|
||||||
|
while (MLS.next(mtab, mkey, mval)) {
|
||||||
|
if (!MLS.issortablekey(mkey)) continue;
|
||||||
|
if (!MLS.istable(mval)) continue;
|
||||||
|
MLS.movesortablekey(mkey, SLS, skey);
|
||||||
|
SLS.rawget(sval, stab, skey);
|
||||||
|
if (!SLS.istable(sval)) continue;
|
||||||
|
lua_checkstack(master, 20);
|
||||||
|
lua_checkstack(synch, 20);
|
||||||
|
lua_pushvalue(master, mval.index());
|
||||||
|
lua_pushvalue(synch, sval.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MLS.result();
|
||||||
|
SLS.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
int World::pair_new_tables(const IdVector &basis, lua_State *master) {
|
||||||
|
// This is conceptually recursive, but we're going to use an
|
||||||
|
// explicit stack (the lua stack).
|
||||||
|
lua_State *L = master;
|
||||||
|
LuaVar tnmap, ntmap, tangibles, tab, key, val, xid;
|
||||||
|
LuaStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid);
|
||||||
|
LS.rawget(tnmap, LuaRegistry, "tnmap");
|
||||||
|
LS.rawget(ntmap, LuaRegistry, "ntmap");
|
||||||
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
|
int ntables = LS.rawlen(ntmap);
|
||||||
|
std::vector<bool> visited;
|
||||||
|
visited.assign(ntables + 1, false);
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
|
||||||
|
// Push all subtables onto the stack. Note that we may push
|
||||||
|
// the same table twice, that's OK.
|
||||||
|
for (int64_t id : basis) {
|
||||||
|
LS.rawget(tab, tangibles, id);
|
||||||
|
assert(LS.istable(tab));
|
||||||
|
LS.set(key, LuaNil);
|
||||||
|
while (LS.next(tab, key, val)) {
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop tables from the stack one by one. If the table is not
|
||||||
|
// numbered, number it. If it is not visited, visit it.
|
||||||
|
while (lua_gettop(L) > top) {
|
||||||
|
lua_replace(L, tab.index());
|
||||||
|
int id = 0;
|
||||||
|
LS.rawget(xid, tnmap, tab);
|
||||||
|
if (!LS.isnumber(xid)) {
|
||||||
|
id = visited.size();
|
||||||
|
LS.rawset(tnmap, tab, id);
|
||||||
|
LS.rawset(ntmap, id, tab);
|
||||||
|
visited.push_back(false);
|
||||||
|
} else {
|
||||||
|
id = LS.cknumber(xid);
|
||||||
|
assert((id >= 0) && (id < int(visited.size())));
|
||||||
|
}
|
||||||
|
if (!visited[id]) {
|
||||||
|
visited[id] = true;
|
||||||
|
// Traverse the metatable.
|
||||||
|
LS.getmetatable(val, tab);
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
// Traverse the subtables.
|
||||||
|
LS.set(key, LuaNil);
|
||||||
|
while (LS.next(tab, key, val)) {
|
||||||
|
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
||||||
|
lua_checkstack(L, 10);
|
||||||
|
lua_pushvalue(L, val.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LS.result();
|
||||||
|
assert(stack_is_clear());
|
||||||
|
return visited.size() - 1 - ntables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::create_new_tables(int n) {
|
||||||
|
LuaVar tnmap, ntmap, tab;
|
||||||
|
LuaStack LS(state(), tnmap, ntmap, tab);
|
||||||
|
LS.rawget(tnmap, LuaRegistry, "tnmap");
|
||||||
|
LS.rawget(ntmap, LuaRegistry, "ntmap");
|
||||||
|
assert(LS.istable(tnmap));
|
||||||
|
assert(LS.istable(ntmap));
|
||||||
|
int ntables = LS.rawlen(ntmap);
|
||||||
|
int nextid = ntables + 1;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int id = nextid++;
|
||||||
|
LS.newtable(tab);
|
||||||
|
LS.rawset(ntmap, id, tab);
|
||||||
|
LS.rawset(tnmap, tab, id);
|
||||||
|
}
|
||||||
|
LS.result();
|
||||||
|
assert(stack_is_clear());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "animqueue.hpp"
|
#include "animqueue.hpp"
|
||||||
#include "gui.hpp"
|
#include "gui.hpp"
|
||||||
#include "traceback.hpp"
|
#include "traceback.hpp"
|
||||||
#include "tablecmp.hpp"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void World::store_global_pointer(lua_State *L, World *v) {
|
void World::store_global_pointer(lua_State *L, World *v) {
|
||||||
@@ -879,333 +878,6 @@ void World::patch_visible_animations(StreamBuffer *sb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::number_lua_tables(const IdVector &basis) {
|
|
||||||
// This is conceptually recursive, but we're going to use an
|
|
||||||
// explicit stack (the lua stack).
|
|
||||||
lua_State *L = state();
|
|
||||||
LuaVar tnmap, ntmap, tangibles, tab, key, val, xid;
|
|
||||||
LuaStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid);
|
|
||||||
LS.set(tnmap, LuaNewTable);
|
|
||||||
LS.set(ntmap, LuaNewTable);
|
|
||||||
LS.rawset(LuaRegistry, "tnmap", tnmap);
|
|
||||||
LS.rawset(LuaRegistry, "ntmap", ntmap);
|
|
||||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
||||||
int nextid = 1;
|
|
||||||
int top = lua_gettop(L);
|
|
||||||
|
|
||||||
// Push all subtables onto the stack. Note that we may push
|
|
||||||
// the same table twice, that's OK.
|
|
||||||
for (int64_t id : basis) {
|
|
||||||
LS.rawget(tab, tangibles, id);
|
|
||||||
assert(LS.istable(tab));
|
|
||||||
// Traverse subtables.
|
|
||||||
LS.set(key, LuaNil);
|
|
||||||
while (LS.next(tab, key, val)) {
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop tables from the stack one by one. If the table is not
|
|
||||||
// already numbered, number it and push subtables onto the stack.
|
|
||||||
while (lua_gettop(L) > top) {
|
|
||||||
lua_replace(L, tab.index());
|
|
||||||
LS.rawget(xid, tnmap, tab);
|
|
||||||
if (LS.isnil(xid)) {
|
|
||||||
int id = nextid++;
|
|
||||||
LS.rawset(tnmap, tab, id);
|
|
||||||
LS.rawset(ntmap, id, tab);
|
|
||||||
// Traverse the metatable.
|
|
||||||
LS.getmetatable(val, tab);
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
// Traverse the subtables.
|
|
||||||
LS.set(key, LuaNil);
|
|
||||||
while (LS.next(tab, key, val)) {
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LS.result();
|
|
||||||
assert(stack_is_clear());
|
|
||||||
return nextid - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::unnumber_lua_tables() {
|
|
||||||
// All we have to do is remove these tables from the registry.
|
|
||||||
LuaStack LS(state());
|
|
||||||
LS.rawset(LuaRegistry, "tnmap", LuaNil);
|
|
||||||
LS.rawset(LuaRegistry, "ntmap", LuaNil);
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::pair_lua_tables(const IdVector &basis, lua_State *master) {
|
|
||||||
lua_State *synch = state();
|
|
||||||
LuaVar stangibles, mtangibles, sntmap, mntmap, stnmap, mtnmap, stab, mtab, skey, mkey, sval, mval, sidx, midx;
|
|
||||||
LuaStack SLS(synch, stangibles, stab, skey, sval, sntmap, stnmap, sidx);
|
|
||||||
LuaStack MLS(master, mtangibles, mtab, mkey, mval, mntmap, mtnmap, midx);
|
|
||||||
|
|
||||||
// Fetch the tangible databases
|
|
||||||
SLS.rawget(stangibles, LuaRegistry, "tangibles");
|
|
||||||
MLS.rawget(mtangibles, LuaRegistry, "tangibles");
|
|
||||||
|
|
||||||
// Fetch the synchronous model tnmap and ntmap
|
|
||||||
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
|
||||||
SLS.rawget(sntmap, LuaRegistry, "ntmap");
|
|
||||||
assert(SLS.istable(stnmap));
|
|
||||||
assert(SLS.istable(sntmap));
|
|
||||||
|
|
||||||
// Initialize the master model tnmap and ntmap
|
|
||||||
MLS.set(mtnmap, LuaNewTable);
|
|
||||||
MLS.set(mntmap, LuaNewTable);
|
|
||||||
MLS.rawset(LuaRegistry, "tnmap", mtnmap);
|
|
||||||
MLS.rawset(LuaRegistry, "ntmap", mntmap);
|
|
||||||
int s_ntables = SLS.rawlen(sntmap);
|
|
||||||
for (int i = 1; i <= s_ntables; i++) {
|
|
||||||
MLS.rawset(mntmap, i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of which tables are already paired
|
|
||||||
std::vector<bool> paired;
|
|
||||||
paired.assign(s_ntables + 1, false);
|
|
||||||
|
|
||||||
// This records the top of the stack.
|
|
||||||
int mtop = lua_gettop(master);
|
|
||||||
|
|
||||||
for (int64_t id : basis) {
|
|
||||||
MLS.rawget(mtab, mtangibles, id);
|
|
||||||
SLS.rawget(stab, stangibles, id);
|
|
||||||
assert(MLS.istable(mtab));
|
|
||||||
assert(SLS.istable(stab));
|
|
||||||
MLS.set(mkey, LuaNil);
|
|
||||||
while (MLS.next(mtab, mkey, mval)) {
|
|
||||||
if (!MLS.issortablekey(mkey)) continue;
|
|
||||||
if (!MLS.istable(mval)) continue;
|
|
||||||
MLS.movesortablekey(mkey, SLS, skey);
|
|
||||||
SLS.rawget(sval, stab, skey);
|
|
||||||
if (!SLS.istable(sval)) continue;
|
|
||||||
lua_checkstack(master, 20);
|
|
||||||
lua_checkstack(synch, 20);
|
|
||||||
lua_pushvalue(master, mval.index());
|
|
||||||
lua_pushvalue(synch, sval.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lua_gettop(master) > mtop) {
|
|
||||||
lua_replace(master, mtab.index());
|
|
||||||
lua_replace(synch, stab.index());
|
|
||||||
// If the master table is not a general table, skip.
|
|
||||||
if (MLS.gettabletype(mtab) != LUA_TT_GENERAL) continue;
|
|
||||||
// If the master table is already paired, skip.
|
|
||||||
MLS.rawget(midx, mtnmap, mtab);
|
|
||||||
if (MLS.isnumber(midx)) continue;
|
|
||||||
// If the synch table is not a table, skip.
|
|
||||||
if (!SLS.istable(stab)) continue;
|
|
||||||
// If the synch table doesn't have a number, skip.
|
|
||||||
SLS.rawget(sidx, stnmap, stab);
|
|
||||||
if (!SLS.isnumber(sidx)) continue;
|
|
||||||
int idx = SLS.ckinteger(sidx);
|
|
||||||
assert((idx >= 1) && (idx <= s_ntables));
|
|
||||||
// Pair the tables.
|
|
||||||
MLS.rawset(mtnmap, mtab, idx);
|
|
||||||
MLS.rawset(mntmap, idx, mtab);
|
|
||||||
paired[idx] = true;
|
|
||||||
// Potentially pair the metatables.
|
|
||||||
MLS.getmetatable(mval, mtab);
|
|
||||||
if (MLS.istable(mval)) {
|
|
||||||
SLS.getmetatable(sval, stab);
|
|
||||||
if (SLS.istable(sval)) {
|
|
||||||
lua_pushvalue(master, mval.index());
|
|
||||||
lua_pushvalue(synch, sval.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Pair the subtables.
|
|
||||||
MLS.set(mkey, LuaNil);
|
|
||||||
while (MLS.next(mtab, mkey, mval)) {
|
|
||||||
if (!MLS.issortablekey(mkey)) continue;
|
|
||||||
if (!MLS.istable(mval)) continue;
|
|
||||||
MLS.movesortablekey(mkey, SLS, skey);
|
|
||||||
SLS.rawget(sval, stab, skey);
|
|
||||||
if (!SLS.istable(sval)) continue;
|
|
||||||
lua_checkstack(master, 20);
|
|
||||||
lua_checkstack(synch, 20);
|
|
||||||
lua_pushvalue(master, mval.index());
|
|
||||||
lua_pushvalue(synch, sval.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MLS.result();
|
|
||||||
SLS.result();
|
|
||||||
}
|
|
||||||
|
|
||||||
int World::pair_new_tables(const IdVector &basis, lua_State *master) {
|
|
||||||
// This is conceptually recursive, but we're going to use an
|
|
||||||
// explicit stack (the lua stack).
|
|
||||||
lua_State *L = master;
|
|
||||||
LuaVar tnmap, ntmap, tangibles, tab, key, val, xid;
|
|
||||||
LuaStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid);
|
|
||||||
LS.rawget(tnmap, LuaRegistry, "tnmap");
|
|
||||||
LS.rawget(ntmap, LuaRegistry, "ntmap");
|
|
||||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
||||||
int ntables = LS.rawlen(ntmap);
|
|
||||||
std::vector<bool> visited;
|
|
||||||
visited.assign(ntables + 1, false);
|
|
||||||
int top = lua_gettop(L);
|
|
||||||
|
|
||||||
// Push all subtables onto the stack. Note that we may push
|
|
||||||
// the same table twice, that's OK.
|
|
||||||
for (int64_t id : basis) {
|
|
||||||
LS.rawget(tab, tangibles, id);
|
|
||||||
assert(LS.istable(tab));
|
|
||||||
LS.set(key, LuaNil);
|
|
||||||
while (LS.next(tab, key, val)) {
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop tables from the stack one by one. If the table is not
|
|
||||||
// numbered, number it. If it is not visited, visit it.
|
|
||||||
while (lua_gettop(L) > top) {
|
|
||||||
lua_replace(L, tab.index());
|
|
||||||
int id = 0;
|
|
||||||
LS.rawget(xid, tnmap, tab);
|
|
||||||
if (!LS.isnumber(xid)) {
|
|
||||||
id = visited.size();
|
|
||||||
LS.rawset(tnmap, tab, id);
|
|
||||||
LS.rawset(ntmap, id, tab);
|
|
||||||
visited.push_back(false);
|
|
||||||
} else {
|
|
||||||
id = LS.cknumber(xid);
|
|
||||||
assert((id >= 0) && (id < int(visited.size())));
|
|
||||||
}
|
|
||||||
if (!visited[id]) {
|
|
||||||
visited[id] = true;
|
|
||||||
// Traverse the metatable.
|
|
||||||
LS.getmetatable(val, tab);
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
// Traverse the subtables.
|
|
||||||
LS.set(key, LuaNil);
|
|
||||||
while (LS.next(tab, key, val)) {
|
|
||||||
if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) {
|
|
||||||
lua_checkstack(L, 10);
|
|
||||||
lua_pushvalue(L, val.index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LS.result();
|
|
||||||
assert(stack_is_clear());
|
|
||||||
return visited.size() - 1 - ntables;
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::create_new_tables(int n) {
|
|
||||||
LuaVar tnmap, ntmap, tab;
|
|
||||||
LuaStack LS(state(), tnmap, ntmap, tab);
|
|
||||||
LS.rawget(tnmap, LuaRegistry, "tnmap");
|
|
||||||
LS.rawget(ntmap, LuaRegistry, "ntmap");
|
|
||||||
assert(LS.istable(tnmap));
|
|
||||||
assert(LS.istable(ntmap));
|
|
||||||
int ntables = LS.rawlen(ntmap);
|
|
||||||
int nextid = ntables + 1;
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
int id = nextid++;
|
|
||||||
LS.newtable(tab);
|
|
||||||
LS.rawset(ntmap, id, tab);
|
|
||||||
LS.rawset(tnmap, tab, id);
|
|
||||||
}
|
|
||||||
LS.result();
|
|
||||||
assert(stack_is_clear());
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::diff_lua_tables(lua_State *master, StreamBuffer *sb) {
|
|
||||||
lua_State *synch = state();
|
|
||||||
LuaVar sntmap, mntmap, stnmap, mtnmap;
|
|
||||||
LuaStack SLS(synch, sntmap, stnmap);
|
|
||||||
LuaStack MLS(master, mntmap, mtnmap);
|
|
||||||
SLS.rawget(sntmap, LuaRegistry, "ntmap");
|
|
||||||
MLS.rawget(mntmap, LuaRegistry, "ntmap");
|
|
||||||
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
|
||||||
MLS.rawget(mtnmap, LuaRegistry, "tnmap");
|
|
||||||
int m_ntables = MLS.rawlen(mntmap);
|
|
||||||
int s_ntables = SLS.rawlen(sntmap);
|
|
||||||
assert(m_ntables == s_ntables);
|
|
||||||
|
|
||||||
sb->write_int32(0);
|
|
||||||
int write_count_after = sb->total_writes();
|
|
||||||
int nmodified = 0;
|
|
||||||
int s_top = lua_gettop(synch);
|
|
||||||
int m_top = lua_gettop(master);
|
|
||||||
for (int id = 1; id <= m_ntables; id++) {
|
|
||||||
lua_pushvalue(master, mtnmap.index());
|
|
||||||
lua_rawgeti(master, mtnmap.index(), id);
|
|
||||||
if (lua_type(master, -1) == LUA_TTABLE) {
|
|
||||||
lua_pushvalue(synch, stnmap.index());
|
|
||||||
lua_rawgeti(synch, sntmap.index(), id);
|
|
||||||
int tw = sb->total_writes();
|
|
||||||
sb->write_int32(id);
|
|
||||||
nmodified += 1;
|
|
||||||
if (!tablecmp_diff(synch, master, true, sb)) {
|
|
||||||
sb->unwrite_to(tw);
|
|
||||||
nmodified -= 1;
|
|
||||||
}
|
|
||||||
assert(lua_gettop(synch) == s_top);
|
|
||||||
assert(lua_gettop(master) == m_top);
|
|
||||||
} else {
|
|
||||||
lua_pop(master, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb->overwrite_int32(write_count_after, nmodified);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void World::diff_tangible_databases(const IdVector &basis, lua_State *master, StreamBuffer *sb) {
|
|
||||||
lua_State *synch = state();
|
|
||||||
LuaVar stnmap, mtnmap, stangibles, mtangibles;
|
|
||||||
LuaStack SLS(synch, stnmap, stangibles);
|
|
||||||
LuaStack MLS(master, mtnmap, mtangibles);
|
|
||||||
SLS.rawget(stnmap, LuaRegistry, "tnmap");
|
|
||||||
MLS.rawget(mtnmap, LuaRegistry, "tnmap");
|
|
||||||
SLS.rawget(stangibles, LuaRegistry, "tangibles");
|
|
||||||
MLS.rawget(mtangibles, LuaRegistry, "tangibles");
|
|
||||||
|
|
||||||
sb->write_int32(0);
|
|
||||||
int write_count_after = sb->total_writes();
|
|
||||||
int nmodified = 0;
|
|
||||||
int s_top = lua_gettop(synch);
|
|
||||||
int m_top = lua_gettop(master);
|
|
||||||
for (int64_t id : basis) {
|
|
||||||
lua_pushvalue(master, mtnmap.index());
|
|
||||||
lua_rawgeti(master, mtangibles.index(), id);
|
|
||||||
lua_pushvalue(synch, stnmap.index());
|
|
||||||
lua_rawgeti(synch, stangibles.index(), id);
|
|
||||||
int tw = sb->total_writes();
|
|
||||||
sb->write_int64(id);
|
|
||||||
nmodified += 1;
|
|
||||||
if (!tablecmp_diff(synch, master, false, sb)) {
|
|
||||||
sb->unwrite_to(tw);
|
|
||||||
nmodified -= 1;
|
|
||||||
}
|
|
||||||
assert(lua_gettop(synch) == s_top);
|
|
||||||
assert(lua_gettop(master) == m_top);
|
|
||||||
}
|
|
||||||
sb->overwrite_int32(write_count_after, nmodified);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LuaDefine(tangible_animstate, "c") {
|
LuaDefine(tangible_animstate, "c") {
|
||||||
LuaArg tanobj;
|
LuaArg tanobj;
|
||||||
LuaRet graphic, plane, x, y, z, facing;
|
LuaRet graphic, plane, x, y, z, facing;
|
||||||
|
|||||||
@@ -285,11 +285,26 @@ private:
|
|||||||
static void diff_visible_animations(const TanVector &mvis, const TanVector &svis, StreamBuffer *sb);
|
static void diff_visible_animations(const TanVector &mvis, const TanVector &svis, StreamBuffer *sb);
|
||||||
void patch_visible_animations(StreamBuffer *sb);
|
void patch_visible_animations(StreamBuffer *sb);
|
||||||
|
|
||||||
|
// Compare the general tables.
|
||||||
|
//
|
||||||
|
void diff_lua_tables(lua_State *master, StreamBuffer *sb);
|
||||||
|
|
||||||
|
// Compare the tangible databases.
|
||||||
|
//
|
||||||
|
void diff_tangible_databases(const IdVector &basis, lua_State *master, StreamBuffer *sb);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Pass 3 of difference transmission: numbering of tables.
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Numbering and pairing of lua tables.
|
||||||
//
|
//
|
||||||
// Table-to-number mapping is stored in registry.tnmap
|
// Table-to-number mapping is stored in registry.tnmap
|
||||||
// Number-to-table mapping is stored in registry.ntmap
|
// Number-to-table mapping is stored in registry.ntmap
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// numbering of tables.
|
||||||
|
//
|
||||||
// Returns the total number of tables numbered.
|
// Returns the total number of tables numbered.
|
||||||
//
|
//
|
||||||
int number_lua_tables(const IdVector &basis);
|
int number_lua_tables(const IdVector &basis);
|
||||||
@@ -313,14 +328,6 @@ public:
|
|||||||
//
|
//
|
||||||
void create_new_tables(int n);
|
void create_new_tables(int n);
|
||||||
|
|
||||||
// Compare the general tables.
|
|
||||||
//
|
|
||||||
void diff_lua_tables(lua_State *master, StreamBuffer *sb);
|
|
||||||
|
|
||||||
// Compare the tangible databases.
|
|
||||||
//
|
|
||||||
void diff_tangible_databases(const IdVector &basis, lua_State *master, StreamBuffer *sb);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Type of model
|
// Type of model
|
||||||
util::WorldType world_type_;
|
util::WorldType world_type_;
|
||||||
|
|||||||
Reference in New Issue
Block a user