mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(zone): read version 1-2 paths
Paths before version 3 are laid out differently (LevelPath::FromBuffer,
1.10.64: pathVersion < 3):
- the type is a u8-length wide string, "platform" for a moving platform
and anything else ("npc") for a movement path, instead of a u32;
- the flags and behavior u32s follow as in later versions;
- every waypoint, whatever the path's type, has a rotation, lock player
byte, speed and wait time and then its name/value pairs.
The reader treated the type name's first bytes as the type and misread
everything after it. The LUP group zones of the 0.179.12
client (lup_group_1b, _2a, _6a) now read with all their paths; one of
them read before with a garbage type on a waypoint-less path. Every
other zone reads the same as before (no live zone has a path older than
version 3).
Check in game: nothing to check on live worlds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -176,7 +176,12 @@ void ZoneFile::ReadPath(std::istream& file) {
|
||||
|
||||
BinaryIO::ReadString<uint8_t>(file, path.pathName, BinaryIO::ReadType::WideString);
|
||||
|
||||
BinaryIO::BinaryRead(file, path.pathType);
|
||||
if (path.pathVersion < 3) {
|
||||
// Before version 3 the type is a name, "platform" or "npc" (LevelPath::FromBuffer)
|
||||
std::string typeName;
|
||||
BinaryIO::ReadString<uint8_t>(file, typeName, BinaryIO::ReadType::WideString);
|
||||
path.pathType = typeName == "platform" ? PathType::MovingPlatform : PathType::Movement;
|
||||
} else BinaryIO::BinaryRead(file, path.pathType);
|
||||
BinaryIO::BinaryRead(file, path.flags);
|
||||
BinaryIO::BinaryRead(file, path.pathBehavior);
|
||||
|
||||
@@ -236,6 +241,19 @@ void ZoneFile::ReadPath(std::istream& file) {
|
||||
BinaryIO::BinaryRead(file, waypoint.position.y);
|
||||
BinaryIO::BinaryRead(file, waypoint.position.z);
|
||||
|
||||
if (path.pathVersion < 3) {
|
||||
// Before version 3 every waypoint has a moving platform's data and then name/value pairs, whatever its path's type
|
||||
BinaryIO::BinaryRead(file, waypoint.rotation.w);
|
||||
BinaryIO::BinaryRead(file, waypoint.rotation.x);
|
||||
BinaryIO::BinaryRead(file, waypoint.rotation.y);
|
||||
BinaryIO::BinaryRead(file, waypoint.rotation.z);
|
||||
BinaryIO::BinaryRead(file, waypoint.movingPlatform.lockPlayer);
|
||||
BinaryIO::BinaryRead(file, waypoint.speed);
|
||||
BinaryIO::BinaryRead(file, waypoint.movingPlatform.wait);
|
||||
ReadLdfConfig(file, path.pathType, waypoint);
|
||||
path.pathWaypoints.push_back(waypoint);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (path.pathType == PathType::Spawner || path.pathType == PathType::MovingPlatform || path.pathType == PathType::Race || path.pathType == PathType::Camera || path.pathType == PathType::Rail) {
|
||||
BinaryIO::BinaryRead(file, waypoint.rotation.w);
|
||||
|
||||
@@ -164,6 +164,46 @@ TEST(ZoneFileTests, PrePreAlphaHasNoZoneName) {
|
||||
EXPECT_TRUE(zone.zoneDesc.empty());
|
||||
}
|
||||
|
||||
// Before path version 3 the type is a name and every waypoint has a platform's data and name/value pairs
|
||||
TEST(ZoneFileTests, ReadsLegacyPaths) {
|
||||
ZoneBytes w;
|
||||
w.Put<uint32_t>(35).Put<uint32_t>(137).Put<uint8_t>(1); // version, world, scene count
|
||||
w.Text("lup.lvl").Put<uint32_t>(0).Put<uint32_t>(0).Text("Global Scene").Put<uint8_t>(0).Put<uint8_t>(0).Put<uint8_t>(0);
|
||||
w.Put<uint8_t>(0).Text("lup.raw").Text("Name").Text("Description");
|
||||
w.Put<uint32_t>(0); // no transitions
|
||||
w.Put<uint32_t>(0).Put<uint32_t>(1).Put<uint32_t>(2);
|
||||
w.Put<uint32_t>(2).Wide("LavaPath").Wide("npc").Put<uint32_t>(1).Put<uint32_t>(0);
|
||||
w.Put<uint32_t>(1).Point(1, 2, 3).Put(1.0f).Put(0.0f).Put(0.0f).Put(0.0f).Put<uint8_t>(0).Put(3.0f).Put(0.5f);
|
||||
w.Put<uint32_t>(1).Wide("delay").Wide("2");
|
||||
w.Put<uint32_t>(2).Wide("Mower").Wide("platform").Put<uint32_t>(0).Put<uint32_t>(2);
|
||||
w.Put<uint32_t>(1).Point(4, 5, 6).Put(0.0f).Put(1.0f).Put(0.0f).Put(0.0f).Put<uint8_t>(1).Put(7.0f).Put(1.5f).Put<uint32_t>(0);
|
||||
|
||||
std::istringstream stream(w.data);
|
||||
ZoneFile zone;
|
||||
zone.Read(stream);
|
||||
EXPECT_FALSE(stream.fail());
|
||||
EXPECT_EQ(stream.peek(), std::char_traits<char>::eof());
|
||||
ASSERT_EQ(zone.paths.size(), 2u);
|
||||
|
||||
const auto& npc = zone.paths[0];
|
||||
EXPECT_EQ(npc.pathType, PathType::Movement);
|
||||
EXPECT_EQ(npc.flags, 1u);
|
||||
ASSERT_EQ(npc.pathWaypoints.size(), 1u);
|
||||
EXPECT_EQ(npc.pathWaypoints[0].position, NiPoint3(1, 2, 3));
|
||||
EXPECT_EQ(npc.pathWaypoints[0].speed, 3.0f);
|
||||
ASSERT_EQ(npc.pathWaypoints[0].commands.size(), 1u);
|
||||
EXPECT_EQ(npc.pathWaypoints[0].commands[0].command, eWaypointCommandType::DELAY);
|
||||
|
||||
const auto& platform = zone.paths[1];
|
||||
EXPECT_EQ(platform.pathType, PathType::MovingPlatform);
|
||||
EXPECT_EQ(platform.pathBehavior, PathBehavior::Once);
|
||||
ASSERT_EQ(platform.pathWaypoints.size(), 1u);
|
||||
EXPECT_EQ(platform.pathWaypoints[0].rotation.x, 1.0f);
|
||||
EXPECT_EQ(platform.pathWaypoints[0].movingPlatform.lockPlayer, 1);
|
||||
EXPECT_EQ(platform.pathWaypoints[0].speed, 7.0f);
|
||||
EXPECT_EQ(platform.pathWaypoints[0].movingPlatform.wait, 1.5f);
|
||||
}
|
||||
|
||||
TEST(ZoneFileTests, ShortFilesThrowOrFail) {
|
||||
const auto zone = SampleZone();
|
||||
for (const size_t length : { size_t{ 3 }, size_t{ 40 }, zone.size() / 2, zone.size() - 1 }) {
|
||||
|
||||
Reference in New Issue
Block a user