From 9b304985e320d870f071bc98ae58f7f71f6ccdff Mon Sep 17 00:00:00 2001 From: jyelon Date: Mon, 4 Aug 2025 17:13:34 -0400 Subject: [PATCH] Fix name reuse issues for actors, and make luprex IDs more readable --- Source/Integration/Tangible.cpp | 6 +++++- luprex/cpp/core/eng-tests.cpp | 2 +- luprex/cpp/core/idalloc.cpp | 29 +++++++++++++++-------------- luprex/cpp/core/idalloc.hpp | 18 ++++++++++-------- luprex/cpp/core/world-testing.cpp | 4 ++-- luprex/lua/ut-table.lua | 26 +++++++++++++------------- 6 files changed, 46 insertions(+), 39 deletions(-) diff --git a/Source/Integration/Tangible.cpp b/Source/Integration/Tangible.cpp index 1f65e3af..7f024b8e 100644 --- a/Source/Integration/Tangible.cpp +++ b/Source/Integration/Tangible.cpp @@ -38,6 +38,8 @@ void UlxTangible::DeleteCurrentActor() // Now destroy the actor itself. According to various // documents I've read online, it may be necessary to take // further steps to delete the object. Not clear. + UE_LOG(LogLuprexIntegration, Display, TEXT("Deleting actor: %s"), *CurrentActor->GetName()); + CurrentActor->Rename(nullptr); CurrentActor->Destroy(); // If this actor previously was posessed by a player controller, @@ -75,7 +77,7 @@ void UlxTangible::SetActorBlueprint(const FString &XName) { FActorSpawnParameters params; // Give the new actor a reasonable name. - params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId)); + params.Name = FName(*FString::Printf(TEXT("Tan:%s_%ld"), *Name, TangibleId)); // Currently, the actor is spawned at (0,0,0), which is not good. // We should spawn at the actor's current location. I'll get to it @@ -91,6 +93,8 @@ void UlxTangible::SetActorBlueprint(const FString &XName) { // want to delay that until after we've had a chance to set // up the TangibleComponent. params.bDeferConstruction = true; + params.bNoFail = true; + UE_LOG(LogLuprexIntegration, Display, TEXT("Creating Actor: %s"), *params.Name.ToString()); AActor* a = w->SpawnActor(blueprint, &transform, params); check(a != nullptr); diff --git a/luprex/cpp/core/eng-tests.cpp b/luprex/cpp/core/eng-tests.cpp index 73ab1e26..f50d028d 100644 --- a/luprex/cpp/core/eng-tests.cpp +++ b/luprex/cpp/core/eng-tests.cpp @@ -107,7 +107,6 @@ public: RunUnitTests() { world_.reset(new World(WORLD_TYPE_MASTER)); - stop_driver(); rescan_lua_source(true); } @@ -116,6 +115,7 @@ public: case AccessKind::INVOKE_LUA_SOURCE: { world_->update_source(datapk); world_->run_unittests(); + stop_driver(); break; } default: break; diff --git a/luprex/cpp/core/idalloc.cpp b/luprex/cpp/core/idalloc.cpp index b77c7baa..ef9b2293 100644 --- a/luprex/cpp/core/idalloc.cpp +++ b/luprex/cpp/core/idalloc.cpp @@ -7,6 +7,7 @@ #include +// This is used in some unit tests to make sure that the deque contains the expected values. static bool ranges_equal(const eng::deque &dq, int64_t a, int64_t b, int64_t c) { if (dq.size() != 3) return false; if (dq[0] != a) return false; @@ -27,14 +28,14 @@ IdGlobalPool::~IdGlobalPool() { void IdGlobalPool::init_master() { salvaged_.clear(); - next_batch_ = 0x0001000000000000; - next_id_ = 0x0010000000000000; + next_batch_ = 1000000000000000; + next_id_ = 5000000000000000; } void IdGlobalPool::init_synch() { salvaged_.clear(); next_batch_ = 0; - next_id_ = 0x001E000000000000; + next_id_ = 8000000000000000; } int64_t IdGlobalPool::get_one() { @@ -260,7 +261,7 @@ eng::string IdPlayerPool::debug_string() const { } static int64_t nthbatch(int64_t n) { - return int64_t(0x0001000000000000) + n*256; + return int64_t(1000000000000000) + n*256; } LuaDefine(unittests_idalloc, "", "some unit tests") { @@ -272,15 +273,15 @@ LuaDefine(unittests_idalloc, "", "some unit tests") { // Synchronous pools produce IDs starting at 0x001E000000000000 gp.init_synch(); - LuaAssert(L, gp.get_one() == 0x001E000000000000); - LuaAssert(L, gp.get_one() == 0x001E000000000001); - LuaAssert(L, gp.get_one() == 0x001E000000000002); + LuaAssert(L, gp.get_one() == 8000000000000000); + LuaAssert(L, gp.get_one() == 8000000000000001); + LuaAssert(L, gp.get_one() == 8000000000000002); // Master pools produce IDs starting at 0x0010000000000000 gp.init_master(); - LuaAssert(L, gp.get_one() == 0x0010000000000000); - LuaAssert(L, gp.get_one() == 0x0010000000000001); - LuaAssert(L, gp.get_one() == 0x0010000000000002); + LuaAssert(L, gp.get_one() == 5000000000000000); + LuaAssert(L, gp.get_one() == 5000000000000001); + LuaAssert(L, gp.get_one() == 5000000000000002); // Synchronous pools produce only null batches. gp.init_synch(); @@ -329,7 +330,7 @@ LuaDefine(unittests_idalloc, "", "some unit tests") { pp.set_fifo_capacity(3); pp.refill(); LuaAssert(L, pp.size() == 0); - LuaAssert(L, pp.get_one() == 0x001E000000000000); + LuaAssert(L, pp.get_one() == 8000000000000000); LuaAssert(L, pp.size() == 0); // In the master model, with fifo disabled. Fifo should remain @@ -339,7 +340,7 @@ LuaDefine(unittests_idalloc, "", "some unit tests") { pp.set_fifo_capacity(0); pp.refill(); LuaAssert(L, pp.size() == 0); - LuaAssert(L, pp.get_one() == 0x0010000000000000); + LuaAssert(L, pp.get_one() == 5000000000000000); LuaAssert(L, pp.size() == 0); // Test refill from master (with enabled fifo). @@ -370,13 +371,13 @@ LuaDefine(unittests_idalloc, "", "some unit tests") { // Serialize and deserialize a global pool. gp.init_master(); gpds.init_master(); - LuaAssert(L, gp.get_one() == 0x0010000000000000); + LuaAssert(L, gp.get_one() == 5000000000000000); LuaAssert(L, gp.get_batch() == nthbatch(0)); gp.salvage(nthbatch(182)); gp.salvage(nthbatch(183)); gp.serialize(&sb); gpds.deserialize(&sb); - LuaAssert(L, gpds.get_one() == 0x0010000000000001); + LuaAssert(L, gpds.get_one() == 5000000000000001); LuaAssert(L, gpds.get_batch() == nthbatch(183)); LuaAssert(L, gpds.get_batch() == nthbatch(182)); LuaAssert(L, gpds.get_batch() == nthbatch(1)); diff --git a/luprex/cpp/core/idalloc.hpp b/luprex/cpp/core/idalloc.hpp index c59fa197..6591037e 100644 --- a/luprex/cpp/core/idalloc.hpp +++ b/luprex/cpp/core/idalloc.hpp @@ -37,17 +37,19 @@ // // THE NUMERIC RANGES // -// The largest integer that can be stored losslessly in a lua_Number is: +// Any 53-bit number can be losslessly stored in a lua_Number. In other +// words, the largest integer that can be stored losslessly is: // -// * 0x0020000000000000 +// * 0x001FFFFFFFFFFFFF // -// In other words, any 53-bit number can be stored. We subdivide the range as -// follows: +// As it turns out, that's just barely larger than 9 quadrillion. We are +// going to use IDs that are between 0 and 9 quadrillion. We divide the +// range of possible IDs into several subsections: // -// * 0x0000+ : manually created IDs. -// * 0x0001+ : used by master model's IdGlobalPool to create batches. -// * 0x0010+ : used by master model's IdGlobalPool to create individual IDs. -// * 0x001E+ : used by sync model's IdGlobalPool to create individual IDs. +// 0 quadrillion + : manually created IDs. +// 1 quadrillion + : used by master model's IdGlobalPool to create batches. +// 5 quadrillion + : used by master model's IdGlobalPool to create individual IDs. +// 8 quadrillion + : used by sync model's IdGlobalPool to create individual IDs. // // If you exhaust the Master Model's invididual pool at a rate of 10,000,000 IDs // per second, the individual pool will last for 12 years. diff --git a/luprex/cpp/core/world-testing.cpp b/luprex/cpp/core/world-testing.cpp index 491846c9..2482101a 100644 --- a/luprex/cpp/core/world-testing.cpp +++ b/luprex/cpp/core/world-testing.cpp @@ -393,7 +393,7 @@ LuaDefine(unittests_world3diffluatab, "", "some unit tests") { // The data in the master model should now look like this: const char *expect_123 = - "{ " + "{ " "bacon='crispy', " "inventory={ gold='wealthy' }, " "skills={ " @@ -402,7 +402,7 @@ LuaDefine(unittests_world3diffluatab, "", "some unit tests") { "} " "}"; const char *expect_345 = - "{ " + "{ " "inventory={ gold='poor' }, " "phone='867-5309' " "}"; diff --git a/luprex/lua/ut-table.lua b/luprex/lua/ut-table.lua index 9a043c86..b1be9724 100644 --- a/luprex/lua/ut-table.lua +++ b/luprex/lua/ut-table.lua @@ -35,38 +35,38 @@ function unittests.tables() end function unittests.vectors() - assert(true == table.isvector{1,2,3}) - assert(false == table.isvector{1,2,nil,3}) + assert(true == table.isarray{1,2,3}) + assert(false == table.isarray{1,2,nil,3}) -- check vector.removeall t = {1,2,3,4,5,1,2,3,4,5} - assert(true == vector.removeall(t, 2)) + assert(true == array.removeall(t, 2)) assert(table.equal(t, {1,3,4,5,1,3,4,5})) - assert(false == vector.removeall(t, 7)) + assert(false == array.removeall(t, 7)) assert(table.equal(t, {1,3,4,5,1,3,4,5})) - assert(true == vector.removeall(t, 5)) + assert(true == array.removeall(t, 5)) assert(table.equal(t, {1,3,4,1,3,4})) - assert(true == vector.removeall(t, 1)) + assert(true == array.removeall(t, 1)) assert(table.equal(t, {3,4,3,4})) -- check vector.push t = {} - vector.push(t, 1) + array.push(t, 1) assert(table.equal(t, {1})) - vector.push(t, 2) + array.push(t, 2) assert(table.equal(t, {1,2})) - vector.push(t, 3) + array.push(t, 3) assert(table.equal(t, {1,2,3})) -- check vector.pop t = {1,2,3} - assert(3 == vector.pop(t)) + assert(3 == array.pop(t)) assert(table.equal(t, {1,2})) - assert(2 == vector.pop(t)) + assert(2 == array.pop(t)) assert(table.equal(t, {1})) - assert(1 == vector.pop(t)) + assert(1 == array.pop(t)) assert(table.equal(t, {})) - assert(nil == vector.pop(t)) + assert(nil == array.pop(t)) assert(table.equal(t, {})) end