mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-20 03:32:48 +00:00
fix: brick by brick and model placement work the way the client expects
Mapped from the 1.10.64 client and live captures (docs/BuildWorkflow.md). Model placement (PropertyManagementComponent): - A brick built model placed from the inventory spawned at the world origin with no rotation and without PlaceModelResponse/PreCreate, and was saved to properties_contents with ugc_id 0; it is now placed where the client put it, keeps its UGID and blueprint and is saved with them. - Picking up, putting away and taking apart a brick built model gave it to MODELS_IN_BBB and then deleted it; every way off the property now puts it in MODELS (carried when picked up), as live, with its blueprint config. Taking a premade model apart no longer deletes it either. - Placing and removing a model saves the property at once, so a crash or a disconnect before PropertyEditorEnd does not lose it. - DoneArrangingWithItem only answers when something new is picked (not when leaving), with the subject as build area; SetBuildModeConfirmed's warnVisitors matches live. Brick by brick (BrickByBrick): - BBBLoadItemRequest moves the model to MODELS_IN_BBB keeping its id and fails cleanly when the player has no such model. - MoveInventoryBatch moves bricks between BRICKS and BRICKS_IN_BBB (it was not handled, so the client and server disagreed until a relog). - BBBSaveRequest uses up the opened models, places the new ones through the property, returns the bricks (or uses them with bbb_consume_bricks=1), clears the autosave and sends RequeryPropertyModels. Every save makes new ugc rows (is_optimized 0, so the UGC server processes them). - Quick save: SetBBBAutosave is stored per character (bbb_autosave). - UnUseBBBModel puts a model back on the property where it was when it came from there, otherwise back in MODELS. - Leaving brick mode without a save, a disconnect or a crash: the autosave is rebuilt into models (RebuildBBBAutosaveMsg) or the opened models go back to MODELS. MODELS_IN_BBB is saved with the character now and loads into MODELS, BRICKS_IN_BBB into BRICKS. Fixes #1632 Fixes #159 Fixes #1565 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -386,3 +386,52 @@ TEST_F(BuildingMessagesTests, GoldenBytes) {
|
||||
load.WritePacket(bitStream);
|
||||
EXPECT_PACKET_EQ(FromHex("53 05 00 17 00 00 00 00 01 03 02 00 00 00 00 00 00 de 03 00 00 00 00 00 00"), FromBitStream(bitStream));
|
||||
}
|
||||
|
||||
// Messages added for the brick by brick workflow (docs/BuildWorkflow.md), laid out as the 1.10.64 client reads them.
|
||||
TEST_F(BuildingMessagesTests, BrickModeMessagesRoundTrip) {
|
||||
GameMessages::ActivateBrickMode enter;
|
||||
enter.buildObjectID = 0x1122334455667788;
|
||||
enter.enterBuildFromWorld = false;
|
||||
enter.enterFlag = true;
|
||||
// flag 1 + the build area, flag 0 (build type 2, on a property), 0, 1 (0x00d8ecb0)
|
||||
EXPECT_PACKET_EQ(FromHex("c4 3b b3 2a a2 19 91 08 90", 68), Payload(enter));
|
||||
const auto enterCopy = RoundTrip(enter);
|
||||
EXPECT_EQ(enterCopy.buildObjectID, enter.buildObjectID);
|
||||
EXPECT_EQ(enterCopy.buildType, 2);
|
||||
EXPECT_FALSE(enterCopy.enterBuildFromWorld);
|
||||
EXPECT_TRUE(enterCopy.enterFlag);
|
||||
ExpectTruncatedFails(enter);
|
||||
|
||||
GameMessages::ActivateBrickMode leave;
|
||||
leave.buildType = 1;
|
||||
leave.enterBuildFromWorld = true;
|
||||
leave.enterFlag = false;
|
||||
const auto leaveCopy = RoundTrip(leave);
|
||||
EXPECT_EQ(leaveCopy.buildObjectID, LWOOBJID_EMPTY);
|
||||
EXPECT_EQ(leaveCopy.buildType, 1);
|
||||
EXPECT_FALSE(leaveCopy.enterFlag);
|
||||
|
||||
// The client clears its autosave with the bare sd0 header: u32 size, then the bytes (0x00f2af60)
|
||||
GameMessages::SetBBBAutosave clear;
|
||||
clear.lxfmlDataCompressed = std::string("sd0\x01\xff", 5);
|
||||
EXPECT_PACKET_EQ(FromHex("05 00 00 00 73 64 30 01 ff"), Payload(clear));
|
||||
EXPECT_EQ(RoundTrip(clear).lxfmlDataCompressed, clear.lxfmlDataCompressed);
|
||||
ExpectTruncatedFails(clear);
|
||||
|
||||
GameMessages::SetBBBAutosave empty;
|
||||
EXPECT_PACKET_EQ(FromHex("00 00 00 00"), Payload(empty));
|
||||
EXPECT_TRUE(RoundTrip(empty).lxfmlDataCompressed.empty());
|
||||
|
||||
// A size larger than what is left is dropped rather than read past the end
|
||||
RakNet::BitStream tooLong;
|
||||
tooLong.Write<uint32_t>(100);
|
||||
tooLong.Write<uint8_t>(1);
|
||||
GameMessages::SetBBBAutosave read;
|
||||
EXPECT_FALSE(read.Deserialize(tooLong));
|
||||
|
||||
GameMessages::RebuildBBBAutosaveMsg rebuilt;
|
||||
rebuilt.count = 2;
|
||||
EXPECT_PACKET_EQ(FromHex("02 00 00 00"), Payload(rebuilt));
|
||||
EXPECT_EQ(RoundTrip(rebuilt).count, 2);
|
||||
ExpectTruncatedFails(rebuilt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user