CPL command

This commit is contained in:
2026-05-26 15:07:42 -04:00
parent 933c1ac6c3
commit 8dab0d16b7
9 changed files with 64 additions and 47 deletions

Binary file not shown.

View File

@@ -73,7 +73,6 @@ void ALuprexGameModeBase::UpdateConsoleOutput() {
} }
} }
#pragma optimize("", off)
void ALuprexGameModeBase::UpdateTangibles() { void ALuprexGameModeBase::UpdateTangibles() {
double radius = 1000.0; // Hardwired for now. double radius = 1000.0; // Hardwired for now.
using TanArray = UlxTangibleManager::TanArray; using TanArray = UlxTangibleManager::TanArray;
@@ -132,8 +131,9 @@ void ALuprexGameModeBase::UpdatePossessedTangible() {
void ALuprexGameModeBase::UpdateLuaSourceCode() { void ALuprexGameModeBase::UpdateLuaSourceCode() {
FlxLockedWrapper lockedwrap; FlxLockedWrapper lockedwrap;
if (lockedwrap->get_rescan_lua_source(lockedwrap.Get())) if (lockedwrap->get_rescan_lua_source(lockedwrap.Get()) || ReloadSource)
{ {
ReloadSource = false;
drvutil::ostringstream srcpak; drvutil::ostringstream srcpak;
FString LuprexRoot = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex")); FString LuprexRoot = FPaths::Combine(FPaths::ProjectDir(), TEXT("luprex"));
std::string srcpakerr = drvutil::package_lua_source(TCHAR_TO_UTF8(*LuprexRoot), &srcpak); std::string srcpakerr = drvutil::package_lua_source(TCHAR_TO_UTF8(*LuprexRoot), &srcpak);
@@ -259,4 +259,9 @@ ALuprexGameModeBase *ALuprexGameModeBase::FromContext(const UObject *context) {
return result; return result;
} }
void ALuprexGameModeBase::TriggerReloadSource(const UObject *WorldContextObject) {
ALuprexGameModeBase *GameMode = FromContext(WorldContextObject);
GameMode->ReloadSource = true;
}

View File

@@ -63,6 +63,11 @@ public:
// Get the current Luprex Game Mode Base, given a Context object. // Get the current Luprex Game Mode Base, given a Context object.
static ALuprexGameModeBase *FromContext(const UObject *Context); static ALuprexGameModeBase *FromContext(const UObject *Context);
// Set the ReloadSource flag on the current Luprex game mode, causing
// the Lua source to be reloaded on the next tick.
UFUNCTION(BlueprintCallable, Category = "Luprex|Miscellaneous", meta = (WorldContext = "WorldContextObject"))
static void TriggerReloadSource(const UObject *WorldContextObject);
// The sensitivity level at which a log message triggers a debugger breakpoint. // The sensitivity level at which a log message triggers a debugger breakpoint.
UPROPERTY(EditAnywhere, Category="Debugging Tools") UPROPERTY(EditAnywhere, Category="Debugging Tools")
ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity; ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity;
@@ -76,6 +81,9 @@ public:
// This is always true unless you use the debugger to set it to false. // This is always true unless you use the debugger to set it to false.
bool TickEnabled = true; bool TickEnabled = true;
// True to trigger a source reload.
bool ReloadSource = false;
// Current Player ID // Current Player ID
int64 PlayerId = 0; int64 PlayerId = 0;

View File

@@ -278,7 +278,6 @@ void SourceDB::update(const util::LuaSourceVec &source) {
for (int i = 0; i < int(source.size()); i++) { for (int i = 0; i < int(source.size()); i++) {
const eng::string &file = source[i].first; const eng::string &file = source[i].first;
const eng::string &code = source[i].second; const eng::string &code = source[i].second;
util::dprint("Compiling ", file);
LS.newtable(info); LS.newtable(info);
LS.rawset(info, "name", file); LS.rawset(info, "name", file);
LS.rawset(info, "code", code); LS.rawset(info, "code", code);

View File

@@ -55,7 +55,7 @@ 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 {
switch (kind) { switch (kind) {
case AccessKind::INVOKE_LUA_SOURCE: { case AccessKind::INVOKE_LUA_SOURCE: {
world_->update_source(datapk); world_->update_source(datapk, 0);
run_unittests(world_->state()); run_unittests(world_->state());
stop_driver(); stop_driver();
break; break;

View File

@@ -523,6 +523,9 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
// This is called from World::update_source, and also // This is called from World::update_source, and also
// from World::patch_source in the difference transmitter. // from World::patch_source in the difference transmitter.
// //
// When called from the difference transmitter, we suppress
// error messages.
//
// For the moment, errors are channeled to util::dprint, // For the moment, errors are channeled to util::dprint,
// and 'print' statements just go to std::cerr. Neither // and 'print' statements just go to std::cerr. Neither
// of these is ideal. We need to get serious about setting // of these is ideal. We need to get serious about setting
@@ -532,7 +535,7 @@ 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.
// //
bool World::rebuild_sourcedb() { bool World::rebuild_sourcedb(int64_t actor_id) {
bool ok = true; 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); open_lthread_state(0, 0, 0, false);
@@ -540,30 +543,28 @@ bool World::rebuild_sourcedb() {
eng::string prints = lthread_prints_.str(); eng::string prints = lthread_prints_.str();
clear_lthread_state(); clear_lthread_state();
if (!err.empty()) ok = false; if (!err.empty()) ok = false;
if (!err.empty() || !prints.empty()) { if (actor_id >= 0) {
util::dprint("Loading Module ", mod); lthread_prints_ << "Compiling " << mod << std::endl;
if (!err.empty()) util::dprint(err); if (!err.empty()) lthread_prints_ << err << std::endl;
if (!prints.empty()) util::dprint(prints); if (!prints.empty()) lthread_prints_ << prints;
lthread_prints_to_actor(actor_id);
} }
} }
if (actor_id > 0) {
lthread_prints_ << (ok ? "Compilation Successful." : "Compilation Failed.") << std::endl;
lthread_prints_to_actor(actor_id);
}
return ok; return ok;
} }
bool World::update_source(const util::LuaSourceVec &source) { bool World::update_source(const util::LuaSourceVec &source, int64_t actor_id) {
assert(stack_is_clear()); assert(stack_is_clear());
source_db_.update(source); source_db_.update(source);
return rebuild_sourcedb(); return rebuild_sourcedb(actor_id);
assert(stack_is_clear()); assert(stack_is_clear());
} }
bool World::update_source(const util::LuaSourcePtr &source) { bool World::update_source(std::string_view sourcepack, int64_t actor_id) {
if (source == nullptr) {
return false;
}
return update_source(*source);
}
bool World::update_source(std::string_view sourcepack) {
if (sourcepack.empty()) { if (sourcepack.empty()) {
return false; return false;
} }
@@ -571,7 +572,7 @@ bool World::update_source(std::string_view sourcepack) {
StreamBuffer sb(sourcepack); StreamBuffer sb(sourcepack);
util::LuaSourceVec sv; util::LuaSourceVec sv;
SourceDB::deserialize_source(&sv, &sb); SourceDB::deserialize_source(&sv, &sb);
return update_source(sv); return update_source(sv, actor_id);
} catch (const StreamException &ex) { } catch (const StreamException &ex) {
return false; return false;
} }
@@ -697,7 +698,7 @@ HttpServerResponse World::http_serve(const HttpParser &request) {
open_lthread_state(0, 0, 0, false); open_lthread_state(0, 0, 0, false);
eng::string msg = traceback_pcall(L, 1, LUA_MULTRET); eng::string msg = traceback_pcall(L, 1, LUA_MULTRET);
if (!msg.empty()) lthread_prints_ << msg << std::endl; if (!msg.empty()) lthread_prints_ << msg << std::endl;
lthread_prints_to_dprint(); lthread_prints_to_actor(0);
clear_lthread_state(); clear_lthread_state();
// If the call threw an error, return // If the call threw an error, return
@@ -954,7 +955,7 @@ void World::invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_vi
bool brand_new = (source_db_.modules().size() == 1); bool brand_new = (source_db_.modules().size() == 1);
// Compile and load the source. // Compile and load the source.
bool success = update_source(datapack); bool success = update_source(datapack, actor_id);
// Call world.init // Call world.init
if (brand_new) { if (brand_new) {
@@ -1096,7 +1097,7 @@ void World::run_scheduled_threads() {
} }
LS.rawset(threads, sched.thread_id(), LuaNil); LS.rawset(threads, sched.thread_id(), LuaNil);
} }
lthread_prints_to_printbuffer(); lthread_prints_to_actor(lthread_actor_id_);
clear_lthread_state(); clear_lthread_state();
} }
} }
@@ -1162,22 +1163,20 @@ void World::open_lthread_state(int64_t actor, int64_t place, int64_t thread, boo
lthread_prints_.clear(); lthread_prints_.clear();
} }
void World::lthread_prints_to_printbuffer() void World::lthread_prints_to_actor(int64_t actor_id)
{ {
const eng::string &output = lthread_prints_.str(); const eng::string &output = lthread_prints_.str();
if (output.size() > 0) { if (output.size() > 0) {
Tangible *actor = tangible_get(lthread_actor_id_); if (actor_id >= 0) {
if (actor != nullptr) { Tangible *actor = tangible_get(actor_id);
actor->print_buffer_.add_string(output, is_authoritative()); if (actor != nullptr) {
actor->print_buffer_.add_string(output, is_authoritative());
} else {
util::dprintview(output);
}
} }
} lthread_prints_.str("");
} lthread_prints_.clear();
void World::lthread_prints_to_dprint()
{
const eng::string &output = lthread_prints_.str();
if (output.size() > 0) {
util::dprintview(output);
} }
} }

View File

@@ -292,7 +292,7 @@ void World::patch_source(StreamBuffer *sb, DebugCollector *dbc) {
DebugBlock dbb(dbc, "patch_source"); DebugBlock dbb(dbc, "patch_source");
bool modified = source_db_.patch(sb, dbc); bool modified = source_db_.patch(sb, dbc);
if (modified) { if (modified) {
rebuild_sourcedb(); rebuild_sourcedb(-1);
DebugLine(dbc) << "Source DB rebuilt"; DebugLine(dbc) << "Source DB rebuilt";
} }
} }

View File

@@ -284,19 +284,20 @@ public:
// Rebuild the global environment from the source database. // Rebuild the global environment from the source database.
// //
// Error messages go to the specified actor.
//
// Returns true if the rebuild goes without errors. // Returns true if the rebuild goes without errors.
// //
bool rebuild_sourcedb(); bool rebuild_sourcedb(int64_t actor_id);
// Update the source database from disk, then rebuild the global environment. // Update the source database from disk, then rebuild the global environment.
// //
// Special case: if the source pointer is nullptr, does not update. // Error messages go to the specified actor.
// //
// Returns true if the update goes without errors. // Returns true if the update goes without errors.
// //
bool update_source(const util::LuaSourceVec &source); bool update_source(const util::LuaSourceVec &source, int64_t actor_id);
bool update_source(const util::LuaSourcePtr &source); bool update_source(std::string_view sourcepk, int64_t actor_id);
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.
// //
@@ -375,8 +376,13 @@ public:
std::ostream *lthread_print_stream() { return &lthread_prints_; } std::ostream *lthread_print_stream() { return &lthread_prints_; }
void lthread_prints_to_printbuffer(); // Send the lthread_prints output to the specified actor.
void lthread_prints_to_dprint(); //
// If actor_id == (-1) prints are discarded.
// If actor_id == (0) prints go to dprint.
// Anything else, and the prints go to a specific actor.
//
void lthread_prints_to_actor(int64_t actor_id);
// Set a lua global variable. // Set a lua global variable.
// //

View File

@@ -79,7 +79,7 @@ function engio.getlookat()
return "" return ""
end end
print("Hello from login.lua")
function jp3() function jp3()
tangible.animate{tan=actor, anim={action="play", seq="jump"}} tangible.animate{tan=actor, anim={action="play", seq="jump"}}