Refactor code for invoke_lua_source and world.init. Also, add compile_commands.json to luprex
This commit is contained in:
@@ -54,6 +54,21 @@ ALuprexGameModeBase::~ALuprexGameModeBase()
|
|||||||
//
|
//
|
||||||
uint32 ALuprexGameModeBase::Run() {
|
uint32 ALuprexGameModeBase::Run() {
|
||||||
FlxLockedWrapper lockedwrap(LockableWrapper);
|
FlxLockedWrapper lockedwrap(LockableWrapper);
|
||||||
|
if (lockedwrap->get_rescan_lua_source(lockedwrap.Get()))
|
||||||
|
{
|
||||||
|
drvutil::ostringstream srcpak;
|
||||||
|
std::string srcpakerr = drvutil::package_lua_source(LUPREX_ROOT_PATH, &srcpak);
|
||||||
|
if (!srcpakerr.empty())
|
||||||
|
{
|
||||||
|
FString FMessage((const UTF8CHAR *)(srcpakerr.c_str()));
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Trying to read Lua source: %s"), *FMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string_view srcpakv = srcpak.view();
|
||||||
|
lockedwrap->play_access(lockedwrap.Get(), AccessKind::INVOKE_LUA_SOURCE, 0, srcpakv.size(), srcpakv.data(), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
Sockets->Update(lockedwrap);
|
Sockets->Update(lockedwrap);
|
||||||
lockedwrap->play_update(lockedwrap.Get(), EngineSeconds);
|
lockedwrap->play_update(lockedwrap.Get(), EngineSeconds);
|
||||||
Sockets->Update(lockedwrap);
|
Sockets->Update(lockedwrap);
|
||||||
@@ -290,19 +305,7 @@ void ALuprexGameModeBase::InitializeGlobalState()
|
|||||||
// If wrapper is initialized, try to initialize the luprex engine.
|
// If wrapper is initialized, try to initialize the luprex engine.
|
||||||
if (w->play_initialize != nullptr)
|
if (w->play_initialize != nullptr)
|
||||||
{
|
{
|
||||||
drvutil::ostringstream srcpak;
|
w->play_initialize(w.Get(), "lpxclient", "");
|
||||||
std::string srcpakerr = drvutil::package_lua_source(LUPREX_ROOT_PATH, &srcpak);
|
|
||||||
if (!srcpakerr.empty())
|
|
||||||
{
|
|
||||||
FString FMessage((const UTF8CHAR *)(srcpakerr.c_str()));
|
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Trying to read Lua source: %s"), *FMessage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string_view srcpakv = srcpak.view();
|
|
||||||
char* argv[1];
|
|
||||||
argv[0] = const_cast<char*>("lpxclient");
|
|
||||||
w->play_initialize(w.Get(), 1, argv, srcpakv.size(), srcpakv.data(), "");
|
|
||||||
if (w->error[0])
|
if (w->error[0])
|
||||||
{
|
{
|
||||||
FString FMessage((const UTF8CHAR *)w->error);
|
FString FMessage((const UTF8CHAR *)w->error);
|
||||||
@@ -313,7 +316,6 @@ void ALuprexGameModeBase::InitializeGlobalState()
|
|||||||
Playing = true;
|
Playing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we successfully created a luprex engine, create a socket system and a worker thread.
|
// If we successfully created a luprex engine, create a socket system and a worker thread.
|
||||||
if (Playing) {
|
if (Playing) {
|
||||||
|
|||||||
1
build.py
1
build.py
@@ -266,6 +266,7 @@ def build_intellisense_database_for_clangd(force):
|
|||||||
shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject -mode=GenerateClangDatabase -OutputDir={UNREALENGINE}/.vscode")
|
shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject -mode=GenerateClangDatabase -OutputDir={UNREALENGINE}/.vscode")
|
||||||
shell(UNREALENGINE, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex UnrealEditor {OS} DebugGame -mode=GenerateClangDatabase -OutputDir={UNREALENGINE}/.vscode")
|
shell(UNREALENGINE, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex UnrealEditor {OS} DebugGame -mode=GenerateClangDatabase -OutputDir={UNREALENGINE}/.vscode")
|
||||||
shell(INTEGRATION, f"cat {UNREALENGINE}/.vscode/compile_commands.json >> {INTEGRATION}/.vscode/compile_commands.json")
|
shell(INTEGRATION, f"cat {UNREALENGINE}/.vscode/compile_commands.json >> {INTEGRATION}/.vscode/compile_commands.json")
|
||||||
|
shell(INTEGRATION, f"cat {INTEGRATION}/luprex/build/{OS}/compile_commands.json >> {INTEGRATION}/.vscode/compile_commands.json")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error = e
|
error = e
|
||||||
else:
|
else:
|
||||||
|
|||||||
196
luprex/Makefile
196
luprex/Makefile
@@ -5,11 +5,11 @@
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
ifneq "" "$(findstring -linux-,$(MAKE_HOST))"
|
ifneq "" "$(findstring -linux-,$(MAKE_HOST))"
|
||||||
OS=Linux
|
OS:=Linux
|
||||||
else ifneq "" "$(VSINSTALLDIR)"
|
else ifneq "" "$(VSINSTALLDIR)"
|
||||||
OS=Windows
|
OS:=Windows
|
||||||
else
|
else
|
||||||
OS=""
|
OS:=""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(OS)" ""
|
ifeq "$(OS)" ""
|
||||||
@@ -18,91 +18,6 @@ endif
|
|||||||
$(info Building for $(OS)...)
|
$(info Building for $(OS)...)
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
##
|
|
||||||
## List of all OBJ files
|
|
||||||
##
|
|
||||||
#######################################################################
|
|
||||||
|
|
||||||
OBJ_ERIS=\
|
|
||||||
build/$(OS)/eris/lapi.obj \
|
|
||||||
build/$(OS)/eris/lcode.obj \
|
|
||||||
build/$(OS)/eris/lctype.obj \
|
|
||||||
build/$(OS)/eris/ldebug.obj \
|
|
||||||
build/$(OS)/eris/ldo.obj \
|
|
||||||
build/$(OS)/eris/ldump.obj \
|
|
||||||
build/$(OS)/eris/lfunc.obj \
|
|
||||||
build/$(OS)/eris/lgc.obj \
|
|
||||||
build/$(OS)/eris/llex.obj \
|
|
||||||
build/$(OS)/eris/lmem.obj \
|
|
||||||
build/$(OS)/eris/lobject.obj \
|
|
||||||
build/$(OS)/eris/lopcodes.obj \
|
|
||||||
build/$(OS)/eris/lparser.obj \
|
|
||||||
build/$(OS)/eris/lstate.obj \
|
|
||||||
build/$(OS)/eris/lstring.obj \
|
|
||||||
build/$(OS)/eris/ltable.obj \
|
|
||||||
build/$(OS)/eris/ltm.obj \
|
|
||||||
build/$(OS)/eris/lundump.obj \
|
|
||||||
build/$(OS)/eris/lvm.obj \
|
|
||||||
build/$(OS)/eris/lzio.obj \
|
|
||||||
build/$(OS)/eris/lauxlib.obj \
|
|
||||||
build/$(OS)/eris/lbaselib.obj \
|
|
||||||
build/$(OS)/eris/lbitlib.obj \
|
|
||||||
build/$(OS)/eris/lcorolib.obj \
|
|
||||||
build/$(OS)/eris/ldblib.obj \
|
|
||||||
build/$(OS)/eris/liolib.obj \
|
|
||||||
build/$(OS)/eris/lmathlib.obj \
|
|
||||||
build/$(OS)/eris/loslib.obj \
|
|
||||||
build/$(OS)/eris/lstrlib.obj \
|
|
||||||
build/$(OS)/eris/ltablib.obj \
|
|
||||||
build/$(OS)/eris/loadlib.obj \
|
|
||||||
build/$(OS)/eris/linit.obj \
|
|
||||||
build/$(OS)/eris/eris.obj \
|
|
||||||
|
|
||||||
OBJ_CORE=\
|
|
||||||
build/$(OS)/core/invocation.obj\
|
|
||||||
build/$(OS)/core/spookyv2.obj\
|
|
||||||
build/$(OS)/core/eng-malloc.obj\
|
|
||||||
build/$(OS)/core/debugcollector.obj\
|
|
||||||
build/$(OS)/core/drivenengine.obj\
|
|
||||||
build/$(OS)/core/util.obj\
|
|
||||||
build/$(OS)/core/luastack.obj\
|
|
||||||
build/$(OS)/core/traceback.obj\
|
|
||||||
build/$(OS)/core/planemap.obj\
|
|
||||||
build/$(OS)/core/pprint.obj\
|
|
||||||
build/$(OS)/core/luaconsole.obj\
|
|
||||||
build/$(OS)/core/luavector.obj\
|
|
||||||
build/$(OS)/core/idalloc.obj\
|
|
||||||
build/$(OS)/core/globaldb.obj\
|
|
||||||
build/$(OS)/core/sched.obj\
|
|
||||||
build/$(OS)/core/http.obj\
|
|
||||||
build/$(OS)/core/json.obj\
|
|
||||||
build/$(OS)/core/table.obj\
|
|
||||||
build/$(OS)/core/luasnap.obj\
|
|
||||||
build/$(OS)/core/animqueue.obj\
|
|
||||||
build/$(OS)/core/streambuffer.obj\
|
|
||||||
build/$(OS)/core/source.obj\
|
|
||||||
build/$(OS)/core/world-core.obj\
|
|
||||||
build/$(OS)/core/world-accessor.obj\
|
|
||||||
build/$(OS)/core/world-difftab.obj\
|
|
||||||
build/$(OS)/core/world-diffxmit.obj\
|
|
||||||
build/$(OS)/core/world-pairtab.obj\
|
|
||||||
build/$(OS)/core/world-testing.obj\
|
|
||||||
build/$(OS)/core/lpxserver.obj\
|
|
||||||
build/$(OS)/core/lpxclient.obj\
|
|
||||||
build/$(OS)/core/eng-tests.obj\
|
|
||||||
build/$(OS)/core/printbuffer.obj\
|
|
||||||
build/$(OS)/core/serializelua.obj\
|
|
||||||
|
|
||||||
|
|
||||||
OBJ_DRV=\
|
|
||||||
build/$(OS)/drv/driver.obj\
|
|
||||||
build/$(OS)/drv/drvutil.obj\
|
|
||||||
build/$(OS)/drv/osdrvutil.obj\
|
|
||||||
build/$(OS)/drv/sslutil.obj\
|
|
||||||
build/$(OS)/drv/readline.obj\
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##
|
##
|
||||||
## Make rules for linux
|
## Make rules for linux
|
||||||
@@ -110,17 +25,20 @@ OBJ_DRV=\
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
ifeq "$(OS)" "Linux"
|
ifeq "$(OS)" "Linux"
|
||||||
OPT=-g -O0
|
OPT:=-g -O0
|
||||||
LUPREX_EXE=luprex
|
LUPREX_EXE:=luprex
|
||||||
LUPREXLIB_DLL=luprexlib.so
|
LUPREXLIB_DLL:=luprexlib.so
|
||||||
LUPREXSTATIC_EXE=luprexstatic
|
LUPREXSTATIC_EXE:=luprexstatic
|
||||||
COMPILE=g++ -Wall $(OPT) -std=c++20 -fvisibility=hidden -c -MMD -fPIC -o
|
COMPILE:=g++ -Wall $(OPT) -std=c++20 -fvisibility=hidden -c -MMD -fPIC -o
|
||||||
LINKDLL=g++ -Wall $(OPT) -std=c++20 -export-dynamic -Wl,--no-allow-shlib-undefined -Wl,-z,defs -shared -o
|
LINKDLL:=g++ -Wall $(OPT) -std=c++20 -export-dynamic -Wl,--no-allow-shlib-undefined -Wl,-z,defs -shared -o
|
||||||
LINKEXE=g++ -Wall $(OPT) -std=c++20 -export-dynamic -o
|
LINKEXE:=g++ -Wall $(OPT) -std=c++20 -export-dynamic -o
|
||||||
MAKEDEPS=true
|
MAKEDEPS:=true
|
||||||
OPENSSL_INCLUDE=-I./ext/openssl-3.0.1/inc
|
LIBS:=-L./ext/openssl-3.0.1/lib/linux -lssl -lcrypto -ldl
|
||||||
LUA_FLAGS=-DLUA_USE_APICHECK -DLUA_USE_POSIX
|
CCJSON="build/$(OS)/compile_commands.json"
|
||||||
LIBS=-L./ext/openssl-3.0.1/lib/linux -lssl -lcrypto -ldl
|
|
||||||
|
FLAGS_ERIS:=-DLUA_USE_APICHECK -DLUA_USE_POSIX
|
||||||
|
FLAGS_CORE:=-I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -I./ext
|
||||||
|
FLAGS_DRV:=-I./ext/openssl-3.1.0/inc -I./src/drv -I./ext
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
@@ -133,26 +51,60 @@ ifeq "$(OS)" "Windows"
|
|||||||
ifeq "" "$(VSINSTALLDIR)"
|
ifeq "" "$(VSINSTALLDIR)"
|
||||||
$(error You must use vcvars64.bat to set up the visual studio environment variables)
|
$(error You must use vcvars64.bat to set up the visual studio environment variables)
|
||||||
endif
|
endif
|
||||||
OPT=/Od /Zi
|
OPT:=/Od /Zi
|
||||||
LUPREX_EXE=luprex.exe
|
LUPREX_EXE:=luprex.exe
|
||||||
LUPREXLIB_DLL=luprexlib.dll
|
LUPREXLIB_DLL:=luprexlib.dll
|
||||||
LUPREXSTATIC_EXE=luprexstatic.exe
|
LUPREXSTATIC_EXE:=luprexstatic.exe
|
||||||
COMPILE=CL $(OPT) /std:c++20 /EHsc /nologo /MD /TP /c /Fo:
|
COMPILE:=CL $(OPT) /std:c++20 /EHsc /nologo /MD /TP /c /Fo:
|
||||||
LINKDLL=CL $(OPT) /std:c++20 /EHsc /nologo /LDd /Fe:
|
LINKDLL:=CL $(OPT) /std:c++20 /EHsc /nologo /LDd /Fe:
|
||||||
LINKEXE=CL $(OPT) /std:c++20 /EHsc /nologo /Fe:
|
LINKEXE:=CL $(OPT) /std:c++20 /EHsc /nologo /Fe:
|
||||||
MAKEDEPS=g++ -Wall -std=c++20 -MMD -E -o
|
MAKEDEPS:=g++ -Wall -std=c++20 -MMD -E -o
|
||||||
OPENSSL_INCLUDE=-I./ext/openssl-3.1.0/inc
|
LIBS:=ext/openssl-3.1.0/lib/visual/libcrypto.lib ext/openssl-3.1.0/lib/visual/libssl.lib ws2_32.lib crypt32.lib cryptui.lib user32.lib advapi32.lib
|
||||||
LUA_FLAGS=-DLUA_USE_APICHECK -DLUA_COMPAT_ALL
|
CCJSON="build/$(OS)/compile_commands.json"
|
||||||
LIBS=ext/openssl-3.1.0/lib/visual/libcrypto.lib ext/openssl-3.1.0/lib/visual/libssl.lib ws2_32.lib crypt32.lib cryptui.lib user32.lib advapi32.lib
|
|
||||||
|
FLAGS_ERIS:=-DLUA_USE_APICHECK -DLUA_COMPAT_ALL
|
||||||
|
FLAGS_CORE:=-I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -I./ext
|
||||||
|
FLAGS_DRV:=-I./ext/openssl-3.1.0/inc -I./src/drv -I./ext
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
##
|
||||||
|
## List of all source files
|
||||||
|
##
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
BASE_ERIS := \
|
||||||
|
lapi lcode lctype ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes \
|
||||||
|
lparser lstate lstring ltable ltm lundump lvm lzio \
|
||||||
|
lauxlib lbaselib lbitlib lcorolib ldblib liolib lmathlib loslib \
|
||||||
|
lstrlib ltablib loadlib linit eris
|
||||||
|
|
||||||
|
BASE_CORE := \
|
||||||
|
invocation spookyv2 eng-malloc debugcollector drivenengine util luastack \
|
||||||
|
traceback planemap pprint luaconsole luavector idalloc globaldb sched http \
|
||||||
|
json table luasnap animqueue streambuffer source world-core world-accessor \
|
||||||
|
world-difftab world-diffxmit world-pairtab world-testing lpxserver lpxclient \
|
||||||
|
eng-tests printbuffer serializelua
|
||||||
|
|
||||||
|
BASE_DRV := driver drvutil osdrvutil sslutil readline
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
##
|
||||||
|
## Generate lists of OBJ files.
|
||||||
|
##
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
OBJ_ERIS := $(patsubst %,build/$(OS)/eris/%.obj,$(BASE_ERIS))
|
||||||
|
OBJ_CORE := $(patsubst %,build/$(OS)/core/%.obj,$(BASE_CORE))
|
||||||
|
OBJ_DRV := $(patsubst %,build/$(OS)/drv/%.obj,$(BASE_DRV))
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##
|
##
|
||||||
## Make Rules
|
## Make Rules
|
||||||
##
|
##
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
all: build/$(OS)/$(LUPREX_EXE) build/$(OS)/$(LUPREXSTATIC_EXE) build/$(OS)/$(LUPREXLIB_DLL)
|
all: build/$(OS)/$(LUPREX_EXE) build/$(OS)/$(LUPREXSTATIC_EXE) build/$(OS)/$(LUPREXLIB_DLL) $(CCJSON)
|
||||||
|
|
||||||
build/$(OS)/DIRECTORY:
|
build/$(OS)/DIRECTORY:
|
||||||
mkdir -p build/$(OS)/core build/$(OS)/eris build/$(OS)/drv
|
mkdir -p build/$(OS)/core build/$(OS)/eris build/$(OS)/drv
|
||||||
@@ -168,23 +120,29 @@ build/$(OS)/$(LUPREXLIB_DLL): $(OBJ_ERIS) $(OBJ_CORE)
|
|||||||
$(LINKDLL) $@ $^
|
$(LINKDLL) $@ $^
|
||||||
|
|
||||||
build/$(OS)/eris/%.obj: ext/eris-master/src/%.c build/$(OS)/DIRECTORY
|
build/$(OS)/eris/%.obj: ext/eris-master/src/%.c build/$(OS)/DIRECTORY
|
||||||
$(MAKEDEPS) $@d $(LUA_FLAGS) $<
|
$(MAKEDEPS) $@d $(FLAGS_ERIS) $<
|
||||||
$(COMPILE) $@ $(LUA_FLAGS) $<
|
$(COMPILE) $@ $(FLAGS_ERIS) $<
|
||||||
|
|
||||||
build/$(OS)/core/%.obj: cpp/core/%.cpp build/$(OS)/DIRECTORY
|
build/$(OS)/core/%.obj: cpp/core/%.cpp build/$(OS)/DIRECTORY
|
||||||
$(MAKEDEPS) $@d -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -I./ext $<
|
$(MAKEDEPS) $@d $(FLAGS_CORE) $<
|
||||||
$(COMPILE) $@ -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -I./ext $<
|
$(COMPILE) $@ $(FLAGS_CORE) $<
|
||||||
|
|
||||||
build/$(OS)/drv/%.obj: cpp/drv/%.cpp build/$(OS)/DIRECTORY
|
build/$(OS)/drv/%.obj: cpp/drv/%.cpp build/$(OS)/DIRECTORY
|
||||||
$(MAKEDEPS) $@d $(OPENSSL_INCLUDE) -I./src/drv -I./ext $<
|
$(MAKEDEPS) $@d $(FLAGS_DRV) $<
|
||||||
$(COMPILE) $@ $(OPENSSL_INCLUDE) -I./src/drv -I./ext $<
|
$(COMPILE) $@ $(FLAGS_DRV) $<
|
||||||
|
|
||||||
|
$(CCJSON): Makefile add-compile-commands.py
|
||||||
|
rm -rf $(CCJSON)
|
||||||
|
python3 ./add-compile-commands.py "$(CCJSON)" "$(COMPILE)" "$(FLAGS_ERIS)" "build/$(OS)/eris/FILE.obj" "ext/eris-master/src/FILE.c" $(BASE_ERIS)
|
||||||
|
python3 ./add-compile-commands.py "$(CCJSON)" "$(COMPILE)" "$(FLAGS_CORE)" "build/$(OS)/cpp/FILE.obj" "cpp/core/FILE.cpp" $(BASE_CORE)
|
||||||
|
python3 ./add-compile-commands.py "$(CCJSON)" "$(COMPILE)" "$(FLAGS_DRV)" "build/$(OS)/drv/FILE.obj" "cpp/drv/FILE.cpp" $(BASE_DRV)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f luprex* luprex*.* *.pdb
|
rm -f *.pdb
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
||||||
clean-os:
|
clean-os:
|
||||||
rm -f luprex* luprex*.* *.pdb build/$(OS)/* build/$(OS)/*/*
|
rm -f *.pdb build/$(OS)/* build/$(OS)/*/*
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##
|
##
|
||||||
|
|||||||
23
luprex/add-compile-commands.py
Normal file
23
luprex/add-compile-commands.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
LUPREXDIR=os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||||
|
|
||||||
|
JSON=sys.argv[1]
|
||||||
|
COMPILE=sys.argv[2]
|
||||||
|
FLAGS=sys.argv[3]
|
||||||
|
OBJPAT=sys.argv[4]
|
||||||
|
CPAT=sys.argv[5]
|
||||||
|
OBJECTS=sys.argv[6:]
|
||||||
|
|
||||||
|
with open(JSON, "a") as cc:
|
||||||
|
for base in OBJECTS:
|
||||||
|
obj = LUPREXDIR + "/" + OBJPAT.replace("FILE", base)
|
||||||
|
file = LUPREXDIR + "/" + CPAT.replace("FILE", base)
|
||||||
|
flags = FLAGS.replace("-I./", f"-I{LUPREXDIR}/")
|
||||||
|
cc.write('{\n')
|
||||||
|
cc.write(f' "file" : "{file}",\n')
|
||||||
|
cc.write(f' "command" : "{COMPILE} {obj} {flags} {file}",\n')
|
||||||
|
cc.write(f' "directory" : "{LUPREXDIR}"\n')
|
||||||
|
cc.write('}\n')
|
||||||
@@ -436,9 +436,6 @@ void DrivenEngine::drv_get_animation_queues(uint32_t count, const int64_t *ids,
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DrivenEngine::drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv) {
|
|
||||||
event_init(std::string_view(srcpk, srcpklen), argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrivenEngine::drv_clear_new_outgoing() {
|
void DrivenEngine::drv_clear_new_outgoing() {
|
||||||
new_outgoing_.clear();
|
new_outgoing_.clear();
|
||||||
@@ -569,7 +566,7 @@ static void drv_get_animation_queues(EngineWrapper *w, uint32_t count, const int
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
static void play_initialize(EngineWrapper *w, uint32_t argc, char **argv, uint32_t srcpklen, const char *srcpk, const char *logfn) {
|
static void play_initialize(EngineWrapper *w, const char *engtype, const char *logfn) {
|
||||||
if (w->engine != nullptr) {
|
if (w->engine != nullptr) {
|
||||||
return reset_wrapper(w, "Cannot initialize wrapper, it's already initialized.");
|
return reset_wrapper(w, "Cannot initialize wrapper, it's already initialized.");
|
||||||
}
|
}
|
||||||
@@ -590,63 +587,31 @@ static void play_initialize(EngineWrapper *w, uint32_t argc, char **argv, uint32
|
|||||||
// If we have a logfile, then log this initialization.
|
// If we have a logfile, then log this initialization.
|
||||||
if (w->wlog != nullptr) {
|
if (w->wlog != nullptr) {
|
||||||
w->wlog->write_cmd_hash(PLAY_INITIALIZE, eng::memhash());
|
w->wlog->write_cmd_hash(PLAY_INITIALIZE, eng::memhash());
|
||||||
w->wlog->write_uint32(argc);
|
w->wlog->write_string(engtype);
|
||||||
for (uint32_t i = 0; i < argc; i++) {
|
|
||||||
w->wlog->write_string(argv[i]);
|
|
||||||
}
|
|
||||||
w->wlog->write_string(std::string_view(srcpk, srcpklen));
|
|
||||||
w->wlog->flush();
|
w->wlog->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the engine of the appropriate type.
|
// Create the engine of the appropriate type.
|
||||||
if (argc < 1) {
|
w->engine = make_engine(engtype);
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "Must pass an engine type on the command line. Known types:\n";
|
|
||||||
for (auto reg = DrivenEngineReg::All; reg != nullptr; reg=reg->next) {
|
|
||||||
oss << " " << reg->name << std::endl;
|
|
||||||
}
|
|
||||||
std::string err = oss.str();
|
|
||||||
return reset_wrapper(w, err.c_str());
|
|
||||||
}
|
|
||||||
w->engine = make_engine(argv[0]);
|
|
||||||
if (w->engine == nullptr) {
|
if (w->engine == nullptr) {
|
||||||
return reset_wrapper(w, "No such driven engine type: %s", argv[0]);
|
return reset_wrapper(w, "No such driven engine type: %s", engtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the engine initialization sequence.
|
|
||||||
w->engine->drv_initialize(srcpklen, srcpk, argc - 1, argv + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void replay_initialize(EngineWrapper *w) {
|
static void replay_initialize(EngineWrapper *w) {
|
||||||
assert(w->rlog != nullptr);
|
assert(w->rlog != nullptr);
|
||||||
std::vector<std::string> argvstr;
|
std::string engtype = w->rlog->read_string();
|
||||||
uint32_t argc = w->rlog->read_uint32();
|
|
||||||
for (uint32_t i = 0; i < argc; i++) {
|
|
||||||
argvstr.push_back(w->rlog->read_string());
|
|
||||||
}
|
|
||||||
std::string srcpk = w->rlog->read_string();
|
|
||||||
|
|
||||||
if (!w->rlog->good()) {
|
if (!w->rlog->good()) {
|
||||||
return reset_wrapper(w, "replay log corrupt in replay_initialize");
|
return reset_wrapper(w, "replay log corrupt in replay_initialize");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to convert the argument vector from an array
|
|
||||||
// of C++ strings into the canonical argc, argv format.
|
|
||||||
std::vector<char *> argvec;
|
|
||||||
for (uint32_t i = 0; i < argc; i++) {
|
|
||||||
argvec.push_back(&argvstr[i][0]);
|
|
||||||
}
|
|
||||||
char **argv = &argvec[0];
|
|
||||||
|
|
||||||
// Create the engine.
|
// Create the engine.
|
||||||
w->engine = make_engine(argv[0]);
|
w->engine = make_engine(engtype.c_str());
|
||||||
if (w->engine == nullptr) {
|
if (w->engine == nullptr) {
|
||||||
return reset_wrapper(w, "No such driven engine type: %s", argvstr[0]);
|
return reset_wrapper(w, "No such driven engine type: %s", engtype.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
w->engine->drv_initialize(srcpk.size(), srcpk.c_str(), argc - 1, argv + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -142,11 +142,6 @@ public:
|
|||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// The init callback. You may override this in a subclass.
|
|
||||||
// This will be called once at program initialization.
|
|
||||||
//
|
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) = 0;
|
|
||||||
|
|
||||||
// The call-function callback. This is invoked whenever drv_access
|
// The call-function callback. This is invoked whenever drv_access
|
||||||
// is called. This is the main entry point for "general" access into the
|
// is called. This is the main entry point for "general" access into the
|
||||||
// DrivenEngine. The datapk parameter can contain any arbitrary data needed
|
// DrivenEngine. The datapk parameter can contain any arbitrary data needed
|
||||||
@@ -289,7 +284,6 @@ public:
|
|||||||
void drv_get_tangibles_near(int64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids);
|
void drv_get_tangibles_near(int64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids);
|
||||||
void drv_get_animation_queues(uint32_t count, const int64_t *ids, uint32_t *lengths, const char **strings);
|
void drv_get_animation_queues(uint32_t count, const int64_t *ids, uint32_t *lengths, const char **strings);
|
||||||
|
|
||||||
void drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv);
|
|
||||||
void drv_clear_new_outgoing();
|
void drv_clear_new_outgoing();
|
||||||
void drv_sent_outgoing(uint32_t chid, uint32_t nbytes);
|
void drv_sent_outgoing(uint32_t chid, uint32_t nbytes);
|
||||||
void drv_recv_incoming(uint32_t chid, uint32_t nbytes, const char *bytes);
|
void drv_recv_incoming(uint32_t chid, uint32_t nbytes, const char *bytes);
|
||||||
|
|||||||
@@ -22,21 +22,12 @@ static void dump_lines(StreamBuffer *in, StreamBuffer *out, int chid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test is the minimal possible DrivenEngine.
|
|
||||||
class DriverStubTest : public DrivenEngine {
|
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
|
||||||
stop_driver();
|
|
||||||
}
|
|
||||||
virtual void event_update() override {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This test connects to a public webserver and prints
|
// This test connects to a public webserver and prints
|
||||||
// the output from the server.
|
// the output from the server.
|
||||||
class DriverWebServerTest : public DrivenEngine {
|
class DriverWebServerTest : public DrivenEngine {
|
||||||
public:
|
public:
|
||||||
eng::vector<SharedChannel> channels_;
|
eng::vector<SharedChannel> channels_;
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
DriverWebServerTest() {
|
||||||
SharedChannel ch = new_outgoing_channel("cert:stanford.edu:443");
|
SharedChannel ch = new_outgoing_channel("cert:stanford.edu:443");
|
||||||
ch->out()->write_bytes("GET https://stanford.edu/xbanankjdsh.html HTTP/1.1\n\n");
|
ch->out()->write_bytes("GET https://stanford.edu/xbanankjdsh.html HTTP/1.1\n\n");
|
||||||
channels_.emplace_back(std::move(ch));
|
channels_.emplace_back(std::move(ch));
|
||||||
@@ -62,7 +53,7 @@ public:
|
|||||||
class DriverDNSFailTest : public DrivenEngine {
|
class DriverDNSFailTest : public DrivenEngine {
|
||||||
public:
|
public:
|
||||||
eng::vector<SharedChannel> channels_;
|
eng::vector<SharedChannel> channels_;
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
DriverDNSFailTest() {
|
||||||
SharedChannel ch = new_outgoing_channel("akjsdkajshdakjshd.alk:80");
|
SharedChannel ch = new_outgoing_channel("akjsdkajshdakjshd.alk:80");
|
||||||
ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n");
|
ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n");
|
||||||
channels_.emplace_back(std::move(ch));
|
channels_.emplace_back(std::move(ch));
|
||||||
@@ -89,7 +80,7 @@ class DriverPrintClockTest : public DrivenEngine {
|
|||||||
public:
|
public:
|
||||||
int count_;
|
int count_;
|
||||||
double last_clock_;
|
double last_clock_;
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
DriverPrintClockTest() {
|
||||||
count_ = 0;
|
count_ = 0;
|
||||||
last_clock_ = 0.0;
|
last_clock_ = 0.0;
|
||||||
}
|
}
|
||||||
@@ -111,21 +102,29 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
class RunUnitTests : public DrivenEngine {
|
class RunUnitTests : public DrivenEngine {
|
||||||
private:
|
public:
|
||||||
UniqueWorld world_;
|
UniqueWorld world_;
|
||||||
|
|
||||||
void event_init(std::string_view srcpk, int argc, char *argv[]) override
|
RunUnitTests() {
|
||||||
{
|
|
||||||
world_.reset(new World(WORLD_TYPE_MASTER));
|
world_.reset(new World(WORLD_TYPE_MASTER));
|
||||||
world_->update_source(srcpk);
|
|
||||||
world_->run_unittests();
|
|
||||||
stop_driver();
|
stop_driver();
|
||||||
|
rescan_lua_source();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void event_access(AccessKind kind, int64_t place_id, std::string_view datapk, StreamBuffer *retpk) override {
|
||||||
|
switch (kind) {
|
||||||
|
case AccessKind::INVOKE_LUA_SOURCE: {
|
||||||
|
world_->update_source(datapk);
|
||||||
|
world_->run_unittests();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_update() override {}
|
void event_update() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
DrivenEngineDefine("driverstubtest", DriverStubTest);
|
|
||||||
DrivenEngineDefine("driverwebservertest", DriverWebServerTest);
|
DrivenEngineDefine("driverwebservertest", DriverWebServerTest);
|
||||||
DrivenEngineDefine("driverdnsfailtest", DriverDNSFailTest);
|
DrivenEngineDefine("driverdnsfailtest", DriverDNSFailTest);
|
||||||
DrivenEngineDefine("driverprintclocktest", DriverPrintClockTest);
|
DrivenEngineDefine("driverprintclocktest", DriverPrintClockTest);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ enum class AccessKind {
|
|||||||
INVOKE_TICK,
|
INVOKE_TICK,
|
||||||
INVOKE_LUA_SOURCE,
|
INVOKE_LUA_SOURCE,
|
||||||
PROBE_LUA_CALL,
|
PROBE_LUA_CALL,
|
||||||
|
CONNECT_TO_SERVER,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrivenEngine;
|
class DrivenEngine;
|
||||||
@@ -154,15 +155,11 @@ struct EngineWrapper {
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Create the driven engine. argc and argv allow you to specify what
|
// Create the driven engine. You must specify the type of engine you
|
||||||
// kind of engine you want. You must pass in the initial state of the lua
|
// want (typically 'lpxserver' or 'lpxclient'), and a filename for the
|
||||||
// source, if you have any. You may optionally also specify a replay log.
|
// logfile.
|
||||||
// If you don't want to create a replay log, pass a null pointer.
|
|
||||||
//
|
//
|
||||||
// Check to see if the error buffer contains a message after calling
|
void (*play_initialize)(EngineWrapper *w, const char *engtype, const char *logfn);
|
||||||
// this function.
|
|
||||||
//
|
|
||||||
void (*play_initialize)(EngineWrapper *w, uint32_t argc, char **argv, uint32_t srcpklen, const char *srcpk, const char *logfn);
|
|
||||||
|
|
||||||
// Clear the list of recently-opened channels. You are meant to fetch
|
// Clear the list of recently-opened channels. You are meant to fetch
|
||||||
// new outgoing channels using get_new_outgoing, then you call
|
// new outgoing channels using get_new_outgoing, then you call
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ public:
|
|||||||
eng::vector<Invocation> delayed_invocations_;
|
eng::vector<Invocation> delayed_invocations_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
LpxClient() {
|
||||||
|
set_console_prompt(console_.get_prompt());
|
||||||
|
|
||||||
|
set_initial_state_standalone();
|
||||||
|
}
|
||||||
|
|
||||||
void set_initial_state_connect(const eng::string &hostspec) {
|
void set_initial_state_connect(const eng::string &hostspec) {
|
||||||
// Create the world model.
|
// Create the world model.
|
||||||
world_.reset(new World(WORLD_TYPE_PREDICTIVE));
|
world_.reset(new World(WORLD_TYPE_PREDICTIVE));
|
||||||
@@ -46,21 +52,16 @@ public:
|
|||||||
print_channeler_.reset();
|
print_channeler_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_initial_state_standalone(std::string_view srcpk) {
|
void set_initial_state_standalone() {
|
||||||
// Create the world model.
|
// Create the world model.
|
||||||
world_.reset(new World(WORLD_TYPE_MASTER));
|
world_.reset(new World(WORLD_TYPE_MASTER));
|
||||||
|
|
||||||
// Update the source code of the master model.
|
|
||||||
world_->update_source(srcpk);
|
|
||||||
|
|
||||||
// Make sure the channel is empty.
|
// Make sure the channel is empty.
|
||||||
channel_.reset();
|
channel_.reset();
|
||||||
|
|
||||||
// Create the standalone actor.
|
// Create the standalone actor.
|
||||||
actor_id_ = world_->create_login_actor();
|
actor_id_ = world_->create_login_actor();
|
||||||
|
|
||||||
// TODO: initialize the standalone actor.
|
|
||||||
|
|
||||||
// Clear the unack command queue.
|
// Clear the unack command queue.
|
||||||
unack_.clear();
|
unack_.clear();
|
||||||
|
|
||||||
@@ -69,8 +70,10 @@ public:
|
|||||||
|
|
||||||
// Reset the print channeler
|
// Reset the print channeler
|
||||||
print_channeler_.reset();
|
print_channeler_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
|
// Trigger lua source loading.
|
||||||
|
rescan_lua_source();
|
||||||
|
}
|
||||||
|
|
||||||
// When the world is in synchronous mode, there's no
|
// When the world is in synchronous mode, there's no
|
||||||
// snapshot, and the commands in the unack queue are not
|
// snapshot, and the commands in the unack queue are not
|
||||||
@@ -96,37 +99,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void abandon_server() {
|
void abandon_server() {
|
||||||
// When we abandon the server, we leave the world model
|
if (channel_)
|
||||||
// hanging around to preserve the invariant that there
|
{
|
||||||
// is always a world model. Then, we trigger a rescan
|
set_initial_state_standalone();
|
||||||
// of the lua source. When the lua source shows up, then
|
|
||||||
// we will create a standalone model to replace the client
|
|
||||||
// model.
|
|
||||||
|
|
||||||
channel_.reset();
|
|
||||||
rescan_lua_source();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) {
|
|
||||||
// Put the world into the starting state.
|
|
||||||
set_initial_state_standalone(srcpk);
|
|
||||||
|
|
||||||
// Set the console prompt
|
|
||||||
set_console_prompt(console_.get_prompt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_invocation(const Invocation &inv) {
|
void send_invocation(const Invocation &inv) {
|
||||||
if (channel_ == nullptr) {
|
if (channel_ == nullptr) {
|
||||||
if ((!world_->is_authoritative()) && (inv.kind() == AccessKind::INVOKE_LUA_SOURCE)) {
|
|
||||||
// We have a client model, but no client connection. That means we're
|
|
||||||
// in the process of shutting down a client model. The client model
|
|
||||||
// is supposed to linger until the lua source is reread. Once we have
|
|
||||||
// the lua source, we're supposed to throw out the client model and
|
|
||||||
// create a standalone model.
|
|
||||||
set_initial_state_standalone(inv.datapack());
|
|
||||||
} else {
|
|
||||||
world_->invoke(inv);
|
world_->invoke(inv);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
world_to_asynchronous();
|
world_to_asynchronous();
|
||||||
world_->invoke(inv);
|
world_->invoke(inv);
|
||||||
@@ -247,14 +228,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void event_access(AccessKind kind, int64_t place_id, std::string_view datapk, StreamBuffer *retpk) override {
|
virtual void event_access(AccessKind kind, int64_t place_id, std::string_view datapk, StreamBuffer *retpk) override {
|
||||||
|
if (place_id == 0) place_id = actor_id_;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
case AccessKind::INVOKE_LUA_CALL:
|
||||||
|
case AccessKind::INVOKE_LUA_EXPR:
|
||||||
|
case AccessKind::INVOKE_FLUSH_PRINTS:
|
||||||
|
case AccessKind::INVOKE_TICK:
|
||||||
|
case AccessKind::INVOKE_LUA_SOURCE: {
|
||||||
|
delayed_invocations_.emplace_back(kind, actor_id_, place_id, datapk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case AccessKind::PROBE_LUA_CALL: {
|
case AccessKind::PROBE_LUA_CALL: {
|
||||||
world_to_asynchronous();
|
world_to_asynchronous();
|
||||||
world_->probe_lua_call(actor_id_, place_id, datapk, retpk);
|
world_->probe_lua_call(actor_id_, place_id, datapk, retpk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case AccessKind::CONNECT_TO_SERVER: {
|
||||||
|
set_initial_state_connect(util::ss("nocert:", datapk, ":8085"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
delayed_invocations_.emplace_back(kind, actor_id_, place_id, datapk);
|
stdostream() << "Invalid event_access: " << int(kind) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,24 +29,19 @@ public:
|
|||||||
PrintChanneler print_channeler_;
|
PrintChanneler print_channeler_;
|
||||||
HttpChannelMap http_client_channels_;
|
HttpChannelMap http_client_channels_;
|
||||||
HttpChannelVec http_server_channels_;
|
HttpChannelVec http_server_channels_;
|
||||||
int64_t admin_id_;
|
|
||||||
int next_diff_chan_;
|
|
||||||
double next_tick_;
|
|
||||||
eng::vector<Invocation> delayed_invocations_;
|
eng::vector<Invocation> delayed_invocations_;
|
||||||
|
int64_t admin_id_ = 0;
|
||||||
|
double next_tick_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
LpxServer()
|
||||||
|
{
|
||||||
// Create the master world model.
|
// Create the master world model.
|
||||||
master_.reset(new World(WORLD_TYPE_MASTER));
|
master_.reset(new World(WORLD_TYPE_MASTER));
|
||||||
|
|
||||||
// Update the source code of the master model.
|
// Create the admin actor. Note: there isn't any 'init' function yet.
|
||||||
master_->update_source(srcpk);
|
|
||||||
|
|
||||||
// Create an actor for administrative commands.
|
|
||||||
admin_id_ = master_->create_login_actor();
|
admin_id_ = master_->create_login_actor();
|
||||||
|
|
||||||
// TODO: initialize the admin actor.
|
|
||||||
|
|
||||||
// Print out admin ID for debugging purposes.
|
// Print out admin ID for debugging purposes.
|
||||||
stdostream() << "Admin actor id = " << admin_id_ << std::endl;
|
stdostream() << "Admin actor id = " << admin_id_ << std::endl;
|
||||||
|
|
||||||
@@ -62,8 +57,8 @@ public:
|
|||||||
// Export stuff to the graphics engine.
|
// Export stuff to the graphics engine.
|
||||||
set_visible_world_and_actor(master_.get(), admin_id_);
|
set_visible_world_and_actor(master_.get(), admin_id_);
|
||||||
|
|
||||||
// for ticking.
|
// Trigger the loading of the lua source.
|
||||||
next_tick_ = 0.0;
|
rescan_lua_source();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void do_syntax_error(std::string_view error) override {
|
virtual void do_syntax_error(std::string_view error) override {
|
||||||
@@ -91,35 +86,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void do_work_command() override {
|
virtual void do_work_command() override {
|
||||||
master_->snapshot();
|
do_unknown_command("work");
|
||||||
StreamBuffer datapack;
|
|
||||||
StreamBuffer retvals;
|
|
||||||
datapack.write_string("engio");
|
|
||||||
datapack.write_string("myfunction");
|
|
||||||
datapack.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
|
||||||
datapack.write_double(3.7);
|
|
||||||
datapack.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
|
||||||
datapack.write_string("banana");
|
|
||||||
datapack.write_simple_dynamic_tag(SimpleDynamicTag::BOOLEAN);
|
|
||||||
datapack.write_bool(true);
|
|
||||||
master_->probe_lua_call(admin_id_, admin_id_, datapack.view(), &retvals);
|
|
||||||
while (!retvals.empty()) {
|
|
||||||
SimpleDynamicValue value;
|
|
||||||
retvals.read_simple_dynamic(&value);
|
|
||||||
if (value.type == SimpleDynamicTag::NUMBER) {
|
|
||||||
util::dprint("retval: ", value.x);
|
|
||||||
} else if (value.type == SimpleDynamicTag::STRING) {
|
|
||||||
util::dprint("retval: ", value.s);
|
|
||||||
} else if (value.type == SimpleDynamicTag::BOOLEAN) {
|
|
||||||
util::dprint(value.x ? "retval: true" : "retval: false");
|
|
||||||
} else if (value.type == SimpleDynamicTag::VECTOR) {
|
|
||||||
util::dprint("retval: ", value.x, " ", value.y, " ", value.z);
|
|
||||||
} else {
|
|
||||||
util::dprint("retval: invalid");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master_->rollback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void do_display_command() override {
|
virtual void do_display_command() override {
|
||||||
@@ -194,7 +161,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void event_access(AccessKind kind, int64_t place_id, std::string_view datapk, StreamBuffer *retpk) override {
|
virtual void event_access(AccessKind kind, int64_t place_id, std::string_view datapk, StreamBuffer *retpk) override {
|
||||||
|
if (place_id == 0) place_id = admin_id_;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
case AccessKind::INVOKE_LUA_CALL:
|
||||||
|
case AccessKind::INVOKE_LUA_EXPR:
|
||||||
|
case AccessKind::INVOKE_FLUSH_PRINTS:
|
||||||
|
case AccessKind::INVOKE_TICK:
|
||||||
|
case AccessKind::INVOKE_LUA_SOURCE: {
|
||||||
|
delayed_invocations_.emplace_back(kind, admin_id_, place_id, datapk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case AccessKind::PROBE_LUA_CALL: {
|
case AccessKind::PROBE_LUA_CALL: {
|
||||||
master_->snapshot();
|
master_->snapshot();
|
||||||
master_->probe_lua_call(admin_id_, place_id, datapk, retpk);
|
master_->probe_lua_call(admin_id_, place_id, datapk, retpk);
|
||||||
@@ -202,7 +178,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
delayed_invocations_.emplace_back(kind, admin_id_, place_id, datapk);
|
stdostream() << "Invalid event_access: " << int(kind) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -546,44 +546,49 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
// some lua source file tries to modify, say, tangible state
|
// some lua source file tries to modify, say, tangible state
|
||||||
// in top-level code.
|
// in top-level code.
|
||||||
//
|
//
|
||||||
void World::rebuild_sourcedb() {
|
bool World::rebuild_sourcedb() {
|
||||||
|
bool ok = true;
|
||||||
for (const eng::string &mod: source_db_.modules()) {
|
for (const eng::string &mod: source_db_.modules()) {
|
||||||
open_lthread_state(0, 0, 0, false, true);
|
open_lthread_state(0, 0, 0, false, true);
|
||||||
eng::string err = source_db_.rebuild_module(mod);
|
eng::string err = source_db_.rebuild_module(mod);
|
||||||
eng::string prints = lthread_prints_->str();
|
eng::string prints = lthread_prints_->str();
|
||||||
lthread_prints_.reset();
|
lthread_prints_.reset();
|
||||||
close_lthread_state();
|
close_lthread_state();
|
||||||
|
if (!err.empty()) ok = false;
|
||||||
if (!err.empty() || !prints.empty()) {
|
if (!err.empty() || !prints.empty()) {
|
||||||
util::dprint("Loading Module ", mod);
|
util::dprint("Loading Module ", mod);
|
||||||
if (!err.empty()) util::dprint(err);
|
if (!err.empty()) util::dprint(err);
|
||||||
if (!prints.empty()) util::dprint(prints);
|
if (!prints.empty()) util::dprint(prints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::update_source(const util::LuaSourceVec &source) {
|
bool World::update_source(const util::LuaSourceVec &source) {
|
||||||
assert(stack_is_clear());
|
assert(stack_is_clear());
|
||||||
source_db_.update(source);
|
source_db_.update(source);
|
||||||
rebuild_sourcedb();
|
return rebuild_sourcedb();
|
||||||
assert(stack_is_clear());
|
assert(stack_is_clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::update_source(const util::LuaSourcePtr &source) {
|
bool World::update_source(const util::LuaSourcePtr &source) {
|
||||||
if (source != nullptr) {
|
if (source == nullptr) {
|
||||||
update_source(*source);
|
return false;
|
||||||
}
|
}
|
||||||
|
return update_source(*source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::update_source(std::string_view sourcepack) {
|
bool World::update_source(std::string_view sourcepack) {
|
||||||
if (!sourcepack.empty()) {
|
if (sourcepack.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
StreamBuffer sb(sourcepack);
|
StreamBuffer sb(sourcepack);
|
||||||
util::LuaSourceVec sv;
|
util::LuaSourceVec sv;
|
||||||
SourceDB::deserialize_source(&sv, &sb);
|
SourceDB::deserialize_source(&sv, &sb);
|
||||||
update_source(sv);
|
return update_source(sv);
|
||||||
} catch (const StreamException &ex) {
|
} catch (const StreamException &ex) {
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,11 +965,40 @@ void World::invoke_tick(int64_t actor_id, int64_t place_id, std::string_view dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_view datapack) {
|
void World::invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_view datapack) {
|
||||||
if (!is_authoritative()) {
|
// Sanity check arguments.
|
||||||
return;
|
// We also need some kind of authentication here.
|
||||||
|
if (!is_authoritative()) return;
|
||||||
|
if (actor_id != place_id) return;
|
||||||
|
|
||||||
|
// Check if this is the first time we're loading the source.
|
||||||
|
bool brand_new = (source_db_.modules().size() == 1);
|
||||||
|
|
||||||
|
// Compile and load the source.
|
||||||
|
bool success = update_source(datapack);
|
||||||
|
|
||||||
|
// Call world.init
|
||||||
|
if (brand_new) {
|
||||||
|
if (success) {
|
||||||
|
{
|
||||||
|
lua_State *L = state();
|
||||||
|
LuaVar lclass, lfunc;
|
||||||
|
LuaExtStack LS(L, lclass, lfunc);
|
||||||
|
|
||||||
|
LS.getclass(lclass, "world");
|
||||||
|
if (LS.classname(lclass) != "") {
|
||||||
|
LS.rawget(lfunc, lclass, "init");
|
||||||
|
spawn(LS, actor_id, place_id, lfunc, 0, false);
|
||||||
}
|
}
|
||||||
// We need some kind of authentication here.
|
}
|
||||||
update_source(datapack);
|
run_scheduled_threads();
|
||||||
|
} else {
|
||||||
|
util::dprint("Did not run world.init because of lua errors.");
|
||||||
|
util::dprint("You will need to fix the errors then run it manually.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the new thread and return.
|
||||||
|
assert(stack_is_clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::guard_blockable(lua_State *L, const char *fn) {
|
void World::guard_blockable(lua_State *L, const char *fn) {
|
||||||
|
|||||||
@@ -216,11 +216,11 @@ public:
|
|||||||
// This is used to create a temporary actor which is used during
|
// This is used to create a temporary actor which is used during
|
||||||
// the login process.
|
// the login process.
|
||||||
//
|
//
|
||||||
// If this is a master model, The function 'login.initialize'
|
// If this is a master model, The function 'login.init'
|
||||||
// called. Then, the following login flags are set:
|
// called. Then, the following login flags are set:
|
||||||
// can_be_controlled, is_controlled, and delete_on_disconnect.
|
// can_be_controlled, is_controlled, and delete_on_disconnect.
|
||||||
//
|
//
|
||||||
// In a client model, 'login.initialize' is not called,
|
// In a client model, 'login.init' is not called,
|
||||||
// and the login flags are not used in client models.
|
// and the login flags are not used in client models.
|
||||||
//
|
//
|
||||||
int64_t create_login_actor();
|
int64_t create_login_actor();
|
||||||
@@ -265,19 +265,21 @@ public:
|
|||||||
//
|
//
|
||||||
const PrintBuffer *get_printbuffer(int64_t actor_id);
|
const PrintBuffer *get_printbuffer(int64_t actor_id);
|
||||||
|
|
||||||
// Update the source database from disk.
|
// Rebuild the global environment from the source database.
|
||||||
|
//
|
||||||
|
// Returns true if the rebuild goes without errors.
|
||||||
|
//
|
||||||
|
bool rebuild_sourcedb();
|
||||||
|
|
||||||
|
// Update the source database from disk, then rebuild the global environment.
|
||||||
//
|
//
|
||||||
// Special case: if the source pointer is nullptr, does not update.
|
// Special case: if the source pointer is nullptr, does not update.
|
||||||
// The final form takes a sourcepk, a serialized representation
|
|
||||||
// of a LuaSourceVec.
|
|
||||||
//
|
//
|
||||||
void update_source(const util::LuaSourceVec &source);
|
// Returns true if the update goes without errors.
|
||||||
void update_source(const util::LuaSourcePtr &source);
|
|
||||||
void update_source(std::string_view sourcepk);
|
|
||||||
|
|
||||||
// Rebuild the source database.
|
|
||||||
//
|
//
|
||||||
void rebuild_sourcedb();
|
bool update_source(const util::LuaSourceVec &source);
|
||||||
|
bool update_source(const util::LuaSourcePtr &source);
|
||||||
|
bool update_source(std::string_view sourcepk);
|
||||||
|
|
||||||
// Supply an HTTP response to an outstanding HTTP request.
|
// Supply an HTTP response to an outstanding HTTP request.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -646,14 +646,8 @@ class Driver {
|
|||||||
ssl_load_certificate_authorities(ssl_client_secure_ctx_.get());
|
ssl_load_certificate_authorities(ssl_client_secure_ctx_.get());
|
||||||
sslutil::ctx_load_dummy_cert(ssl_server_ctx_.get());
|
sslutil::ctx_load_dummy_cert(ssl_server_ctx_.get());
|
||||||
|
|
||||||
// Read the initial lua source code.
|
|
||||||
drvutil::ostringstream srcpak;
|
|
||||||
std::string srcpakerr = drvutil::package_lua_source(luprexroot, &srcpak);
|
|
||||||
if_error_print_and_exit(srcpakerr);
|
|
||||||
|
|
||||||
// Initialize the engine.
|
// Initialize the engine.
|
||||||
std::string_view srcpakv = srcpak.view();
|
engw.play_initialize(&engw, argv[0], replaylogfn.c_str());
|
||||||
engw.play_initialize(&engw, argc, argv, srcpakv.size(), srcpakv.data(), replaylogfn.c_str());
|
|
||||||
if_error_print_and_exit(engw.error);
|
if_error_print_and_exit(engw.error);
|
||||||
|
|
||||||
// Set up listening ports.
|
// Set up listening ports.
|
||||||
|
|||||||
@@ -1,14 +1,23 @@
|
|||||||
|
makeclass("world")
|
||||||
makeclass('login')
|
makeclass('login')
|
||||||
makeclass("engio")
|
makeclass("engio")
|
||||||
makeclass('cube')
|
makeclass('cube')
|
||||||
makeclass('sphere')
|
makeclass('sphere')
|
||||||
|
|
||||||
|
-- This gets called on every login except the admin user.
|
||||||
function login.init()
|
function login.init()
|
||||||
local actor = tangible.actor()
|
local actor = tangible.actor()
|
||||||
dprint("login.init:", actor)
|
dprint("login.init:", actor)
|
||||||
tangible.animinit(actor, {bp="character", plane="earth", xyz={0, 0, 90}})
|
tangible.animinit(actor, {bp="character", plane="earth", xyz={0, 0, 90}})
|
||||||
tangible.build{class=cube, xyz={500,-100,0}}
|
end
|
||||||
tangible.build{class=sphere, xyz={500,100,0}}
|
|
||||||
|
-- This gets called on the admin user. You can call login.init in here if you want.
|
||||||
|
function world.init()
|
||||||
|
local actor = tangible.actor()
|
||||||
|
dprint("world.init:", actor)
|
||||||
|
tangible.build{class=cube, plane="earth", xyz={500,-100,0}}
|
||||||
|
tangible.build{class=sphere, plane="earth", xyz={500,100,0}}
|
||||||
|
login.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.move(action, xyz, facing)
|
function engio.move(action, xyz, facing)
|
||||||
|
|||||||
Reference in New Issue
Block a user