Changes related to ray-collision, and luprex global variable stuff
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
|
||||
#include "world.hpp"
|
||||
#include "pprint.hpp"
|
||||
#include "serializelua.hpp"
|
||||
#include <cmath>
|
||||
|
||||
static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) {
|
||||
@@ -949,14 +950,7 @@ LuaDefine(global_set, "varname, value",
|
||||
"|lua identifier."
|
||||
"|"
|
||||
"|You can store global data using global.set, then you can"
|
||||
"|retrieve it using global.get. You can also retrieve data using"
|
||||
"|gv.varname, which is just shorthand for global.get. You may not"
|
||||
"|store data using gv.varname=value, this yields the error 'Use "
|
||||
"|global.set to store data in the global data table.'"
|
||||
"|"
|
||||
"|Values stored using global.set are transmitted to all"
|
||||
"|connected clients immediately. When a new client connects,"
|
||||
"|he will receive all the global data."
|
||||
"|retrieve it using global.get."
|
||||
"|"
|
||||
"|The global data table is not the same thing as the lua "
|
||||
"|environment table. Trying to store data in the lua environment"
|
||||
@@ -966,18 +960,16 @@ LuaDefine(global_set, "varname, value",
|
||||
"|global data table (using global.set) instead of in the lua"
|
||||
"|environment table."
|
||||
"|"
|
||||
"|There are certain restrictions on the values that you store."
|
||||
"|Only data that can be serialized according to doc(table.serialize)"
|
||||
"|can be stored."
|
||||
"|Data is stored in a serialized form. The data is serialized"
|
||||
"|at the moment you call global.set. It is deserialized when you"
|
||||
"|call global.get. Therefore, each time you call global.get, you"
|
||||
"|construct another copy of the value."
|
||||
"|"
|
||||
"|When you store the value, it is immediately serialized and then"
|
||||
"|deserialized again, and the deserialized copy is stored in the"
|
||||
"|variable."
|
||||
"|"
|
||||
// "|When you call global.get, you obtain the copy. Any attempt to"
|
||||
// "|mutate the copy will fail with this lua error message: 'Tables"
|
||||
// "|returned by global.get are immutable.' This rule prevents'"
|
||||
// "|aliasing between global data and other data structures."
|
||||
"|The serialization routine can only serialize certain kinds of"
|
||||
"|values. For example, closures cannot be serialized at all."
|
||||
"|Serializing a tangible serializes the tangible's ID, but"
|
||||
"|none of the contents of the tangible. See doc(table.serialize)"
|
||||
"|for more information about what can and can't be serialized."
|
||||
"|") {
|
||||
LuaArg varname;
|
||||
LuaArg value;
|
||||
@@ -990,8 +982,16 @@ LuaDefine(global_set, "varname, value",
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
// Serialize the data.
|
||||
StreamBuffer sb;
|
||||
eng::string error = serialize_lua(LS, value, &sb);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
w->set_global(LS, gvar, value);
|
||||
w->set_global(gvar, sb.view());
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
@@ -1000,16 +1000,33 @@ LuaDefine(global_get, "varname",
|
||||
"|"
|
||||
"|See doc(global.set) for information on how to store global data."
|
||||
"|"
|
||||
"|Do not mutate data returned by global.get: doing so will produce"
|
||||
"|unpredictable results. Instead, using global.set to mutate global"
|
||||
"|variables."
|
||||
"|Performance note: each time you call global.get, you deserialize the"
|
||||
"|stored serialized version, constructing another copy of the data."
|
||||
"|") {
|
||||
LuaArg varname;
|
||||
LuaRet value;
|
||||
LuaVar globaldb;
|
||||
LuaDefStack LS(L, varname, value, globaldb);
|
||||
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||
LS.rawget(value, globaldb, varname);
|
||||
LuaDefStack LS(L, varname, value);
|
||||
LS.set(value, LuaNil);
|
||||
|
||||
// Check the varname argument.
|
||||
eng::string gvar = LS.ckstring(varname);
|
||||
if (!sv::is_lua_id(gvar)) {
|
||||
luaL_error(L, "variable name must be a valid lua identifier: %s", gvar.c_str());
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
// Fetch the serialized blob.
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
std::string_view data = w->get_global(gvar);
|
||||
if (data.empty()) return LS.result();
|
||||
|
||||
// Deserialize the blob.
|
||||
StreamBuffer sb(data);
|
||||
eng::string error = deserialize_lua(LS, value, &sb);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
return LS.result();
|
||||
}
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
@@ -1022,8 +1039,8 @@ LuaDefine(global_once, "varname",
|
||||
"|") {
|
||||
LuaArg varname;
|
||||
LuaRet result;
|
||||
LuaVar globaldb, flag;
|
||||
LuaDefStack LS(L, varname, flag, result, globaldb);
|
||||
LuaDefStack LS(L, varname, result);
|
||||
LS.set(result, false);
|
||||
|
||||
// Check the varname argument.
|
||||
eng::string gvar = LS.ckstring(varname);
|
||||
@@ -1033,17 +1050,12 @@ LuaDefine(global_once, "varname",
|
||||
}
|
||||
gvar += ":once";
|
||||
|
||||
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||
LS.rawget(flag, globaldb, gvar);
|
||||
|
||||
if (!LS.isnil(flag)) {
|
||||
LS.set(result, false);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LS.set(result, true);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
w->set_global(LS, gvar, result);
|
||||
LS.set(result, false);
|
||||
if (w->get_global(gvar).empty()) {
|
||||
LS.set(result, true);
|
||||
w->set_global(gvar, "x");
|
||||
}
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
@@ -1055,8 +1067,7 @@ LuaDefine(global_clearonce, "varname",
|
||||
"|uses global.set under the covers."
|
||||
"|") {
|
||||
LuaArg varname;
|
||||
LuaVar null;
|
||||
LuaDefStack LS(L, varname, null);
|
||||
LuaDefStack LS(L, varname);
|
||||
|
||||
// Check the varname argument.
|
||||
eng::string gvar = LS.ckstring(varname);
|
||||
@@ -1066,8 +1077,7 @@ LuaDefine(global_clearonce, "varname",
|
||||
}
|
||||
gvar += ":once";
|
||||
|
||||
LS.set(null, LuaNil);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
w->set_global(LS, gvar, null);
|
||||
w->set_global(gvar, "");
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "traceback.hpp"
|
||||
#include "pprint.hpp"
|
||||
#include "util.hpp"
|
||||
#include "serializelua.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -1101,31 +1100,10 @@ std::ostream *World::lthread_print_stream() const {
|
||||
}
|
||||
}
|
||||
|
||||
void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value) {
|
||||
lua_State *L = LS0.state();
|
||||
LuaVar globaldb, copy;
|
||||
LuaExtStack LS(L, globaldb, copy);
|
||||
|
||||
// Serialize then deserialize the data, to produce a copy.
|
||||
StreamBuffer sb;
|
||||
eng::string error = serialize_lua(LS, value, &sb);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
return;
|
||||
}
|
||||
eng::string serialized(sb.view());
|
||||
error = deserialize_lua(LS, copy, &sb);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the copy in the globalDB.
|
||||
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||
LS.rawset(globaldb, gvar, copy);
|
||||
|
||||
void World::set_global(const eng::string &gvar, std::string_view value) {
|
||||
// Store the serialized blob.
|
||||
gvname_to_serial_[gvar] = serialized;
|
||||
//
|
||||
gvname_to_serial_[gvar] = value;
|
||||
|
||||
// Implement the tracking so that we can rapidly determine which global
|
||||
// variables need to be difference transmitted.
|
||||
@@ -1147,6 +1125,15 @@ void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value
|
||||
}
|
||||
}
|
||||
|
||||
const eng::string &World::get_global(const eng::string &gvar) {
|
||||
static eng::string empty;
|
||||
auto iter = gvname_to_serial_.find(gvar);
|
||||
if (iter == gvname_to_serial_.end()) {
|
||||
return empty;
|
||||
} else {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
void World::serialize(StreamBuffer *sb) {
|
||||
assert(stack_is_clear());
|
||||
|
||||
@@ -305,36 +305,15 @@ void World::diff_source(World *master, StreamBuffer *sb) {
|
||||
assert(tsb.empty());
|
||||
}
|
||||
|
||||
const eng::string &World::get_gvname_serial(const eng::string &gvar) {
|
||||
static eng::string empty;
|
||||
auto iter = gvname_to_serial_.find(gvar);
|
||||
if (iter == gvname_to_serial_.end()) {
|
||||
return empty;
|
||||
} else {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
void World::patch_globals(StreamBuffer *sb, DebugCollector *dbc) {
|
||||
DebugBlock dbb(dbc, "patch_globals");
|
||||
int64_t seqno = sb->read_int64();
|
||||
int32_t total = sb->read_int32();
|
||||
if (total > 0) {
|
||||
lua_State *L = state();
|
||||
LuaVar globaldb, copy;
|
||||
LuaExtStack LS(L, globaldb, copy);
|
||||
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||
for (int i = 0; i < total; i++) {
|
||||
eng::string gvar = sb->read_string();
|
||||
eng::string serial = sb->read_string();
|
||||
gvname_to_serial_[gvar] = serial;
|
||||
StreamBuffer sb(serial);
|
||||
eng::string error = deserialize_lua(LS, copy, &sb);
|
||||
if (error.empty()) {
|
||||
LS.rawset(globaldb, gvar, copy);
|
||||
} else {
|
||||
DebugLine(dbc) << "Invalid global serialized data: " << gvar << ":" << error;
|
||||
}
|
||||
}
|
||||
}
|
||||
assign_seqno_ = seqno;
|
||||
@@ -350,8 +329,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) {
|
||||
int64_t count_pos = tsb.total_writes();
|
||||
int32_t total_mods = 0;
|
||||
for (const eng::string &gvar : gvname_modified_) {
|
||||
const eng::string &mval = master->get_gvname_serial(gvar);
|
||||
const eng::string &sval = get_gvname_serial(gvar);
|
||||
const eng::string &mval = master->get_global(gvar);
|
||||
const eng::string &sval = get_global(gvar);
|
||||
if (mval != sval) {
|
||||
total_mods += 1;
|
||||
tsb.write_string(gvar);
|
||||
@@ -362,8 +341,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) {
|
||||
while (iter != master->seqno_to_gvname_.end()) {
|
||||
const auto &gvar = iter->second;
|
||||
if (gvname_modified_.find(gvar) == gvname_modified_.end()) {
|
||||
const eng::string &mval = master->get_gvname_serial(gvar);
|
||||
const eng::string &sval = get_gvname_serial(gvar);
|
||||
const eng::string &mval = master->get_global(gvar);
|
||||
const eng::string &sval = get_global(gvar);
|
||||
if (mval != sval) {
|
||||
total_mods += 1;
|
||||
tsb.write_string(gvar);
|
||||
|
||||
@@ -241,32 +241,6 @@ void World::tangible_set_class(int64_t id, const eng::string &c) const {
|
||||
LS.rawset(meta, "__index", sclass);
|
||||
}
|
||||
|
||||
void World::set_global_json(const eng::string &gvar, const eng::string &json) {
|
||||
LuaVar decoded;
|
||||
LuaExtStack LS(state(), decoded);
|
||||
bool ok = json::decode(LS, decoded, json);
|
||||
if (!ok) {
|
||||
luaL_error(state(), "invalid json");
|
||||
return;
|
||||
}
|
||||
set_global(LS, gvar, decoded);
|
||||
}
|
||||
|
||||
eng::string World::get_global_json(const eng::string &gvar) {
|
||||
LuaVar value, globaldb;
|
||||
LuaExtStack LS(state(), globaldb, value);
|
||||
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||
LS.rawget(value, globaldb, gvar);
|
||||
eng::string out;
|
||||
eng::string error = json::encode(LS, value, out, false, 10000);
|
||||
if (!error.empty()) {
|
||||
luaL_error(state(), "%s", error.c_str());
|
||||
return "";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
eng::string World::tangible_get_class(int64_t id) const {
|
||||
LuaVar tangibles, tan, meta, sclass;
|
||||
LuaExtStack LS(state(), tangibles, tan, meta, sclass);
|
||||
@@ -495,24 +469,24 @@ LuaDefine(unittests_world5diffglobals, "", "some unit tests") {
|
||||
UniqueWorld cs(new World(WORLD_TYPE_PREDICTIVE));
|
||||
StreamBuffer sb;
|
||||
|
||||
m->set_global_json("x", "3");
|
||||
m->set_global("x", "3");
|
||||
ss->diff_globals(m.get(), &sb);
|
||||
cs->patch_globals(&sb, nullptr);
|
||||
LuaAssertStrEq(L, cs->get_global_json("x"), "3");
|
||||
LuaAssertStrEq(L, cs->get_global("x"), "3");
|
||||
|
||||
m->set_global_json("x", "4");
|
||||
m->set_global_json("x", "5");
|
||||
m->set_global_json("y", "6");
|
||||
m->set_global("x", "4");
|
||||
m->set_global("x", "5");
|
||||
m->set_global("y", "6");
|
||||
ss->diff_globals(m.get(), &sb);
|
||||
cs->patch_globals(&sb, nullptr);
|
||||
LuaAssertStrEq(L, cs->get_global_json("x"), "5");
|
||||
LuaAssertStrEq(L, cs->get_global_json("y"), "6");
|
||||
LuaAssertStrEq(L, cs->get_global("x"), "5");
|
||||
LuaAssertStrEq(L, cs->get_global("y"), "6");
|
||||
|
||||
cs->set_global_json("x", "2");
|
||||
ss->set_global_json("x", "2");
|
||||
cs->set_global("x", "2");
|
||||
ss->set_global("x", "2");
|
||||
ss->diff_globals(m.get(), &sb);
|
||||
cs->patch_globals(&sb, nullptr);
|
||||
LuaAssertStrEq(L, cs->get_global_json("x"), "5");
|
||||
LuaAssertStrEq(L, cs->get_global("x"), "5");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -357,17 +357,18 @@ public:
|
||||
|
||||
std::ostream *lthread_print_stream() const;
|
||||
|
||||
// Set a global variable.
|
||||
// Set a lua global variable.
|
||||
//
|
||||
// This will throw lua errors if there's a problem.
|
||||
// The table just stores strings, and the difference transmitter
|
||||
// just difference transmits those strings. The strings are meant
|
||||
// to be serialized lua data structures, but there is no enforcement
|
||||
// of that here.
|
||||
//
|
||||
void set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value);
|
||||
void set_global(const eng::string &var, std::string_view value);
|
||||
|
||||
// Get the serialized value of a global variable.
|
||||
// Get a lua global variable.
|
||||
//
|
||||
// This accessor is used during difference transmission.
|
||||
//
|
||||
const eng::string &get_gvname_serial(const eng::string &gvar);
|
||||
const eng::string &get_global(const eng::string &var);
|
||||
|
||||
// Allocate a single ID.
|
||||
//
|
||||
@@ -491,14 +492,6 @@ public:
|
||||
//
|
||||
eng::string tangible_get_class(int64_t id) const;
|
||||
|
||||
// Store json in a global variable.
|
||||
//
|
||||
void set_global_json(const eng::string &gvar, const eng::string &json);
|
||||
|
||||
// Get a global variable as json.
|
||||
//
|
||||
eng::string get_global_json(const eng::string &gvar);
|
||||
|
||||
public:
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -671,7 +664,6 @@ private:
|
||||
std::unique_ptr<eng::ostringstream> lthread_prints_;
|
||||
|
||||
friend class Tangible;
|
||||
friend void global_set(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value);
|
||||
friend int lfn_tangible_animate(lua_State *L);
|
||||
friend int lfn_tangible_build(lua_State *L);
|
||||
friend int lfn_tangible_redirect(lua_State *L);
|
||||
|
||||
Reference in New Issue
Block a user