diff --git a/Deps/TRGE.Coord.dll b/Deps/TRGE.Coord.dll index 331968e09..157050b06 100644 Binary files a/Deps/TRGE.Coord.dll and b/Deps/TRGE.Coord.dll differ diff --git a/TREnvironmentEditor/Helpers/EMLevelData.cs b/TREnvironmentEditor/Helpers/EMLevelData.cs index c7cfceb07..3b62d8cdb 100644 --- a/TREnvironmentEditor/Helpers/EMLevelData.cs +++ b/TREnvironmentEditor/Helpers/EMLevelData.cs @@ -4,9 +4,9 @@ namespace TREnvironmentEditor.Helpers; public class EMLevelData { - public uint NumCameras { get; set; } + public int NumCameras { get; set; } public int NumEntities { get; set; } - public uint NumRooms { get; set; } + public int NumRooms { get; set; } /// /// Negative values will imply a backwards search against NumCameras. @@ -42,31 +42,31 @@ public static short Convert(int itemIndex, long numItems) public static EMLevelData GetData(TR1Level level) { - return new EMLevelData + return new() { - NumCameras = level.NumCameras, + NumCameras = level.Cameras.Count, NumEntities = level.Entities.Count, - NumRooms = level.NumRooms + NumRooms = level.Rooms.Count }; } public static EMLevelData GetData(TR2Level level) { - return new EMLevelData + return new() { - NumCameras = level.NumCameras, + NumCameras = level.Cameras.Count, NumEntities = level.Entities.Count, - NumRooms = level.NumRooms + NumRooms = level.Rooms.Count }; } public static EMLevelData GetData(TR3Level level) { - return new EMLevelData + return new() { - NumCameras = level.NumCameras, + NumCameras = level.Cameras.Count, NumEntities = level.Entities.Count, - NumRooms = level.NumRooms + NumRooms = level.Rooms.Count }; } } diff --git a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs index 36d3c72dd..a1570bd72 100644 --- a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs +++ b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs @@ -530,7 +530,7 @@ private void MirrorBoxes(TR3Level level) MirrorBoxes(level.Boxes); } - private void MirrorBoxes(TRBox[] boxes) + private void MirrorBoxes(List boxes) { // TR1 boxes are in world coordinate values foreach (TRBox box in boxes) @@ -543,7 +543,7 @@ private void MirrorBoxes(TRBox[] boxes) } } - private void MirrorBoxes(TR2Box[] boxes) + private void MirrorBoxes(List boxes) { // Boxes do not necessarily cover only one sector and several sectors can point // to the same box. So we need to work out the smallest new X position for shared @@ -583,7 +583,7 @@ private static void MirrorStaticMeshes(TR3Level level) }); } - private static void MirrorStaticMeshes(TRStaticMesh[] staticMeshes, Func meshFunc) + private static void MirrorStaticMeshes(List staticMeshes, Func meshFunc) { foreach (TRStaticMesh staticMesh in staticMeshes) { diff --git a/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs b/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs index 5cc6f619e..16a9c1cf8 100644 --- a/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs +++ b/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs @@ -9,7 +9,7 @@ public class EMVisibilityPortalFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { - EMLevelData data = new() { NumRooms = level.NumRooms }; + EMLevelData data = GetData(level); foreach (EMVisibilityPortal emPortal in Portals) { @@ -24,7 +24,7 @@ public override void ApplyToLevel(TR1Level level) public override void ApplyToLevel(TR2Level level) { - EMLevelData data = new() { NumRooms = level.NumRooms }; + EMLevelData data = GetData(level); foreach (EMVisibilityPortal emPortal in Portals) { @@ -39,7 +39,7 @@ public override void ApplyToLevel(TR2Level level) public override void ApplyToLevel(TR3Level level) { - EMLevelData data = new() { NumRooms = level.NumRooms }; + EMLevelData data = GetData(level); foreach (EMVisibilityPortal emPortal in Portals) { diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs index 312ff6f35..d39a2715b 100644 --- a/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs +++ b/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs @@ -157,10 +157,7 @@ public override void ApplyToLevel(TR1Level level) BoxGenerator.Generate(newRoom, level, linkedSector); } - List rooms = level.Rooms.ToList(); - rooms.Add(newRoom); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(newRoom); } public override void ApplyToLevel(TR2Level level) @@ -311,10 +308,7 @@ public override void ApplyToLevel(TR2Level level) BoxGenerator.Generate(newRoom, level, linkedSector); } - List rooms = level.Rooms.ToList(); - rooms.Add(newRoom); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(newRoom); } public override void ApplyToLevel(TR3Level level) @@ -466,10 +460,7 @@ public override void ApplyToLevel(TR3Level level) BoxGenerator.Generate(newRoom, level, linkedSector); } - List rooms = level.Rooms.ToList(); - rooms.Add(newRoom); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(newRoom); } private TRRoomSector RebuildSector(TRRoomSector originalSector, int sectorIndex, FDControl floorData, int ydiff, TRRoomInfo oldRoomInfo) diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMCreateRoomFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMCreateRoomFunction.cs index 62500bc5f..4a88b9fe0 100644 --- a/TREnvironmentEditor/Model/Types/Rooms/EMCreateRoomFunction.cs +++ b/TREnvironmentEditor/Model/Types/Rooms/EMCreateRoomFunction.cs @@ -98,10 +98,7 @@ public override void ApplyToLevel(TR1Level level) room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); - List rooms = level.Rooms.ToList(); - rooms.Add(room); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(room); } public override void ApplyToLevel(TR2Level level) @@ -185,10 +182,7 @@ public override void ApplyToLevel(TR2Level level) room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); - List rooms = level.Rooms.ToList(); - rooms.Add(room); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(room); } public override void ApplyToLevel(TR3Level level) @@ -271,10 +265,7 @@ public override void ApplyToLevel(TR3Level level) room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); - List rooms = level.Rooms.ToList(); - rooms.Add(room); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(room); } private List GenerateSectors(sbyte ceiling, sbyte floor) diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMImportRoomFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMImportRoomFunction.cs index dcf34e539..6e54c1900 100644 --- a/TREnvironmentEditor/Model/Types/Rooms/EMImportRoomFunction.cs +++ b/TREnvironmentEditor/Model/Types/Rooms/EMImportRoomFunction.cs @@ -188,7 +188,7 @@ public override void ApplyToLevel(TR2Level level) if (!PreserveBoxes) { TRRoomSector linkedSector = FDUtilities.GetRoomSector(LinkedLocation.X, LinkedLocation.Y, LinkedLocation.Z, data.ConvertRoom(LinkedLocation.Room), level, floorData); - newBoxIndex = (ushort)level.NumBoxes; + newBoxIndex = (ushort)level.Boxes.Count; int linkedBoxIndex = linkedSector.BoxIndex; TR2BoxUtilities.DuplicateZone(level, linkedBoxIndex); @@ -209,11 +209,8 @@ public override void ApplyToLevel(TR2Level level) XMax = xmax, ZMax = zmax, TrueFloor = (short)newRoom.Info.YBottom - }; - List boxes = level.Boxes.ToList(); - boxes.Add(box); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + }; + level.Boxes.Add(box); // Link the box to the room we're joining to TR2BoxUtilities.UpdateOverlaps(level, box, new List { (ushort)linkedBoxIndex }); @@ -302,10 +299,7 @@ public override void ApplyToLevel(TR2Level level) floorData.WriteToLevel(level); - List rooms = level.Rooms.ToList(); - rooms.Add(newRoom); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(newRoom); } public override void ApplyToLevel(TR3Level level) @@ -456,7 +450,7 @@ public override void ApplyToLevel(TR3Level level) if (!PreserveBoxes) { - newBoxIndex = (ushort)level.NumBoxes; + newBoxIndex = (ushort)level.Boxes.Count; // Duplicate the zone for the new box and link the current box to the new room TR2BoxUtilities.DuplicateZone(level, linkedBoxIndex); @@ -478,10 +472,7 @@ public override void ApplyToLevel(TR3Level level) ZMax = zmax, TrueFloor = (short)newRoom.Info.YBottom }; - List boxes = level.Boxes.ToList(); - boxes.Add(box); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(box); // Link the box to the room we're joining to TR2BoxUtilities.UpdateOverlaps(level, box, new List { (ushort)linkedBoxIndex }); @@ -612,10 +603,7 @@ public override void ApplyToLevel(TR3Level level) floorData.WriteToLevel(level); - List rooms = level.Rooms.ToList(); - rooms.Add(newRoom); - level.Rooms = rooms.ToArray(); - level.NumRooms++; + level.Rooms.Add(newRoom); } public void RemapTextures(Dictionary indexMap) diff --git a/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs b/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs index 39db372ab..17d92de3d 100644 --- a/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs @@ -8,25 +8,16 @@ public class EMAddSoundSourceFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { - List soundSources = level.SoundSources.ToList(); - soundSources.Add(Source); - level.SoundSources = soundSources.ToArray(); - level.NumSoundSources++; + level.SoundSources.Add(Source); } public override void ApplyToLevel(TR2Level level) { - List soundSources = level.SoundSources.ToList(); - soundSources.Add(Source); - level.SoundSources = soundSources.ToArray(); - level.NumSoundSources++; + level.SoundSources.Add(Source); } public override void ApplyToLevel(TR3Level level) { - List soundSources = level.SoundSources.ToList(); - soundSources.Add(Source); - level.SoundSources = soundSources.ToArray(); - level.NumSoundSources++; + level.SoundSources.Add(Source); } } diff --git a/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs b/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs index 2fb011b06..5361aafd5 100644 --- a/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs @@ -8,43 +8,22 @@ public class EMRemoveSoundSourceFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { - // Can't remove by index in case several are called in succession - List sources = level.SoundSources.ToList(); - if (RemoveSource(sources)) - { - level.SoundSources = sources.ToArray(); - level.NumSoundSources--; - } + RemoveSource(level.SoundSources); } public override void ApplyToLevel(TR2Level level) { - // Can't remove by index in case several are called in succession - List sources = level.SoundSources.ToList(); - if (RemoveSource(sources)) - { - level.SoundSources = sources.ToArray(); - level.NumSoundSources--; - } + RemoveSource(level.SoundSources); } public override void ApplyToLevel(TR3Level level) { - List sources = level.SoundSources.ToList(); - if (RemoveSource(sources)) - { - level.SoundSources = sources.ToArray(); - level.NumSoundSources--; - } + RemoveSource(level.SoundSources); } private bool RemoveSource(List sources) { TRSoundSource source = sources.Find(s => s.X == Source.X && s.Y == Source.Y && s.Z == Source.Z); - if (source != null) - { - return sources.Remove(source); - } - return false; + return source != null && sources.Remove(source); } } diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs index c59d7ec5a..9205e1069 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs @@ -224,7 +224,7 @@ private static void AlterSectorBox(TR1Level level, TRRoom room, int sectorIndex) else { ushort currentBoxIndex = sector.BoxIndex; - ushort newBoxIndex = (ushort)level.NumBoxes; + ushort newBoxIndex = (ushort)level.Boxes.Count; // Make a new zone to match the addition of a new box. TR1BoxUtilities.DuplicateZone(level, sector.BoxIndex); @@ -248,10 +248,7 @@ private static void AlterSectorBox(TR1Level level, TRRoom room, int sectorIndex) // Point the sector to the new box, and save it to the level sector.BoxIndex = newBoxIndex; - List boxes = level.Boxes.ToList(); - boxes.Add(box); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(box); // Finally add the previous box as a neighbour to the new one. TR1BoxUtilities.UpdateOverlaps(level, box, new List { currentBoxIndex }); @@ -260,7 +257,7 @@ private static void AlterSectorBox(TR1Level level, TRRoom room, int sectorIndex) private static void GenerateOverlaps(TR1Level level, ushort currentBoxIndex, ushort newBoxIndex) { - for (int i = 0; i < level.NumBoxes; i++) + for (int i = 0; i < level.Boxes.Count; i++) { TRBox box = level.Boxes[i]; // Anything that has the current box as an overlap will need @@ -461,7 +458,7 @@ private static void AlterSectorBox(TR2Level level, TR2Room room, int sectorIndex else { ushort currentBoxIndex = sector.BoxIndex; - ushort newBoxIndex = (ushort)level.NumBoxes; + ushort newBoxIndex = (ushort)level.Boxes.Count; // Make a new zone to match the addition of a new box. TR2BoxUtilities.DuplicateZone(level, sector.BoxIndex); @@ -483,10 +480,7 @@ private static void AlterSectorBox(TR2Level level, TR2Room room, int sectorIndex // Point the sector to the new box, and save it to the level sector.BoxIndex = newBoxIndex; - List boxes = level.Boxes.ToList(); - boxes.Add(box); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(box); // Finally add the previous box as a neighbour to the new one. TR2BoxUtilities.UpdateOverlaps(level, box, new List { currentBoxIndex }); @@ -495,7 +489,7 @@ private static void AlterSectorBox(TR2Level level, TR2Room room, int sectorIndex private static void GenerateOverlaps(TR2Level level, ushort currentBoxIndex, ushort newBoxIndex) { - for (int i = 0; i < level.NumBoxes; i++) + for (int i = 0; i < level.Boxes.Count; i++) { TR2Box box = level.Boxes[i]; // Anything that has the current box as an overlap will need @@ -713,7 +707,7 @@ private static void AlterSectorBox(TR3Level level, TR3Room room, int sectorIndex } else { - ushort newBoxIndex = (ushort)level.NumBoxes; + ushort newBoxIndex = (ushort)level.Boxes.Count; // Make a new zone to match the addition of a new box. TR2BoxUtilities.DuplicateZone(level, currentBoxIndex); @@ -737,10 +731,7 @@ private static void AlterSectorBox(TR3Level level, TR3Room room, int sectorIndex newBoxIndex <<= 4; newBoxIndex |= (ushort)currentMaterial; sector.BoxIndex = newBoxIndex; - List boxes = level.Boxes.ToList(); - boxes.Add(box); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(box); // Finally add the previous box as a neighbour to the new one. TR2BoxUtilities.UpdateOverlaps(level, box, new List { currentBoxIndex }); @@ -749,7 +740,7 @@ private static void AlterSectorBox(TR3Level level, TR3Room room, int sectorIndex private static void GenerateOverlaps(TR3Level level, ushort currentBoxIndex, ushort newBoxIndex) { - for (int i = 0; i < level.NumBoxes; i++) + for (int i = 0; i < level.Boxes.Count; i++) { TR2Box box = level.Boxes[i]; // Anything that has the current box as an overlap will need diff --git a/TREnvironmentEditor/Model/Types/Textures/EMCreateStaticMeshFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMCreateStaticMeshFunction.cs index 873e707dc..08452cfd2 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMCreateStaticMeshFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMCreateStaticMeshFunction.cs @@ -10,37 +10,22 @@ public class EMCreateStaticMeshFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { - List statics = level.StaticMeshes.ToList(); - TRStaticMesh newMesh = Info.Clone(); newMesh.Mesh = (ushort)TRMeshUtilities.InsertMesh(level, Mesh); - statics.Add(newMesh); - - level.StaticMeshes = statics.ToArray(); - level.NumStaticMeshes++; + level.StaticMeshes.Add(newMesh); } public override void ApplyToLevel(TR2Level level) { - List statics = level.StaticMeshes.ToList(); - TRStaticMesh newMesh = Info.Clone(); newMesh.Mesh = (ushort)TRMeshUtilities.InsertMesh(level, Mesh); - statics.Add(newMesh); - - level.StaticMeshes = statics.ToArray(); - level.NumStaticMeshes++; + level.StaticMeshes.Add(newMesh); } public override void ApplyToLevel(TR3Level level) { - List statics = level.StaticMeshes.ToList(); - TRStaticMesh newMesh = Info.Clone(); newMesh.Mesh = (ushort)TRMeshUtilities.InsertMesh(level, Mesh); - statics.Add(newMesh); - - level.StaticMeshes = statics.ToArray(); - level.NumStaticMeshes++; + level.StaticMeshes.Add(newMesh); } } diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs index c61f4b84c..f0eacfab4 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs @@ -27,12 +27,8 @@ public override void ApplyToLevel(TR1Level level) ushort cameraIndex; if (Camera != null) { - List cameras = level.Cameras.ToList(); - cameras.Add(CreateCamera(data)); - level.Cameras = cameras.ToArray(); - - cameraIndex = (ushort)level.NumCameras; - level.NumCameras++; + cameraIndex = (ushort)level.Cameras.Count; + level.Cameras.Add(CreateCamera(data)); } else { @@ -81,12 +77,8 @@ public override void ApplyToLevel(TR2Level level) ushort cameraIndex; if (Camera != null) { - List cameras = level.Cameras.ToList(); - cameras.Add(CreateCamera(data)); - level.Cameras = cameras.ToArray(); - - cameraIndex = (ushort)level.NumCameras; - level.NumCameras++; + cameraIndex = (ushort)level.Cameras.Count; + level.Cameras.Add(CreateCamera(data)); } else { @@ -135,12 +127,8 @@ public override void ApplyToLevel(TR3Level level) ushort cameraIndex; if (Camera != null) { - List cameras = level.Cameras.ToList(); - cameras.Add(CreateCamera(data)); - level.Cameras = cameras.ToArray(); - - cameraIndex = (ushort)level.NumCameras; - level.NumCameras++; + cameraIndex = (ushort)level.Cameras.Count; + level.Cameras.Add(CreateCamera(data)); } else { diff --git a/TRFDControl/FDControl.cs b/TRFDControl/FDControl.cs index 7819e8609..595355d67 100644 --- a/TRFDControl/FDControl.cs +++ b/TRFDControl/FDControl.cs @@ -66,15 +66,15 @@ public void ParseFromLevel(TR3Level level) public void ParseFromLevel(TR4Level level) { - ParseLevel(level.LevelDataChunk.Rooms.SelectMany(r => r.Sectors), level.LevelDataChunk.Floordata); + ParseLevel(level.LevelDataChunk.Rooms.SelectMany(r => r.Sectors), level.LevelDataChunk.FloorData); } public void ParseFromLevel(TR5Level level) { - ParseLevel(level.LevelDataChunk.Rooms.SelectMany(r => r.RoomData.SectorList), level.LevelDataChunk.Floordata); + ParseLevel(level.LevelDataChunk.Rooms.SelectMany(r => r.RoomData.SectorList), level.LevelDataChunk.FloorData); } - private void ParseLevel(IEnumerable roomSectors, ushort[] floorData) + private void ParseLevel(IEnumerable roomSectors, List floorData) { _entries = new(); foreach (TRRoomSector sector in roomSectors) @@ -83,7 +83,7 @@ private void ParseLevel(IEnumerable roomSectors, ushort[] floorDat } } - private void ParseFromSector(TRRoomSector sector, ushort[] floorData) + private void ParseFromSector(TRRoomSector sector, List floorData) { ushort index = sector.FDIndex; // Index 0 is always dummy, so NOOP. @@ -173,7 +173,7 @@ private void ParseFromSector(TRRoomSector sector, ushort[] floorData) continueFDParse = camAction.Continue; } } - while (index < floorData.Length && continueFDParse); + while (index < floorData.Count && continueFDParse); } break; @@ -252,45 +252,34 @@ private void ParseFromSector(TRRoomSector sector, ushort[] floorData) public void WriteToLevel(TR1Level level) { - List data = Flatten(level.Rooms.SelectMany(r => r.Sectors), level.FloorData[0]); - level.FloorData = data.ToArray(); - level.NumFloorData = (uint)data.Count; + Flatten(level.Rooms.SelectMany(r => r.Sectors), level.FloorData); } public void WriteToLevel(TR2Level level) { - List data = Flatten(level.Rooms.SelectMany(r => r.SectorList), level.FloorData[0]); - level.FloorData = data.ToArray(); - level.NumFloorData = (uint)data.Count; + Flatten(level.Rooms.SelectMany(r => r.SectorList), level.FloorData); } public void WriteToLevel(TR3Level level) { - List data = Flatten(level.Rooms.SelectMany(r => r.Sectors), level.FloorData[0]); - level.FloorData = data.ToArray(); - level.NumFloorData = (uint)data.Count; + Flatten(level.Rooms.SelectMany(r => r.Sectors), level.FloorData); } public void WriteToLevel(TR4Level level) { - List data = Flatten(level.LevelDataChunk.Rooms.SelectMany(r => r.Sectors), level.LevelDataChunk.Floordata[0]); - level.LevelDataChunk.Floordata = data.ToArray(); - level.LevelDataChunk.NumFloorData = (uint)data.Count; + Flatten(level.LevelDataChunk.Rooms.SelectMany(r => r.Sectors), level.LevelDataChunk.FloorData); } public void WriteToLevel(TR5Level level) { - List data = Flatten(level.LevelDataChunk.Rooms.SelectMany(r => r.RoomData.SectorList), level.LevelDataChunk.Floordata[0]); - level.LevelDataChunk.Floordata = data.ToArray(); - level.LevelDataChunk.NumFloorData = (uint)data.Count; + Flatten(level.LevelDataChunk.Rooms.SelectMany(r => r.RoomData.SectorList), level.LevelDataChunk.FloorData); } - private List Flatten(IEnumerable sectors, ushort dummyEntry) + private void Flatten(IEnumerable sectors, List data) { - List data = new() - { - dummyEntry - }; + ushort dummyEntry = data.Count > 0 ? data[0] : (ushort)0; + data.Clear(); + data.Add(dummyEntry); // Flatten each entry list and map old indices to new. Dictionary newIndices = new(); @@ -326,7 +315,6 @@ private List Flatten(IEnumerable sectors, ushort dummyEntr // Update the stored values in case of further changes _entries = updatedEntries; - return data; } public static List Flatten(List entries) diff --git a/TRFDControl/Utilities/FDUtilities.cs b/TRFDControl/Utilities/FDUtilities.cs index 3681f9485..91b5ea758 100644 --- a/TRFDControl/Utilities/FDUtilities.cs +++ b/TRFDControl/Utilities/FDUtilities.cs @@ -189,7 +189,7 @@ public static TRRoomSector GetRoomSector(int x, int y, int z, short roomNumber, sector = room.Sectors[xFloor + yFloor * room.NumZSectors]; data = GetDoor(sector, floorData); - if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Length - 1) + if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Count - 1) { room = level.Rooms[data]; } @@ -276,7 +276,7 @@ public static TRRoomSector GetRoomSector(int x, int y, int z, short roomNumber, sector = room.SectorList[xFloor + yFloor * room.NumZSectors]; data = GetDoor(sector, floorData); - if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Length - 1) + if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Count - 1) { room = level.Rooms[data]; } @@ -363,7 +363,7 @@ public static TRRoomSector GetRoomSector(int x, int y, int z, short roomNumber, sector = room.Sectors[xFloor + yFloor * room.NumZSectors]; data = GetDoor(sector, floorData); - if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Length - 1) + if (data != TRConsts.NoRoom && data >= 0 && data < level.Rooms.Count - 1) { room = level.Rooms[data]; } diff --git a/TRLevelControl/Control/TR1LevelControl.cs b/TRLevelControl/Control/TR1LevelControl.cs index b1d977180..e7e265a0e 100644 --- a/TRLevelControl/Control/TR1LevelControl.cs +++ b/TRLevelControl/Control/TR1LevelControl.cs @@ -26,12 +26,12 @@ protected override void Read(TRLevelReader reader) uint numImages = reader.ReadUInt32(); _level.Images8 = reader.ReadImage8s(numImages); - //Rooms - _level.Unused = reader.ReadUInt32(); - _level.NumRooms = reader.ReadUInt16(); - _level.Rooms = new TRRoom[_level.NumRooms]; + // Unused, always 0 in OG + _level.Version.LevelNumber = reader.ReadUInt32(); - for (int i = 0; i < _level.NumRooms; i++) + ushort numRooms = reader.ReadUInt16(); + _level.Rooms = new(); + for (int i = 0; i < numRooms; i++) { TRRoom room = new() { @@ -47,6 +47,8 @@ protected override void Read(TRLevelReader reader) //Grab data NumDataWords = reader.ReadUInt32() }; + _level.Rooms.Add(room); + room.Data = new ushort[room.NumDataWords]; for (int j = 0; j < room.NumDataWords; j++) { @@ -92,18 +94,10 @@ protected override void Read(TRLevelReader reader) room.AlternateRoom = reader.ReadInt16(); room.Flags = reader.ReadInt16(); - - _level.Rooms[i] = room; } - //Floordata - _level.NumFloorData = reader.ReadUInt32(); - _level.FloorData = new ushort[_level.NumFloorData]; - - for (int i = 0; i < _level.NumFloorData; i++) - { - _level.FloorData[i] = reader.ReadUInt16(); - } + uint numFloorData = reader.ReadUInt32(); + _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); //Mesh Data //This tells us how much mesh data (# of words/uint16s) coming up @@ -186,12 +180,11 @@ protected override void Read(TRLevelReader reader) } //Static Meshes - _level.NumStaticMeshes = reader.ReadUInt32(); - _level.StaticMeshes = new TRStaticMesh[_level.NumStaticMeshes]; - - for (int i = 0; i < _level.NumStaticMeshes; i++) + uint numStaticMeshes = reader.ReadUInt32(); + _level.StaticMeshes = new(); + for (int i = 0; i < numStaticMeshes; i++) { - _level.StaticMeshes[i] = TR2FileReadUtilities.ReadStaticMesh(reader); + _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } //Object Textures @@ -222,47 +215,34 @@ protected override void Read(TRLevelReader reader) } //Cameras - _level.NumCameras = reader.ReadUInt32(); - _level.Cameras = new TRCamera[_level.NumCameras]; - - for (int i = 0; i < _level.NumCameras; i++) + uint numCameras = reader.ReadUInt32(); + _level.Cameras = new(); + for (int i = 0; i < numCameras; i++) { - _level.Cameras[i] = TR2FileReadUtilities.ReadCamera(reader); + _level.Cameras.Add(TR2FileReadUtilities.ReadCamera(reader)); } - //Sound Sources - _level.NumSoundSources = reader.ReadUInt32(); - _level.SoundSources = new TRSoundSource[_level.NumSoundSources]; - - for (int i = 0; i < _level.NumSoundSources; i++) + uint numSoundSources = reader.ReadUInt32(); + _level.SoundSources = new(); + for (int i = 0; i < numSoundSources; i++) { - _level.SoundSources[i] = TR2FileReadUtilities.ReadSoundSource(reader); + _level.SoundSources.Add(TR2FileReadUtilities.ReadSoundSource(reader)); } //Boxes - _level.NumBoxes = reader.ReadUInt32(); - _level.Boxes = new TRBox[_level.NumBoxes]; - - for (int i = 0; i < _level.NumBoxes; i++) + uint numBoxes = reader.ReadUInt32(); + _level.Boxes = new(); + for (int i = 0; i < numBoxes; i++) { - _level.Boxes[i] = TRFileReadUtilities.ReadBox(reader); + _level.Boxes.Add(TRFileReadUtilities.ReadBox(reader)); } //Overlaps & Zones - _level.NumOverlaps = reader.ReadUInt32(); - _level.Overlaps = new ushort[_level.NumOverlaps]; + uint numOverlaps = reader.ReadUInt32(); + _level.Overlaps = reader.ReadUInt16s(numOverlaps).ToList(); - for (int i = 0; i < _level.NumOverlaps; i++) - { - _level.Overlaps[i] = reader.ReadUInt16(); - } - - ushort[] zoneData = new ushort[_level.NumBoxes * 6]; - for (int i = 0; i < zoneData.Length; i++) - { - zoneData[i] = reader.ReadUInt16(); - } - _level.Zones = TR1BoxUtilities.ReadZones(_level.NumBoxes, zoneData); + ushort[] zoneData = reader.ReadUInt16s(numBoxes * 6); + _level.Zones = TR1BoxUtilities.ReadZones(numBoxes, zoneData); //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) //followed by a ushort to describe the number of actual texture group objects. @@ -281,12 +261,11 @@ protected override void Read(TRLevelReader reader) _level.Palette = reader.ReadColours(TRConsts.PaletteSize); //Cinematic Frames - _level.NumCinematicFrames = reader.ReadUInt16(); - _level.CinematicFrames = new TRCinematicFrame[_level.NumCinematicFrames]; - - for (int i = 0; i < _level.NumCinematicFrames; i++) + ushort numCinematicFrames = reader.ReadUInt16(); + _level.CinematicFrames = new(); + for (int i = 0; i < numCinematicFrames; i++) { - _level.CinematicFrames[i] = TR2FileReadUtilities.ReadCinematicFrame(reader); + _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } //Demo Data @@ -337,13 +316,13 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.Images8.Count); writer.Write(_level.Images8); - writer.Write(_level.Unused); + writer.Write(_level.Version.LevelNumber); - writer.Write(_level.NumRooms); + writer.Write((ushort)_level.Rooms.Count); foreach (TRRoom room in _level.Rooms) { writer.Write(room.Serialize()); } - writer.Write(_level.NumFloorData); - foreach (ushort data in _level.FloorData) { writer.Write(data); } + writer.Write((uint)_level.FloorData.Count); + writer.Write(_level.FloorData); writer.Write(_level.NumMeshData); foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } @@ -365,7 +344,7 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.Models.Count); foreach (TRModel model in _level.Models) { writer.Write(model.Serialize()); } - writer.Write(_level.NumStaticMeshes); + writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } writer.Write(_level.NumObjectTextures); @@ -375,17 +354,17 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumSpriteSequences); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } - writer.Write(_level.NumCameras); + writer.Write((uint)_level.Cameras.Count); foreach (TRCamera cam in _level.Cameras) { writer.Write(cam.Serialize()); } - writer.Write(_level.NumSoundSources); + writer.Write((uint)_level.SoundSources.Count); foreach (TRSoundSource src in _level.SoundSources) { writer.Write(src.Serialize()); } - writer.Write(_level.NumBoxes); + writer.Write((uint)_level.Boxes.Count); foreach (TRBox box in _level.Boxes) { writer.Write(box.Serialize()); } - writer.Write(_level.NumOverlaps); - foreach (ushort overlap in _level.Overlaps) { writer.Write(overlap); } - foreach (ushort zone in TR1BoxUtilities.FlattenZones(_level.Zones)) { writer.Write(zone); } + writer.Write((uint)_level.Overlaps.Count); + writer.Write(_level.Overlaps); + writer.Write(TR1BoxUtilities.FlattenZones(_level.Zones)); writer.Write(_level.NumAnimatedTextures); writer.Write((ushort)_level.AnimatedTextures.Length); @@ -399,7 +378,7 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.LightMap.ToArray()); writer.Write(_level.Palette); - writer.Write(_level.NumCinematicFrames); + writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } writer.Write(_level.NumDemoData); diff --git a/TRLevelControl/Control/TR2LevelControl.cs b/TRLevelControl/Control/TR2LevelControl.cs index f64766ee2..8914a241b 100644 --- a/TRLevelControl/Control/TR2LevelControl.cs +++ b/TRLevelControl/Control/TR2LevelControl.cs @@ -31,12 +31,13 @@ protected override void Read(TRLevelReader reader) _level.Images8 = reader.ReadImage8s(numImages); _level.Images16 = reader.ReadImage16s(numImages); - //Rooms - _level.Unused = reader.ReadUInt32(); - _level.NumRooms = reader.ReadUInt16(); - _level.Rooms = new TR2Room[_level.NumRooms]; + // Unused, always 0 in OG + _level.Version.LevelNumber = reader.ReadUInt32(); - for (int i = 0; i < _level.NumRooms; i++) + //Rooms + ushort numRooms = reader.ReadUInt16(); + _level.Rooms = new(); + for (int i = 0; i < numRooms; i++) { TR2Room room = new() { @@ -52,6 +53,8 @@ protected override void Read(TRLevelReader reader) //Grab data NumDataWords = reader.ReadUInt32() }; + _level.Rooms.Add(room); + room.Data = new ushort[room.NumDataWords]; for (int j = 0; j < room.NumDataWords; j++) { @@ -99,18 +102,10 @@ protected override void Read(TRLevelReader reader) room.AlternateRoom = reader.ReadInt16(); room.Flags = reader.ReadInt16(); - - _level.Rooms[i] = room; } - //Floordata - _level.NumFloorData = reader.ReadUInt32(); - _level.FloorData = new ushort[_level.NumFloorData]; - - for (int i = 0; i < _level.NumFloorData; i++) - { - _level.FloorData[i] = reader.ReadUInt16(); - } + uint numFloorData = reader.ReadUInt32(); + _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); //Mesh Data //This tells us how much mesh data (# of words/uint16s) coming up @@ -192,13 +187,11 @@ protected override void Read(TRLevelReader reader) _level.Models.Add(TR2FileReadUtilities.ReadModel(reader)); } - //Static Meshes - _level.NumStaticMeshes = reader.ReadUInt32(); - _level.StaticMeshes = new TRStaticMesh[_level.NumStaticMeshes]; - - for (int i = 0; i < _level.NumStaticMeshes; i++) + uint numStaticMeshes = reader.ReadUInt32(); + _level.StaticMeshes = new(); + for (int i = 0; i < numStaticMeshes; i++) { - _level.StaticMeshes[i] = TR2FileReadUtilities.ReadStaticMesh(reader); + _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } //Object Textures @@ -228,52 +221,34 @@ protected override void Read(TRLevelReader reader) _level.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); } - //Cameras - _level.NumCameras = reader.ReadUInt32(); - _level.Cameras = new TRCamera[_level.NumCameras]; - - for (int i = 0; i < _level.NumCameras; i++) + uint numCameras = reader.ReadUInt32(); + _level.Cameras = new(); + for (int i = 0; i < numCameras; i++) { - _level.Cameras[i] = TR2FileReadUtilities.ReadCamera(reader); + _level.Cameras.Add(TR2FileReadUtilities.ReadCamera(reader)); } - //Sound Sources - _level.NumSoundSources = reader.ReadUInt32(); - _level.SoundSources = new TRSoundSource[_level.NumSoundSources]; - - for (int i = 0; i < _level.NumSoundSources; i++) + uint numSoundSources = reader.ReadUInt32(); + _level.SoundSources = new(); + for (int i = 0; i < numSoundSources; i++) { - _level.SoundSources[i] = TR2FileReadUtilities.ReadSoundSource(reader); + _level.SoundSources.Add(TR2FileReadUtilities.ReadSoundSource(reader)); } //Boxes - _level.NumBoxes = reader.ReadUInt32(); - _level.Boxes = new TR2Box[_level.NumBoxes]; - - for (int i = 0; i < _level.NumBoxes; i++) + uint numBoxes = reader.ReadUInt32(); + _level.Boxes = new(); + for (int i = 0; i < numBoxes; i++) { - _level.Boxes[i] = TR2FileReadUtilities.ReadBox(reader); + _level.Boxes.Add(TR2FileReadUtilities.ReadBox(reader)); } //Overlaps & Zones - _level.NumOverlaps = reader.ReadUInt32(); - _level.Overlaps = new ushort[_level.NumOverlaps]; + uint numOverlaps = reader.ReadUInt32(); + _level.Overlaps = reader.ReadUInt16s(numOverlaps).ToList(); - for (int i = 0; i < _level.NumOverlaps; i++) - { - _level.Overlaps[i] = reader.ReadUInt16(); - } - - // Although TRosettaStone references a struct for zones, the data isn't - // sequential. Instead it's organised by flipmap status, all the groundzone - // values are then together and the flyzones at the end. TR2BoxUtilities - // handles the complexity here, so we just pass the raw ushort values. - ushort[] zoneData = new ushort[_level.NumBoxes * 10]; - for (int i = 0; i < zoneData.Length; i++) - { - zoneData[i] = reader.ReadUInt16(); - } - _level.Zones = TR2BoxUtilities.ReadZones(_level.NumBoxes, zoneData); + ushort[] zoneData = reader.ReadUInt16s(numBoxes * 10); + _level.Zones = TR2BoxUtilities.ReadZones(numBoxes, zoneData); //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) //followed by a ushort to describe the number of actual texture group objects. @@ -291,12 +266,11 @@ protected override void Read(TRLevelReader reader) _level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize)); //Cinematic Frames - _level.NumCinematicFrames = reader.ReadUInt16(); - _level.CinematicFrames = new TRCinematicFrame[_level.NumCinematicFrames]; - - for (int i = 0; i < _level.NumCinematicFrames; i++) + ushort numCinematicFrames = reader.ReadUInt16(); + _level.CinematicFrames = new(); + for (int i = 0; i < numCinematicFrames; i++) { - _level.CinematicFrames[i] = TR2FileReadUtilities.ReadCinematicFrame(reader); + _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } //Demo Data @@ -346,12 +320,13 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.Images8); writer.Write(_level.Images16); - writer.Write(_level.Unused); + writer.Write(_level.Version.LevelNumber); - writer.Write(_level.NumRooms); + writer.Write((ushort)_level.Rooms.Count); foreach (TR2Room room in _level.Rooms) { writer.Write(room.Serialize()); } - writer.Write(_level.NumFloorData); - foreach (ushort data in _level.FloorData) { writer.Write(data); } + + writer.Write((uint)_level.FloorData.Count); + writer.Write(_level.FloorData); writer.Write(_level.NumMeshData); foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } @@ -373,7 +348,7 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.Models.Count); foreach (TRModel model in _level.Models) { writer.Write(model.Serialize()); } - writer.Write(_level.NumStaticMeshes); + writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } writer.Write(_level.NumObjectTextures); @@ -383,17 +358,17 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumSpriteSequences); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } - writer.Write(_level.NumCameras); + writer.Write((uint)_level.Cameras.Count); foreach (TRCamera cam in _level.Cameras) { writer.Write(cam.Serialize()); } - writer.Write(_level.NumSoundSources); + writer.Write((uint)_level.SoundSources.Count); foreach (TRSoundSource src in _level.SoundSources) { writer.Write(src.Serialize()); } - writer.Write(_level.NumBoxes); + writer.Write((uint)_level.Boxes.Count); foreach (TR2Box box in _level.Boxes) { writer.Write(box.Serialize()); } - writer.Write(_level.NumOverlaps); - foreach (ushort overlap in _level.Overlaps) { writer.Write(overlap); } - foreach (ushort zone in TR2BoxUtilities.FlattenZones(_level.Zones)) { writer.Write(zone); } + writer.Write((uint)_level.Overlaps.Count); + writer.Write(_level.Overlaps); + writer.Write(TR2BoxUtilities.FlattenZones(_level.Zones)); writer.Write(_level.NumAnimatedTextures); writer.Write((ushort)_level.AnimatedTextures.Length); @@ -405,7 +380,7 @@ protected override void Write(TRLevelWriter writer) Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize); writer.Write(_level.LightMap.ToArray()); - writer.Write(_level.NumCinematicFrames); + writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } writer.Write(_level.NumDemoData); diff --git a/TRLevelControl/Control/TR3LevelControl.cs b/TRLevelControl/Control/TR3LevelControl.cs index 51f8c1984..2c4d363cd 100644 --- a/TRLevelControl/Control/TR3LevelControl.cs +++ b/TRLevelControl/Control/TR3LevelControl.cs @@ -31,12 +31,13 @@ protected override void Read(TRLevelReader reader) _level.Images8 = reader.ReadImage8s(numImages); _level.Images16 = reader.ReadImage16s(numImages); - //Rooms - _level.Unused = reader.ReadUInt32(); - _level.NumRooms = reader.ReadUInt16(); - _level.Rooms = new TR3Room[_level.NumRooms]; + // Unused, always 0 in OG + _level.Version.LevelNumber = reader.ReadUInt32(); - for (int i = 0; i < _level.NumRooms; i++) + //Rooms + ushort numRooms = reader.ReadUInt16(); + _level.Rooms = new(); + for (int i = 0; i < numRooms; i++) { TR3Room room = new() { @@ -52,6 +53,8 @@ protected override void Read(TRLevelReader reader) //Grab data NumDataWords = reader.ReadUInt32() }; + _level.Rooms.Add(room); + room.Data = new ushort[room.NumDataWords]; for (int j = 0; j < room.NumDataWords; j++) { @@ -103,18 +106,10 @@ protected override void Read(TRLevelReader reader) room.WaterScheme = reader.ReadByte(); room.ReverbInfo = reader.ReadByte(); room.Filler = reader.ReadByte(); - - _level.Rooms[i] = room; } - //Floordata - _level.NumFloorData = reader.ReadUInt32(); - _level.FloorData = new ushort[_level.NumFloorData]; - - for (int i = 0; i < _level.NumFloorData; i++) - { - _level.FloorData[i] = reader.ReadUInt16(); - } + uint numFloorData = reader.ReadUInt32(); + _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); //Mesh Data //This tells us how much mesh data (# of words/uint16s) coming up @@ -197,12 +192,11 @@ protected override void Read(TRLevelReader reader) } //Static Meshes - _level.NumStaticMeshes = reader.ReadUInt32(); - _level.StaticMeshes = new TRStaticMesh[_level.NumStaticMeshes]; - - for (int i = 0; i < _level.NumStaticMeshes; i++) + uint numStaticMeshes = reader.ReadUInt32(); + _level.StaticMeshes = new(); + for (int i = 0; i < numStaticMeshes; i++) { - _level.StaticMeshes[i] = TR2FileReadUtilities.ReadStaticMesh(reader); + _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } //Object Textures - in TR3 this is now after animated textures @@ -225,48 +219,34 @@ protected override void Read(TRLevelReader reader) _level.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); } - //Cameras - _level.NumCameras = reader.ReadUInt32(); - _level.Cameras = new TRCamera[_level.NumCameras]; - - for (int i = 0; i < _level.NumCameras; i++) + uint numCameras = reader.ReadUInt32(); + _level.Cameras = new(); + for (int i = 0; i < numCameras; i++) { - _level.Cameras[i] = TR2FileReadUtilities.ReadCamera(reader); + _level.Cameras.Add(TR2FileReadUtilities.ReadCamera(reader)); } - //Sound Sources - _level.NumSoundSources = reader.ReadUInt32(); - _level.SoundSources = new TRSoundSource[_level.NumSoundSources]; - - for (int i = 0; i < _level.NumSoundSources; i++) + uint numSoundSources = reader.ReadUInt32(); + _level.SoundSources = new(); + for (int i = 0; i < numSoundSources; i++) { - _level.SoundSources[i] = TR2FileReadUtilities.ReadSoundSource(reader); + _level.SoundSources.Add(TR2FileReadUtilities.ReadSoundSource(reader)); } //Boxes - _level.NumBoxes = reader.ReadUInt32(); - _level.Boxes = new TR2Box[_level.NumBoxes]; - - for (int i = 0; i < _level.NumBoxes; i++) + uint numBoxes = reader.ReadUInt32(); + _level.Boxes = new(); + for (int i = 0; i < numBoxes; i++) { - _level.Boxes[i] = TR2FileReadUtilities.ReadBox(reader); + _level.Boxes.Add(TR2FileReadUtilities.ReadBox(reader)); } //Overlaps & Zones - _level.NumOverlaps = reader.ReadUInt32(); - _level.Overlaps = new ushort[_level.NumOverlaps]; + uint numOverlaps = reader.ReadUInt32(); + _level.Overlaps = reader.ReadUInt16s(numOverlaps).ToList(); - for (int i = 0; i < _level.NumOverlaps; i++) - { - _level.Overlaps[i] = reader.ReadUInt16(); - } - - ushort[] zoneData = new ushort[_level.NumBoxes * 10]; - for (int i = 0; i < zoneData.Length; i++) - { - zoneData[i] = reader.ReadUInt16(); - } - _level.Zones = TR2BoxUtilities.ReadZones(_level.NumBoxes, zoneData); + ushort[] zoneData = reader.ReadUInt16s(numBoxes * 10); + _level.Zones = TR2BoxUtilities.ReadZones(numBoxes, zoneData); //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) //followed by a ushort to describe the number of actual texture group objects. @@ -293,12 +273,11 @@ protected override void Read(TRLevelReader reader) _level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize)); //Cinematic Frames - _level.NumCinematicFrames = reader.ReadUInt16(); - _level.CinematicFrames = new TRCinematicFrame[_level.NumCinematicFrames]; - - for (int i = 0; i < _level.NumCinematicFrames; i++) + ushort numCinematicFrames = reader.ReadUInt16(); + _level.CinematicFrames = new(); + for (int i = 0; i < numCinematicFrames; i++) { - _level.CinematicFrames[i] = TR2FileReadUtilities.ReadCinematicFrame(reader); + _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } //Demo Data @@ -348,12 +327,13 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.Images8); writer.Write(_level.Images16); - writer.Write(_level.Unused); + writer.Write(_level.Version.LevelNumber); - writer.Write(_level.NumRooms); + writer.Write((ushort)_level.Rooms.Count); foreach (TR3Room room in _level.Rooms) { writer.Write(room.Serialize()); } - writer.Write(_level.NumFloorData); - foreach (ushort data in _level.FloorData) { writer.Write(data); } + + writer.Write((uint)_level.FloorData.Count); + writer.Write(_level.FloorData); writer.Write(_level.NumMeshData); foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } @@ -375,7 +355,7 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.Models.Count); foreach (TRModel model in _level.Models) { writer.Write(model.Serialize()); } - writer.Write(_level.NumStaticMeshes); + writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } writer.Write(_level.NumSpriteTextures); @@ -383,17 +363,17 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumSpriteSequences); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } - writer.Write(_level.NumCameras); + writer.Write((uint)_level.Cameras.Count); foreach (TRCamera cam in _level.Cameras) { writer.Write(cam.Serialize()); } - writer.Write(_level.NumSoundSources); + writer.Write((uint)_level.SoundSources.Count); foreach (TRSoundSource src in _level.SoundSources) { writer.Write(src.Serialize()); } - - writer.Write(_level.NumBoxes); + + writer.Write((uint)_level.Boxes.Count); foreach (TR2Box box in _level.Boxes) { writer.Write(box.Serialize()); } - writer.Write(_level.NumOverlaps); - foreach (ushort overlap in _level.Overlaps) { writer.Write(overlap); } - foreach (ushort zone in TR2BoxUtilities.FlattenZones(_level.Zones)) { writer.Write(zone); } + writer.Write((uint)_level.Overlaps.Count); + writer.Write(_level.Overlaps); + writer.Write(TR2BoxUtilities.FlattenZones(_level.Zones)); writer.Write(_level.NumAnimatedTextures); writer.Write((ushort)_level.AnimatedTextures.Length); @@ -407,7 +387,7 @@ protected override void Write(TRLevelWriter writer) Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize); writer.Write(_level.LightMap.ToArray()); - writer.Write(_level.NumCinematicFrames); + writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } writer.Write(_level.NumDemoData); diff --git a/TRLevelControl/Helpers/Pathing/BoxGenerator.cs b/TRLevelControl/Helpers/Pathing/BoxGenerator.cs index 6f449aa57..7b6bf6edc 100644 --- a/TRLevelControl/Helpers/Pathing/BoxGenerator.cs +++ b/TRLevelControl/Helpers/Pathing/BoxGenerator.cs @@ -8,15 +8,12 @@ public class BoxGenerator public static void Generate(TRRoom room, TR1Level level, TRRoomSector linkedSector) { Room boxRoom = Room.Create(room); - Generate(boxRoom, (int)level.NumBoxes); + Generate(boxRoom, level.Boxes.Count); - List boxes = level.Boxes.ToList(); foreach (Box box in boxRoom.Boxes) { TRBox trBox = box.ToTRBox(room.Info); - boxes.Add(trBox); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(trBox); TR1BoxUtilities.UpdateOverlaps(level, trBox, box.Overlaps.Select(o => (ushort)o.Index).ToList()); TR1BoxUtilities.DuplicateZone(level, linkedSector.BoxIndex); } @@ -25,15 +22,12 @@ public static void Generate(TRRoom room, TR1Level level, TRRoomSector linkedSect public static void Generate(TR2Room room, TR2Level level, TRRoomSector linkedSector) { Room boxRoom = Room.Create(room); - Generate(boxRoom, (int)level.NumBoxes); + Generate(boxRoom, level.Boxes.Count); - List boxes = level.Boxes.ToList(); foreach (Box box in boxRoom.Boxes) { TR2Box trBox = box.ToTR2Box(room.Info); - boxes.Add(trBox); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(trBox); TR2BoxUtilities.UpdateOverlaps(level, trBox, box.Overlaps.Select(o => (ushort)o.Index).ToList()); TR2BoxUtilities.DuplicateZone(level, linkedSector.BoxIndex); } @@ -42,15 +36,12 @@ public static void Generate(TR2Room room, TR2Level level, TRRoomSector linkedSec public static void Generate(TR3Room room, TR3Level level, TRRoomSector linkedSector) { Room boxRoom = Room.Create(room); - Generate(boxRoom, (int)level.NumBoxes); + Generate(boxRoom, (int)level.Boxes.Count); - List boxes = level.Boxes.ToList(); foreach (Box box in boxRoom.Boxes) { TR2Box trBox = box.ToTR2Box(room.Info); - boxes.Add(trBox); - level.Boxes = boxes.ToArray(); - level.NumBoxes++; + level.Boxes.Add(trBox); TR2BoxUtilities.UpdateOverlaps(level, trBox, box.Overlaps.Select(o => (ushort)o.Index).ToList()); TR2BoxUtilities.DuplicateZone(level, (linkedSector.BoxIndex & 0x7FF0) >> 4); } diff --git a/TRLevelControl/Helpers/TR1BoxUtilities.cs b/TRLevelControl/Helpers/TR1BoxUtilities.cs index 402e276fc..209d42ae4 100644 --- a/TRLevelControl/Helpers/TR1BoxUtilities.cs +++ b/TRLevelControl/Helpers/TR1BoxUtilities.cs @@ -14,26 +14,24 @@ public static class TR1BoxUtilities public static void DuplicateZone(TR1Level level, int boxIndex) { TRZoneGroup zoneGroup = level.Zones[boxIndex]; - List zones = level.Zones.ToList(); - zones.Add(new TRZoneGroup + level.Zones.Add(new() { NormalZone = zoneGroup.NormalZone.Clone(), AlternateZone = zoneGroup.AlternateZone.Clone() }); - level.Zones = zones.ToArray(); } - public static TRZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) + public static List ReadZones(uint numBoxes, ushort[] zoneData) { // Initialise the zone groups - one for every box. - TRZoneGroup[] zones = new TRZoneGroup[numBoxes]; - for (int i = 0; i < zones.Length; i++) + List zones = new(); + for (int i = 0; i < numBoxes; i++) { - zones[i] = new TRZoneGroup + zones.Add(new() { - NormalZone = new TRZone(), - AlternateZone = new TRZone() - }; + NormalZone = new(), + AlternateZone = new() + }); } // Build the zones, mapping the multidimensional ushort structures into the corresponding @@ -46,13 +44,13 @@ public static TRZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) { foreach (TRZones zone in zoneValues) { - for (int box = 0; box < zones.Length; box++) + for (int box = 0; box < zones.Count; box++) { zones[box][flip].GroundZones[zone] = zoneData[valueIndex++]; } } - for (int box = 0; box < zones.Length; box++) + for (int box = 0; box < zones.Count; box++) { zones[box][flip].FlyZone = zoneData[valueIndex++]; } @@ -61,7 +59,7 @@ public static TRZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) return zones; } - public static ushort[] FlattenZones(TRZoneGroup[] zoneGroups) + public static List FlattenZones(List zoneGroups) { // Convert the zone objects back into a flat ushort list. IEnumerable flipValues = Enum.GetValues(typeof(FlipStatus)).Cast(); @@ -73,19 +71,19 @@ public static ushort[] FlattenZones(TRZoneGroup[] zoneGroups) { foreach (TRZones zone in zoneValues) { - for (int box = 0; box < zoneGroups.Length; box++) + for (int box = 0; box < zoneGroups.Count; box++) { zones.Add(zoneGroups[box][flip].GroundZones[zone]); } } - for (int box = 0; box < zoneGroups.Length; box++) + for (int box = 0; box < zoneGroups.Count; box++) { zones.Add(zoneGroups[box][flip].FlyZone); } } - return zones.ToArray(); + return zones; } public static int GetSectorCount(TR1Level level, int boxIndex) @@ -141,8 +139,8 @@ public static void UpdateOverlaps(TR1Level level, TRBox box, List overla } // Update the level data - level.Overlaps = newOverlaps.ToArray(); - level.NumOverlaps = (uint)newOverlaps.Count; + level.Overlaps.Clear(); + level.Overlaps.AddRange(newOverlaps); } private static void UpdateOverlaps(TRBox lvlBox, List boxOverlaps, List newOverlaps, short noOverlap) diff --git a/TRLevelControl/Helpers/TR2BoxUtilities.cs b/TRLevelControl/Helpers/TR2BoxUtilities.cs index 1c086ed4f..7f8f1dfcb 100644 --- a/TRLevelControl/Helpers/TR2BoxUtilities.cs +++ b/TRLevelControl/Helpers/TR2BoxUtilities.cs @@ -18,38 +18,34 @@ public class TR2BoxUtilities public static void DuplicateZone(TR2Level level, int boxIndex) { TR2ZoneGroup zoneGroup = level.Zones[boxIndex]; - List zones = level.Zones.ToList(); - zones.Add(new TR2ZoneGroup + level.Zones.Add(new() { NormalZone = zoneGroup.NormalZone.Clone(), AlternateZone = zoneGroup.AlternateZone.Clone() }); - level.Zones = zones.ToArray(); } public static void DuplicateZone(TR3Level level, int boxIndex) { TR2ZoneGroup zoneGroup = level.Zones[boxIndex]; - List zones = level.Zones.ToList(); - zones.Add(new TR2ZoneGroup + level.Zones.Add(new() { NormalZone = zoneGroup.NormalZone.Clone(), AlternateZone = zoneGroup.AlternateZone.Clone() }); - level.Zones = zones.ToArray(); } - public static TR2ZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) + public static List ReadZones(uint numBoxes, ushort[] zoneData) { // Initialise the zone groups - one for every box. - TR2ZoneGroup[] zones = new TR2ZoneGroup[numBoxes]; - for (int i = 0; i < zones.Length; i++) + List zones = new(); + for (int i = 0; i < numBoxes; i++) { - zones[i] = new TR2ZoneGroup + zones.Add(new() { - NormalZone = new TR2Zone(), - AlternateZone = new TR2Zone() - }; + NormalZone = new(), + AlternateZone = new() + }); } // Build the zones, mapping the multidimensional ushort structures into the corresponding @@ -62,13 +58,13 @@ public static TR2ZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) { foreach (TR2Zones zone in zoneValues) { - for (int box = 0; box < zones.Length; box++) + for (int box = 0; box < zones.Count; box++) { zones[box][flip].GroundZones[zone] = zoneData[valueIndex++]; } } - for (int box = 0; box < zones.Length; box++) + for (int box = 0; box < zones.Count; box++) { zones[box][flip].FlyZone = zoneData[valueIndex++]; } @@ -77,7 +73,7 @@ public static TR2ZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) return zones; } - public static ushort[] FlattenZones(TR2ZoneGroup[] zoneGroups) + public static List FlattenZones(List zoneGroups) { // Convert the zone objects back into a flat ushort list. IEnumerable flipValues = Enum.GetValues(typeof(FlipStatus)).Cast(); @@ -89,19 +85,19 @@ public static ushort[] FlattenZones(TR2ZoneGroup[] zoneGroups) { foreach (TR2Zones zone in zoneValues) { - for (int box = 0; box < zoneGroups.Length; box++) + for (int box = 0; box < zoneGroups.Count; box++) { zones.Add(zoneGroups[box][flip].GroundZones[zone]); } } - for (int box = 0; box < zoneGroups.Length; box++) + for (int box = 0; box < zoneGroups.Count; box++) { zones.Add(zoneGroups[box][flip].FlyZone); } } - return zones.ToArray(); + return zones; } public static int GetSectorCount(TR2Level level, int boxIndex) @@ -146,7 +142,7 @@ public static List GetOverlaps(TR3Level level, TR2Box box) return GetOverlaps(level.Overlaps, box, TR3NoOverlap); } - private static List GetOverlaps(ushort[] allOverlaps, TR2Box box, short noOverlap) + private static List GetOverlaps(List allOverlaps, TR2Box box, short noOverlap) { List overlaps = new(); @@ -183,8 +179,8 @@ public static void UpdateOverlaps(TR2Level level, TR2Box box, List overl } // Update the level data - level.Overlaps = newOverlaps.ToArray(); - level.NumOverlaps = (uint)newOverlaps.Count; + level.Overlaps.Clear(); + level.Overlaps.AddRange(newOverlaps); } public static void UpdateOverlaps(TR3Level level, TR2Box box, List overlaps) @@ -197,8 +193,8 @@ public static void UpdateOverlaps(TR3Level level, TR2Box box, List overl } // Update the level data - level.Overlaps = newOverlaps.ToArray(); - level.NumOverlaps = (uint)newOverlaps.Count; + level.Overlaps.Clear(); + level.Overlaps.AddRange(newOverlaps); } private static void UpdateOverlaps(TR2Box lvlBox, List boxOverlaps, List newOverlaps, short noOverlap) diff --git a/TRLevelControl/Model/Base/TR1Level.cs b/TRLevelControl/Model/Base/TR1Level.cs index 42fb8000f..32619ab19 100644 --- a/TRLevelControl/Model/Base/TR1Level.cs +++ b/TRLevelControl/Model/Base/TR1Level.cs @@ -3,31 +3,8 @@ public class TR1Level : TRLevelBase { public List Images8 { get; set; } - - /// - /// 4 bytes - /// - public uint Unused { get; set; } - - /// - /// 2 bytes - /// - public ushort NumRooms { get; set; } - - /// - /// Variable - /// - public TRRoom[] Rooms { get; set; } - - /// - /// 4 bytes - /// - public uint NumFloorData { get; set; } - - /// - /// NumFloorData * 2 bytes - /// - public ushort[] FloorData { get; set; } + public List Rooms { get; set; } + public List FloorData { get; set; } /// /// 4 bytes @@ -61,16 +38,7 @@ public class TR1Level : TRLevelBase public List MeshTrees { get; set; } public List Frames { get; set; } public List Models { get; set; } - - /// - /// 4 bytes - /// - public uint NumStaticMeshes { get; set; } - - /// - /// NumStaticMeshes * 32 bytes - /// - public TRStaticMesh[] StaticMeshes { get; set; } + public List StaticMeshes { get; set; } /// /// 4 bytes @@ -101,48 +69,11 @@ public class TR1Level : TRLevelBase /// NumSpriteSequences * 8 bytes /// public TRSpriteSequence[] SpriteSequences { get; set; } - - /// - /// 4 bytes - /// - public uint NumCameras { get; set; } - - /// - /// NumCameras * 16 bytes - /// - public TRCamera[] Cameras { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundSources { get; set; } - - /// - /// NumSoundSources * 16 bytes - /// - public TRSoundSource[] SoundSources { get; set; } - - /// - /// 4 bytes - /// - public uint NumBoxes { get; set; } - - /// - /// NumBoxes * 8 bytes - /// - public TRBox[] Boxes { get; set; } - - /// - /// 4 bytes - /// - public uint NumOverlaps { get; set; } - - /// - /// NumOverlaps * 2 bytes - /// - public ushort[] Overlaps { get; set; } - - public TRZoneGroup[] Zones { get; set; } + public List Cameras { get; set; } + public List SoundSources { get; set; } + public List Boxes { get; set; } + public List Overlaps { get; set; } + public List Zones { get; set; } /// /// 4 bytes @@ -156,16 +87,7 @@ public class TR1Level : TRLevelBase public List Entities { get; set; } public List LightMap { get; set; } public List Palette { get; set; } - - /// - /// 2 bytes - /// - public ushort NumCinematicFrames { get; set; } - - /// - /// NumCinematicFrames * 16 bytes - /// - public TRCinematicFrame[] CinematicFrames { get; set; } + public List CinematicFrames { get; set; } /// /// 2 bytes diff --git a/TRLevelControl/Model/Common/TRVersion.cs b/TRLevelControl/Model/Common/TRVersion.cs index 1f6855981..9f661cb6b 100644 --- a/TRLevelControl/Model/Common/TRVersion.cs +++ b/TRLevelControl/Model/Common/TRVersion.cs @@ -4,4 +4,5 @@ public class TRVersion { public TRGameVersion Game { get; set; } public TRFileVersion File { get; set; } + public uint LevelNumber { get; set; } } diff --git a/TRLevelControl/Model/TR2/TR2Level.cs b/TRLevelControl/Model/TR2/TR2Level.cs index db547ea3c..6169c78a4 100644 --- a/TRLevelControl/Model/TR2/TR2Level.cs +++ b/TRLevelControl/Model/TR2/TR2Level.cs @@ -6,31 +6,8 @@ public class TR2Level : TRLevelBase public List Palette16 { get; set; } public List Images8 { get; set; } public List Images16 { get; set; } - - /// - /// 4 bytes - /// - public uint Unused { get; set; } - - /// - /// 2 bytes - /// - public ushort NumRooms { get; set; } - - /// - /// Variable - /// - public TR2Room[] Rooms { get; set; } - - /// - /// 4 bytes - /// - public uint NumFloorData { get; set; } - - /// - /// NumFloorData * 2 bytes - /// - public ushort[] FloorData { get; set; } + public List Rooms { get; set; } + public List FloorData { get; set; } /// /// 4 bytes @@ -64,16 +41,7 @@ public class TR2Level : TRLevelBase public List MeshTrees { get; set; } public List Frames { get; set; } public List Models { get; set; } - - /// - /// 4 bytes - /// - public uint NumStaticMeshes { get; set; } - - /// - /// NumStaticMeshes * 32 bytes - /// - public TRStaticMesh[] StaticMeshes { get; set; } + public List StaticMeshes { get; set; } /// /// 4 bytes @@ -104,51 +72,11 @@ public class TR2Level : TRLevelBase /// NumSpriteSequences * 8 bytes /// public TRSpriteSequence[] SpriteSequences { get; set; } - - /// - /// 4 bytes - /// - public uint NumCameras { get; set; } - - /// - /// NumCameras * 16 bytes - /// - public TRCamera[] Cameras { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundSources { get; set; } - - /// - /// NumSoundSources * 16 bytes - /// - public TRSoundSource[] SoundSources { get; set; } - - /// - /// 4 bytes - /// - public uint NumBoxes { get; set; } - - /// - /// NumBoxes * 8 bytes - /// - public TR2Box[] Boxes { get; set; } - - /// - /// 4 bytes - /// - public uint NumOverlaps { get; set; } - - /// - /// NumOverlaps * 2 bytes - /// - public ushort[] Overlaps { get; set; } - - /// - /// NumBoxes * 20 bytes (double check this) - /// - public TR2ZoneGroup[] Zones { get; set; } + public List Cameras { get; set; } + public List SoundSources { get; set; } + public List Boxes { get; set; } + public List Overlaps { get; set; } + public List Zones { get; set; } /// /// 4 bytes @@ -161,16 +89,7 @@ public class TR2Level : TRLevelBase public TRAnimatedTexture[] AnimatedTextures { get; set; } public List Entities { get; set; } public List LightMap { get; set; } - - /// - /// 2 bytes - /// - public ushort NumCinematicFrames { get; set; } - - /// - /// NumCinematicFrames * 16 bytes - /// - public TRCinematicFrame[] CinematicFrames { get; set; } + public List CinematicFrames { get; set; } /// /// 2 bytes diff --git a/TRLevelControl/Model/TR3/TR3Level.cs b/TRLevelControl/Model/TR3/TR3Level.cs index 74d751357..36319ad06 100644 --- a/TRLevelControl/Model/TR3/TR3Level.cs +++ b/TRLevelControl/Model/TR3/TR3Level.cs @@ -6,31 +6,8 @@ public class TR3Level : TRLevelBase public List Palette16 { get; set; } public List Images8 { get; set; } public List Images16 { get; set; } - - /// - /// 4 bytes - /// - public uint Unused { get; set; } - - /// - /// 2 bytes - /// - public ushort NumRooms { get; set; } - - /// - /// Variable - /// - public TR3Room[] Rooms { get; set; } - - /// - /// 4 bytes - /// - public uint NumFloorData { get; set; } - - /// - /// NumFloorData * 2 bytes - /// - public ushort[] FloorData { get; set; } + public List Rooms { get; set; } + public List FloorData { get; set; } /// /// 4 bytes @@ -64,16 +41,7 @@ public class TR3Level : TRLevelBase public List MeshTrees { get; set; } public List Frames { get; set; } public List Models { get; set; } - - /// - /// 4 bytes - /// - public uint NumStaticMeshes { get; set; } - - /// - /// NumStaticMeshes * 32 bytes - /// - public TRStaticMesh[] StaticMeshes { get; set; } + public List StaticMeshes { get; set; } /// /// 4 bytes @@ -94,51 +62,11 @@ public class TR3Level : TRLevelBase /// NumSpriteSequences * 8 bytes /// public TRSpriteSequence[] SpriteSequences { get; set; } - - /// - /// 4 bytes - /// - public uint NumCameras { get; set; } - - /// - /// NumCameras * 16 bytes - /// - public TRCamera[] Cameras { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundSources { get; set; } - - /// - /// NumSoundSources * 16 bytes - /// - public TRSoundSource[] SoundSources { get; set; } - - /// - /// 4 bytes - /// - public uint NumBoxes { get; set; } - - /// - /// NumBoxes * 8 bytes - /// - public TR2Box[] Boxes { get; set; } - - /// - /// 4 bytes - /// - public uint NumOverlaps { get; set; } - - /// - /// NumOverlaps * 2 bytes - /// - public ushort[] Overlaps { get; set; } - - /// - /// NumBoxes * 20 bytes (double check this) - /// - public TR2ZoneGroup[] Zones { get; set; } + public List Cameras { get; set; } + public List SoundSources { get; set; } + public List Boxes { get; set; } + public List Overlaps { get; set; } + public List Zones { get; set; } /// /// 4 bytes @@ -161,16 +89,7 @@ public class TR3Level : TRLevelBase public TRObjectTexture[] ObjectTextures { get; set; } public List Entities { get; set; } public List LightMap { get; set; } - - /// - /// 2 bytes - /// - public ushort NumCinematicFrames { get; set; } - - /// - /// NumCinematicFrames * 16 bytes - /// - public TRCinematicFrame[] CinematicFrames { get; set; } + public List CinematicFrames { get; set; } /// /// 2 bytes diff --git a/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs b/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs index a60a13730..2a1715327 100644 --- a/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs +++ b/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs @@ -10,14 +10,8 @@ public class TR4LevelDataChunk : ISerializableCompact public uint CompressedSize { get; set; } public uint Unused { get; set; } - - public ushort NumRooms { get; set; } - - public TR4Room[] Rooms { get; set; } - - public uint NumFloorData { get; set; } - - public ushort[] Floordata { get; set; } + public List Rooms { get; set; } + public List FloorData { get; set; } public uint NumMeshData { get; set; } @@ -36,10 +30,7 @@ public class TR4LevelDataChunk : ISerializableCompact public List MeshTrees { get; set; } public List Frames { get; set; } public List Models { get; set; } - - public uint NumStaticMeshes { get; set; } - - public TRStaticMesh[] StaticMeshes { get; set; } + public List StaticMeshes { get; set; } public byte[] SPRMarker { get; set; } @@ -50,28 +41,12 @@ public class TR4LevelDataChunk : ISerializableCompact public uint NumSpriteSequences { get; set; } public TRSpriteSequence[] SpriteSequences { get; set; } - - public uint NumCameras { get; set; } - - public TRCamera[] Cameras { get; set; } - - public uint NumFlybyCameras { get; set; } - - public TR4FlyByCamera[] FlybyCameras { get; set; } - - public uint NumSoundSources { get; set; } - - public TRSoundSource[] SoundSources { get; set; } - - public uint NumBoxes { get; set; } - - public TR2Box[] Boxes { get; set; } - - public uint NumOverlaps { get; set; } - - public ushort[] Overlaps { get; set; } - - public short[] Zones { get; set; } + public List Cameras { get; set; } + public List FlybyCameras { get; set; } + public List SoundSources { get; set; } + public List Boxes { get; set; } + public List Overlaps { get; set; } + public List Zones { get; set; } public uint NumAnimatedTextures { get; set; } @@ -112,19 +87,15 @@ public byte[] Serialize() using (TRLevelWriter writer = new(stream)) { writer.Write(Unused); - writer.Write(NumRooms); + writer.Write((ushort)Rooms.Count); foreach (TR4Room room in Rooms) { writer.Write(room.Serialize()); } - writer.Write(NumFloorData); - - foreach (ushort data in Floordata) - { - writer.Write(data); - } + writer.Write((uint)FloorData.Count); + writer.Write(FloorData); writer.Write(NumMeshData); @@ -182,8 +153,7 @@ public byte[] Serialize() writer.Write(model.Serialize()); } - writer.Write(NumStaticMeshes); - + writer.Write((uint)StaticMeshes.Count); foreach (TRStaticMesh sm in StaticMeshes) { writer.Write(sm.Serialize()); @@ -205,36 +175,31 @@ public byte[] Serialize() writer.Write(seq.Serialize()); } - writer.Write(NumCameras); - + writer.Write((uint)Cameras.Count); foreach (TRCamera cam in Cameras) { writer.Write(cam.Serialize()); } - writer.Write(NumFlybyCameras); - + writer.Write((uint)FlybyCameras.Count); foreach (TR4FlyByCamera flycam in FlybyCameras) { writer.Write(flycam.Serialize()); } - writer.Write(NumSoundSources); - + writer.Write((uint)SoundSources.Count); foreach (TRSoundSource ssrc in SoundSources) { writer.Write(ssrc.Serialize()); } - writer.Write(NumBoxes); - + writer.Write((uint)Boxes.Count); foreach (TR2Box box in Boxes) { writer.Write(box.Serialize()); } - writer.Write(NumOverlaps); - + writer.Write((uint)Overlaps.Count); foreach (ushort overlap in Overlaps) { writer.Write(overlap); diff --git a/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs b/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs index 8e6ea1a36..619694d06 100644 --- a/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs +++ b/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs @@ -7,16 +7,8 @@ public class TR5LevelDataChunk public uint CompressedSize { get; set; } public uint Unused { get; set; } - - //It says ushort in TRosettaStone, but looking at level files in HxD it seems there is always - //"00 00" before the first XELA landmark. Based on that NumRooms will be read as a uint. - public uint NumRooms { get; set; } - - public TR5Room[] Rooms { get; set; } - - public uint NumFloorData { get; set; } - - public ushort[] Floordata { get; set; } + public List Rooms { get; set; } + public List FloorData { get; set; } public uint NumMeshData { get; set; } @@ -35,10 +27,7 @@ public class TR5LevelDataChunk public List MeshTrees { get; set; } public List Frames { get; set; } public List Models { get; set; } - - public uint NumStaticMeshes { get; set; } - - public TRStaticMesh[] StaticMeshes { get; set; } + public List StaticMeshes { get; set; } public byte[] SPRMarker { get; set; } @@ -49,28 +38,12 @@ public class TR5LevelDataChunk public uint NumSpriteSequences { get; set; } public TRSpriteSequence[] SpriteSequences { get; set; } - - public uint NumCameras { get; set; } - - public TRCamera[] Cameras { get; set; } - - public uint NumFlybyCameras { get; set; } - - public TR4FlyByCamera[] FlybyCameras { get; set; } - - public uint NumSoundSources { get; set; } - - public TRSoundSource[] SoundSources { get; set; } - - public uint NumBoxes { get; set; } - - public TR2Box[] Boxes { get; set; } - - public uint NumOverlaps { get; set; } - - public ushort[] Overlaps { get; set; } - - public short[] Zones { get; set; } + public List Cameras { get; set; } + public List FlybyCameras { get; set; } + public List SoundSources { get; set; } + public List Boxes { get; set; } + public List Overlaps { get; set; } + public List Zones { get; set; } public uint NumAnimatedTextures { get; set; } @@ -111,19 +84,15 @@ public byte[] Serialize() using (TRLevelWriter writer = new(stream)) { writer.Write(Unused); - writer.Write(NumRooms); + writer.Write((uint)Rooms.Count); foreach (TR5Room room in Rooms) { writer.Write(room.Serialize()); } - writer.Write(NumFloorData); - - foreach (ushort data in Floordata) - { - writer.Write(data); - } + writer.Write((uint)FloorData.Count); + writer.Write(FloorData); writer.Write(NumMeshData); @@ -181,8 +150,7 @@ public byte[] Serialize() writer.Write(model.Serialize()); } - writer.Write(NumStaticMeshes); - + writer.Write((uint)StaticMeshes.Count); foreach (TRStaticMesh sm in StaticMeshes) { writer.Write(sm.Serialize()); @@ -204,36 +172,31 @@ public byte[] Serialize() writer.Write(seq.Serialize()); } - writer.Write(NumCameras); - + writer.Write((uint)Cameras.Count); foreach (TRCamera cam in Cameras) { writer.Write(cam.Serialize()); } - writer.Write(NumFlybyCameras); - + writer.Write((uint)FlybyCameras.Count); foreach (TR4FlyByCamera flycam in FlybyCameras) { writer.Write(flycam.Serialize()); } - writer.Write(NumSoundSources); - + writer.Write((uint)SoundSources.Count); foreach (TRSoundSource ssrc in SoundSources) { writer.Write(ssrc.Serialize()); } - writer.Write(NumBoxes); - + writer.Write((uint)Boxes.Count); foreach (TR2Box box in Boxes) { writer.Write(box.Serialize()); } - writer.Write(NumOverlaps); - + writer.Write((uint)Overlaps.Count); foreach (ushort overlap in Overlaps) { writer.Write(overlap); diff --git a/TRLevelControl/TR4FileReadUtilities.cs b/TRLevelControl/TR4FileReadUtilities.cs index e42222716..57ba58092 100644 --- a/TRLevelControl/TR4FileReadUtilities.cs +++ b/TRLevelControl/TR4FileReadUtilities.cs @@ -9,10 +9,10 @@ internal static class TR4FileReadUtilities public static void PopulateRooms(BinaryReader reader, TR4Level lvl) { lvl.LevelDataChunk.Unused = reader.ReadUInt32(); - lvl.LevelDataChunk.NumRooms = reader.ReadUInt16(); - lvl.LevelDataChunk.Rooms = new TR4Room[lvl.LevelDataChunk.NumRooms]; + ushort numRooms = reader.ReadUInt16(); + lvl.LevelDataChunk.Rooms = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumRooms; i++) + for (int i = 0; i < numRooms; i++) { TR4Room room = new() { @@ -28,6 +28,8 @@ public static void PopulateRooms(BinaryReader reader, TR4Level lvl) //Grab data NumDataWords = reader.ReadUInt32() }; + lvl.LevelDataChunk.Rooms.Add(room); + room.Data = new ushort[room.NumDataWords]; for (int j = 0; j < room.NumDataWords; j++) { @@ -77,19 +79,17 @@ public static void PopulateRooms(BinaryReader reader, TR4Level lvl) room.WaterScheme = reader.ReadByte(); room.ReverbInfo = reader.ReadByte(); room.Filler = reader.ReadByte(); - - lvl.LevelDataChunk.Rooms[i] = room; } } public static void PopulateFloordata(BinaryReader reader, TR4Level lvl) { - lvl.LevelDataChunk.NumFloorData = reader.ReadUInt32(); - lvl.LevelDataChunk.Floordata = new ushort[lvl.LevelDataChunk.NumFloorData]; + uint numFloorData = reader.ReadUInt32(); + lvl.LevelDataChunk.FloorData = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumFloorData; i++) + for (int i = 0; i < numFloorData; i++) { - lvl.LevelDataChunk.Floordata[i] = reader.ReadUInt16(); + lvl.LevelDataChunk.FloorData.Add(reader.ReadUInt16()); } } @@ -184,12 +184,12 @@ public static void PopulateMeshTreesFramesModels(BinaryReader reader, TR4Level l public static void PopulateStaticMeshes(BinaryReader reader, TR4Level lvl) { - lvl.LevelDataChunk.NumStaticMeshes = reader.ReadUInt32(); - lvl.LevelDataChunk.StaticMeshes = new TRStaticMesh[lvl.LevelDataChunk.NumStaticMeshes]; + uint numStaticMeshes = reader.ReadUInt32(); + lvl.LevelDataChunk.StaticMeshes = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumStaticMeshes; i++) + for (int i = 0; i < numStaticMeshes; i++) { - lvl.LevelDataChunk.StaticMeshes[i] = TR2FileReadUtilities.ReadStaticMesh(reader); + lvl.LevelDataChunk.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } } @@ -226,61 +226,62 @@ public static void PopulateSprites(BinaryReader reader, TR4Level lvl) public static void PopulateCameras(BinaryReader reader, TR4Level lvl) { //Cameras - lvl.LevelDataChunk.NumCameras = reader.ReadUInt32(); - lvl.LevelDataChunk.Cameras = new TRCamera[lvl.LevelDataChunk.NumCameras]; + uint numCameras = reader.ReadUInt32(); + lvl.LevelDataChunk.Cameras = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumCameras; i++) + for (int i = 0; i < numCameras; i++) { - lvl.LevelDataChunk.Cameras[i] = TR2FileReadUtilities.ReadCamera(reader); + lvl.LevelDataChunk.Cameras.Add(TR2FileReadUtilities.ReadCamera(reader)); } //Flyby Cameras - lvl.LevelDataChunk.NumFlybyCameras = reader.ReadUInt32(); - lvl.LevelDataChunk.FlybyCameras = new TR4FlyByCamera[lvl.LevelDataChunk.NumFlybyCameras]; + uint numFlybyCameras = reader.ReadUInt32(); + lvl.LevelDataChunk.FlybyCameras = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumFlybyCameras; i++) + for (int i = 0; i < numFlybyCameras; i++) { - lvl.LevelDataChunk.FlybyCameras[i] = TR4FileReadUtilities.ReadFlybyCamera(reader); + lvl.LevelDataChunk.FlybyCameras.Add(ReadFlybyCamera(reader)); } } public static void PopulateSoundSources(BinaryReader reader, TR4Level lvl) { //Sound Sources - lvl.LevelDataChunk.NumSoundSources = reader.ReadUInt32(); - lvl.LevelDataChunk.SoundSources = new TRSoundSource[lvl.LevelDataChunk.NumSoundSources]; + uint numSoundSources = reader.ReadUInt32(); + lvl.LevelDataChunk.SoundSources = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSoundSources; i++) + for (int i = 0; i < numSoundSources; i++) { - lvl.LevelDataChunk.SoundSources[i] = TR2FileReadUtilities.ReadSoundSource(reader); + lvl.LevelDataChunk.SoundSources.Add(TR2FileReadUtilities.ReadSoundSource(reader)); } } public static void PopulateBoxesOverlapsZones(BinaryReader reader, TR4Level lvl) { //Boxes - lvl.LevelDataChunk.NumBoxes = reader.ReadUInt32(); - lvl.LevelDataChunk.Boxes = new TR2Box[lvl.LevelDataChunk.NumBoxes]; + uint numBoxes = reader.ReadUInt32(); + lvl.LevelDataChunk.Boxes = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumBoxes; i++) + for (int i = 0; i < numBoxes; i++) { - lvl.LevelDataChunk.Boxes[i] = TR2FileReadUtilities.ReadBox(reader); + lvl.LevelDataChunk.Boxes.Add(TR2FileReadUtilities.ReadBox(reader)); } //Overlaps & Zones - lvl.LevelDataChunk.NumOverlaps = reader.ReadUInt32(); - lvl.LevelDataChunk.Overlaps = new ushort[lvl.LevelDataChunk.NumOverlaps]; - lvl.LevelDataChunk.Zones = new short[10 * lvl.LevelDataChunk.NumBoxes]; + uint numOverlaps = reader.ReadUInt32(); + lvl.LevelDataChunk.Overlaps = new(); + short[] zones = new short[10 * numBoxes]; - for (int i = 0; i < lvl.LevelDataChunk.NumOverlaps; i++) + for (int i = 0; i < numOverlaps; i++) { - lvl.LevelDataChunk.Overlaps[i] = reader.ReadUInt16(); + lvl.LevelDataChunk.Overlaps.Add(reader.ReadUInt16()); } - for (int i = 0; i < lvl.LevelDataChunk.Zones.Length; i++) + for (int i = 0; i < zones.Length; i++) { - lvl.LevelDataChunk.Zones[i] = reader.ReadInt16(); + zones[i] = reader.ReadInt16(); } + lvl.LevelDataChunk.Zones = new(zones); } public static void PopulateAnimatedTextures(BinaryReader reader, TR4Level lvl) diff --git a/TRLevelControl/TR5FileReadUtilities.cs b/TRLevelControl/TR5FileReadUtilities.cs index 14822eb84..3bffba328 100644 --- a/TRLevelControl/TR5FileReadUtilities.cs +++ b/TRLevelControl/TR5FileReadUtilities.cs @@ -9,14 +9,15 @@ internal static class TR5FileReadUtilities public static void PopulateRooms(BinaryReader reader, TR5Level lvl) { lvl.LevelDataChunk.Unused = reader.ReadUInt32(); - lvl.LevelDataChunk.NumRooms = reader.ReadUInt32(); - lvl.LevelDataChunk.Rooms = new TR5Room[lvl.LevelDataChunk.NumRooms]; - for (int i = 0; i < lvl.LevelDataChunk.NumRooms; i++) + uint numRooms = reader.ReadUInt32(); + lvl.LevelDataChunk.Rooms = new(); + for (int i = 0; i < numRooms; i++) { TR5Room room = new() { XELALandmark = reader.ReadBytes(4) }; + lvl.LevelDataChunk.Rooms.Add(room); Debug.Assert(room.XELALandmark[0] == 'X'); Debug.Assert(room.XELALandmark[1] == 'E'); @@ -122,7 +123,6 @@ public static void PopulateRooms(BinaryReader reader, TR5Level lvl) PopulateLightsBulbsAndSectors(room, data); room.RoomData = data; - lvl.LevelDataChunk.Rooms[i] = room; } } @@ -201,12 +201,12 @@ private static TR5FogBulb ReadRoomBulbs(BinaryReader r) public static void PopulateFloordata(BinaryReader reader, TR5Level lvl) { - lvl.LevelDataChunk.NumFloorData = reader.ReadUInt32(); - lvl.LevelDataChunk.Floordata = new ushort[lvl.LevelDataChunk.NumFloorData]; + uint numFloorData = reader.ReadUInt32(); + lvl.LevelDataChunk.FloorData = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumFloorData; i++) + for (int i = 0; i < numFloorData; i++) { - lvl.LevelDataChunk.Floordata[i] = reader.ReadUInt16(); + lvl.LevelDataChunk.FloorData.Add(reader.ReadUInt16()); } } @@ -315,12 +315,12 @@ private static TR5Model ReadTR5Model(BinaryReader reader) public static void PopulateStaticMeshes(BinaryReader reader, TR5Level lvl) { - lvl.LevelDataChunk.NumStaticMeshes = reader.ReadUInt32(); - lvl.LevelDataChunk.StaticMeshes = new TRStaticMesh[lvl.LevelDataChunk.NumStaticMeshes]; + uint numStaticMeshes = reader.ReadUInt32(); + lvl.LevelDataChunk.StaticMeshes = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumStaticMeshes; i++) + for (int i = 0; i < numStaticMeshes; i++) { - lvl.LevelDataChunk.StaticMeshes[i] = TR2FileReadUtilities.ReadStaticMesh(reader); + lvl.LevelDataChunk.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } } @@ -358,61 +358,62 @@ public static void PopulateSprites(BinaryReader reader, TR5Level lvl) public static void PopulateCameras(BinaryReader reader, TR5Level lvl) { //Cameras - lvl.LevelDataChunk.NumCameras = reader.ReadUInt32(); - lvl.LevelDataChunk.Cameras = new TRCamera[lvl.LevelDataChunk.NumCameras]; + uint numCameras = reader.ReadUInt32(); + lvl.LevelDataChunk.Cameras = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumCameras; i++) + for (int i = 0; i < numCameras; i++) { - lvl.LevelDataChunk.Cameras[i] = TR2FileReadUtilities.ReadCamera(reader); + lvl.LevelDataChunk.Cameras.Add(TR2FileReadUtilities.ReadCamera(reader)); } //Flyby Cameras - lvl.LevelDataChunk.NumFlybyCameras = reader.ReadUInt32(); - lvl.LevelDataChunk.FlybyCameras = new TR4FlyByCamera[lvl.LevelDataChunk.NumFlybyCameras]; + uint numFlybyCameras = reader.ReadUInt32(); + lvl.LevelDataChunk.FlybyCameras = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumFlybyCameras; i++) + for (int i = 0; i < numFlybyCameras; i++) { - lvl.LevelDataChunk.FlybyCameras[i] = TR4FileReadUtilities.ReadFlybyCamera(reader); + lvl.LevelDataChunk.FlybyCameras.Add(TR4FileReadUtilities.ReadFlybyCamera(reader)); } } public static void PopulateSoundSources(BinaryReader reader, TR5Level lvl) { //Sound Sources - lvl.LevelDataChunk.NumSoundSources = reader.ReadUInt32(); - lvl.LevelDataChunk.SoundSources = new TRSoundSource[lvl.LevelDataChunk.NumSoundSources]; + uint numSoundSources = reader.ReadUInt32(); + lvl.LevelDataChunk.SoundSources = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSoundSources; i++) + for (int i = 0; i < numSoundSources; i++) { - lvl.LevelDataChunk.SoundSources[i] = TR2FileReadUtilities.ReadSoundSource(reader); + lvl.LevelDataChunk.SoundSources.Add(TR2FileReadUtilities.ReadSoundSource(reader)); } } public static void PopulateBoxesOverlapsZones(BinaryReader reader, TR5Level lvl) { //Boxes - lvl.LevelDataChunk.NumBoxes = reader.ReadUInt32(); - lvl.LevelDataChunk.Boxes = new TR2Box[lvl.LevelDataChunk.NumBoxes]; + uint numBoxes = reader.ReadUInt32(); + lvl.LevelDataChunk.Boxes = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumBoxes; i++) + for (int i = 0; i < numBoxes; i++) { - lvl.LevelDataChunk.Boxes[i] = TR2FileReadUtilities.ReadBox(reader); + lvl.LevelDataChunk.Boxes.Add(TR2FileReadUtilities.ReadBox(reader)); } //Overlaps & Zones - lvl.LevelDataChunk.NumOverlaps = reader.ReadUInt32(); - lvl.LevelDataChunk.Overlaps = new ushort[lvl.LevelDataChunk.NumOverlaps]; - lvl.LevelDataChunk.Zones = new short[10 * lvl.LevelDataChunk.NumBoxes]; + uint numOverlaps = reader.ReadUInt32(); + lvl.LevelDataChunk.Overlaps = new(); + short[] zones = new short[10 * numBoxes]; - for (int i = 0; i < lvl.LevelDataChunk.NumOverlaps; i++) + for (int i = 0; i < numOverlaps; i++) { - lvl.LevelDataChunk.Overlaps[i] = reader.ReadUInt16(); + lvl.LevelDataChunk.Overlaps.Add(reader.ReadUInt16()); } - for (int i = 0; i < lvl.LevelDataChunk.Zones.Length; i++) + for (int i = 0; i < zones.Length; i++) { - lvl.LevelDataChunk.Zones[i] = reader.ReadInt16(); + zones[i] = reader.ReadInt16(); } + lvl.LevelDataChunk.Zones = new(zones); } public static void PopulateAnimatedTextures(BinaryReader reader, TR5Level lvl) diff --git a/TRLevelControlTests/TR1/IOTests.cs b/TRLevelControlTests/TR1/IOTests.cs index 0fc564e04..1aa2fa1d3 100644 --- a/TRLevelControlTests/TR1/IOTests.cs +++ b/TRLevelControlTests/TR1/IOTests.cs @@ -110,33 +110,30 @@ public void ModifyZonesTest() // for comparison. Dictionary flipOffZones = new(); Dictionary flipOnZones = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { flipOffZones[i] = lvl.Zones[i][FlipStatus.Off].Serialize(); flipOnZones[i] = lvl.Zones[i][FlipStatus.On].Serialize(); } // Add a new box - List boxes = lvl.Boxes.ToList(); - boxes.Add(boxes[0]); - lvl.Boxes = boxes.ToArray(); - lvl.NumBoxes++; + lvl.Boxes.Add(lvl.Boxes[0]); // Add a new zone for the box and store its serialized form for comparison - int newBoxIndex = (int)(lvl.NumBoxes - 1); + int newBoxIndex = (int)(lvl.Boxes.Count - 1); TR1BoxUtilities.DuplicateZone(lvl, 0); flipOffZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.Off].Serialize(); flipOnZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.On].Serialize(); // Verify the number of zone ushorts matches what's expected for the box count - Assert.AreEqual(TR1BoxUtilities.FlattenZones(lvl.Zones).Length, (int)(6 * lvl.NumBoxes)); + Assert.AreEqual(TR1BoxUtilities.FlattenZones(lvl.Zones).Count, (int)(6 * lvl.Boxes.Count)); // Write and re-read the level lvl = WriteReadTempLevel(lvl); // Capture all of the zones again. Make sure the addition of the zone above didn't // affect any of the others and that the addition itself matches after IO. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { byte[] flipOff = lvl.Zones[i][FlipStatus.Off].Serialize(); Assert.IsTrue(flipOffZones.ContainsKey(i)); diff --git a/TRLevelControlTests/TR2/IOTests.cs b/TRLevelControlTests/TR2/IOTests.cs index c2d77dd98..657149c81 100644 --- a/TRLevelControlTests/TR2/IOTests.cs +++ b/TRLevelControlTests/TR2/IOTests.cs @@ -220,7 +220,7 @@ public void FloorData_InsertFDTest() //Find a sector that currently has no floor data int room, roomSector = -1; - for (room = 0; room < lvl.NumRooms; room++) + for (room = 0; room < lvl.Rooms.Count; room++) { roomSector = lvl.Rooms[room].SectorList.ToList().FindIndex(s => s.FDIndex == 0); if (roomSector != -1) @@ -295,7 +295,7 @@ public void FloorData_RemoveFDTest() //Find a sector that currently has floor data int room, roomSector = -1; - for (room = 0; room < lvl.NumRooms; room++) + for (room = 0; room < lvl.Rooms.Count; room++) { roomSector = lvl.Rooms[room].SectorList.ToList().FindIndex(s => s.FDIndex > 0); if (roomSector != -1) @@ -338,8 +338,7 @@ public void FloorData_InsertRemoveFDEntryTest() TR2Level lvl = GetTR2Level(TR2LevelNames.LAIR); //Store the original floordata from the level - ushort[] originalFData = new ushort[lvl.NumFloorData]; - Array.Copy(lvl.FloorData, originalFData, lvl.NumFloorData); + List originalFData = new(lvl.FloorData); //Parse the floordata using FDControl FDControl fdataReader = new(); @@ -402,7 +401,6 @@ public void FloorData_InsertRemoveFDEntryTest() //Finally compare to make sure the original fdata was written back. CollectionAssert.AreEqual(originalFData, lvl.FloorData, "Floordata does not match"); - Assert.AreEqual((uint)lvl.FloorData.Length, lvl.NumFloorData); } [TestMethod] @@ -859,33 +857,30 @@ public void ModifyZonesTest() // for comparison. Dictionary flipOffZones = new(); Dictionary flipOnZones = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { flipOffZones[i] = lvl.Zones[i][FlipStatus.Off].Serialize(); flipOnZones[i] = lvl.Zones[i][FlipStatus.On].Serialize(); } // Add a new box - List boxes = lvl.Boxes.ToList(); - boxes.Add(boxes[0]); - lvl.Boxes = boxes.ToArray(); - lvl.NumBoxes++; + lvl.Boxes.Add(lvl.Boxes[0]); // Add a new zone for the box and store its serialized form for comparison - int newBoxIndex = (int)(lvl.NumBoxes - 1); + int newBoxIndex = (int)(lvl.Boxes.Count - 1); TR2BoxUtilities.DuplicateZone(lvl, 0); flipOffZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.Off].Serialize(); flipOnZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.On].Serialize(); // Verify the number of zone ushorts matches what's expected for the box count - Assert.AreEqual(TR2BoxUtilities.FlattenZones(lvl.Zones).Length, (int)(10 * lvl.NumBoxes)); + Assert.AreEqual(TR2BoxUtilities.FlattenZones(lvl.Zones).Count, (int)(10 * lvl.Boxes.Count)); // Write and re-read the level lvl = WriteReadTempLevel(lvl); // Capture all of the zones again. Make sure the addition of the zone above didn't // affect any of the others and that the addition itself matches after IO. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { byte[] flipOff = lvl.Zones[i][FlipStatus.Off].Serialize(); Assert.IsTrue(flipOffZones.ContainsKey(i)); @@ -909,7 +904,7 @@ public void ModifyOverlapsTest() // index itself (which also stores Blockable/Blocked bits). Dictionary> boxOverlaps = new(); Dictionary boxOverlapIndices = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { boxOverlaps[i] = TR2BoxUtilities.GetOverlaps(lvl, lvl.Boxes[i]); boxOverlapIndices[i] = lvl.Boxes[i].OverlapIndex; @@ -918,10 +913,10 @@ public void ModifyOverlapsTest() // Confirm the total matches the total number of overlaps in the level. int total = 0; boxOverlaps.Values.ToList().ForEach(v => total += v.Count); - Assert.AreEqual(lvl.NumOverlaps, (uint)total); + Assert.AreEqual(lvl.Overlaps.Count, total); // Write everything back with no changes. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { TR2BoxUtilities.UpdateOverlaps(lvl, lvl.Boxes[i], boxOverlaps[i]); } @@ -930,13 +925,13 @@ public void ModifyOverlapsTest() CollectionAssert.AreEqual(originalOverlaps, lvl.Overlaps.ToList()); // Confirm the box overlap indices are identical - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { Assert.AreEqual(boxOverlapIndices[i], lvl.Boxes[i].OverlapIndex); } // Add a new overlap to the first box, selecting a box that isn't already there. - for (ushort i = 1; i < lvl.NumBoxes; i++) + for (ushort i = 1; i < lvl.Boxes.Count; i++) { if (!boxOverlaps[0].Contains(i)) { @@ -954,7 +949,7 @@ public void ModifyOverlapsTest() // Capture all of the overlaps again and confirm the numbers are what we expect i.e. // the new overlap for box 0 exists and none of the other overlaps were affected by // the addition. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { List overlaps = TR2BoxUtilities.GetOverlaps(lvl, lvl.Boxes[i]); Assert.IsTrue(boxOverlaps.ContainsKey(i)); diff --git a/TRLevelControlTests/TR3/IOTests.cs b/TRLevelControlTests/TR3/IOTests.cs index e8fc0fae9..6688a1307 100644 --- a/TRLevelControlTests/TR3/IOTests.cs +++ b/TRLevelControlTests/TR3/IOTests.cs @@ -128,20 +128,15 @@ public void Floordata_ReadWrite_LevelHasMonkeySwingTest() TR3Level lvl = GetTR3Level(TR3LevelNames.THAMES); //Store the original floordata from the level - ushort[] originalFData = new ushort[lvl.NumFloorData]; - Array.Copy(lvl.FloorData, originalFData, lvl.NumFloorData); + List originalFData = new(lvl.FloorData); //Parse the floordata using FDControl and re-write the parsed data back FDControl fdataReader = new(); fdataReader.ParseFromLevel(lvl); fdataReader.WriteToLevel(lvl); - //Store the new floordata written back by FDControl - ushort[] newFData = lvl.FloorData; - //Compare to make sure the original fdata was written back. - CollectionAssert.AreEqual(originalFData, newFData, "Floordata does not match"); - Assert.AreEqual((uint)newFData.Length, lvl.NumFloorData); + CollectionAssert.AreEqual(originalFData, lvl.FloorData, "Floordata does not match");; } [TestMethod] @@ -153,33 +148,30 @@ public void ModifyZonesTest() // for comparison. Dictionary flipOffZones = new(); Dictionary flipOnZones = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { flipOffZones[i] = lvl.Zones[i][FlipStatus.Off].Serialize(); flipOnZones[i] = lvl.Zones[i][FlipStatus.On].Serialize(); } // Add a new box - List boxes = lvl.Boxes.ToList(); - boxes.Add(boxes[0]); - lvl.Boxes = boxes.ToArray(); - lvl.NumBoxes++; + lvl.Boxes.Add(lvl.Boxes[0]); // Add a new zone for the box and store its serialized form for comparison - int newBoxIndex = (int)(lvl.NumBoxes - 1); + int newBoxIndex = (int)(lvl.Boxes.Count - 1); TR2BoxUtilities.DuplicateZone(lvl, 0); flipOffZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.Off].Serialize(); flipOnZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.On].Serialize(); // Verify the number of zone ushorts matches what's expected for the box count - Assert.AreEqual(TR2BoxUtilities.FlattenZones(lvl.Zones).Length, (int)(10 * lvl.NumBoxes)); + Assert.AreEqual(TR2BoxUtilities.FlattenZones(lvl.Zones).Count, 10 * lvl.Boxes.Count); // Write and re-read the level lvl = WriteReadTempLevel(lvl); // Capture all of the zones again. Make sure the addition of the zone above didn't // affect any of the others and that the addition itself matches after IO. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { byte[] flipOff = lvl.Zones[i][FlipStatus.Off].Serialize(); Assert.IsTrue(flipOffZones.ContainsKey(i)); @@ -200,7 +192,7 @@ public void ModifyOverlapsTest() // index itself (which also stores Blockable/Blocked bits). Dictionary> boxOverlaps = new(); Dictionary boxOverlapIndices = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { boxOverlaps[i] = TR2BoxUtilities.GetOverlaps(lvl, lvl.Boxes[i]); boxOverlapIndices[i] = lvl.Boxes[i].OverlapIndex; @@ -211,13 +203,13 @@ public void ModifyOverlapsTest() // process above to ensure we get the same results. // Write everything back with no changes. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { TR2BoxUtilities.UpdateOverlaps(lvl, lvl.Boxes[i], boxOverlaps[i]); } Dictionary> newBoxOverlaps = new(); - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { newBoxOverlaps[i] = TR2BoxUtilities.GetOverlaps(lvl, lvl.Boxes[i]); } @@ -229,7 +221,7 @@ public void ModifyOverlapsTest() } // Add a new overlap to the first box, selecting a box that isn't already there. - for (ushort i = 1; i < lvl.NumBoxes; i++) + for (ushort i = 1; i < lvl.Boxes.Count; i++) { if (!boxOverlaps[0].Contains(i)) { @@ -247,7 +239,7 @@ public void ModifyOverlapsTest() // Capture all of the overlaps again and confirm the numbers are what we expect i.e. // the new overlap for box 0 exists and none of the other overlaps were affected by // the addition. - for (int i = 0; i < lvl.NumBoxes; i++) + for (int i = 0; i < lvl.Boxes.Count; i++) { List overlaps = TR2BoxUtilities.GetOverlaps(lvl, lvl.Boxes[i]); Assert.IsTrue(boxOverlaps.ContainsKey(i)); diff --git a/TRLevelControlTests/TR4/IOTests.cs b/TRLevelControlTests/TR4/IOTests.cs index 2f77a4f2a..ed09f84db 100644 --- a/TRLevelControlTests/TR4/IOTests.cs +++ b/TRLevelControlTests/TR4/IOTests.cs @@ -96,13 +96,13 @@ public void TestFloorData(string levelName) { TR4Level level = GetTR4Level(levelName); - List originalData = new(level.LevelDataChunk.Floordata); + List originalData = new(level.LevelDataChunk.FloorData); FDControl fdControl = new(); fdControl.ParseFromLevel(level); fdControl.WriteToLevel(level); - CollectionAssert.AreEqual(originalData, level.LevelDataChunk.Floordata); + CollectionAssert.AreEqual(originalData, level.LevelDataChunk.FloorData); } [TestMethod] @@ -111,20 +111,15 @@ public void Floordata_ReadWrite_MechBeetleTest() TR4Level lvl = GetTR4Level(TR4LevelNames.CLEOPATRA); //Store the original floordata from the level - ushort[] originalFData = new ushort[lvl.LevelDataChunk.NumFloorData]; - Array.Copy(lvl.LevelDataChunk.Floordata, originalFData, lvl.LevelDataChunk.NumFloorData); + List originalFData = new(lvl.LevelDataChunk.FloorData); //Parse the floordata using FDControl and re-write the parsed data back FDControl fdataReader = new(); fdataReader.ParseFromLevel(lvl); fdataReader.WriteToLevel(lvl); - //Store the new floordata written back by FDControl - ushort[] newFData = lvl.LevelDataChunk.Floordata; - //Compare to make sure the original fdata was written back. - CollectionAssert.AreEqual(originalFData, newFData, "Floordata does not match"); - Assert.AreEqual((uint)newFData.Length, lvl.LevelDataChunk.NumFloorData); + CollectionAssert.AreEqual(originalFData, lvl.LevelDataChunk.FloorData, "Floordata does not match"); } [TestMethod] @@ -133,19 +128,14 @@ public void Floordata_ReadWrite_TriggerTriggererTest() TR4Level lvl = GetTR4Level(TR4LevelNames.ALEXANDRIA); //Store the original floordata from the level - ushort[] originalFData = new ushort[lvl.LevelDataChunk.NumFloorData]; - Array.Copy(lvl.LevelDataChunk.Floordata, originalFData, lvl.LevelDataChunk.NumFloorData); + List originalFData = new(lvl.LevelDataChunk.FloorData); //Parse the floordata using FDControl and re-write the parsed data back FDControl fdataReader = new(); fdataReader.ParseFromLevel(lvl); fdataReader.WriteToLevel(lvl); - //Store the new floordata written back by FDControl - ushort[] newFData = lvl.LevelDataChunk.Floordata; - //Compare to make sure the original fdata was written back. - CollectionAssert.AreEqual(originalFData, newFData, "Floordata does not match"); - Assert.AreEqual((uint)newFData.Length, lvl.LevelDataChunk.NumFloorData); + CollectionAssert.AreEqual(originalFData, lvl.LevelDataChunk.FloorData, "Floordata does not match"); } } diff --git a/TRLevelControlTests/TR5/IOTests.cs b/TRLevelControlTests/TR5/IOTests.cs index 4dc9dd044..8c6b2196e 100644 --- a/TRLevelControlTests/TR5/IOTests.cs +++ b/TRLevelControlTests/TR5/IOTests.cs @@ -46,12 +46,12 @@ public void TestFloorData(string levelName) { TR5Level level = GetTR5Level(levelName); - List originalData = new(level.LevelDataChunk.Floordata); + List originalData = new(level.LevelDataChunk.FloorData); FDControl fdControl = new(); fdControl.ParseFromLevel(level); fdControl.WriteToLevel(level); - CollectionAssert.AreEqual(originalData, level.LevelDataChunk.Floordata); + CollectionAssert.AreEqual(originalData, level.LevelDataChunk.FloorData); } } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRCamerasControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRCamerasControl.cs index 040cf2153..27e719e27 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRCamerasControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRCamerasControl.cs @@ -23,7 +23,7 @@ public void Draw() if (ImGui.TreeNodeEx("Camera Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Camera count: " + IOManager.CurrentLevelAsTR1?.NumCameras); + ImGui.Text("Camera count: " + IOManager.CurrentLevelAsTR1?.Cameras.Count); ImGui.BeginChild("cam_property_display", new Vector2(400, 200), true); @@ -63,8 +63,8 @@ public void Clamp() _index = 0; TR1Level level = IOManager.CurrentLevelAsTR1; - if (_index >= level.NumCameras) - _index = (int)(level.NumCameras - 1); + if (_index >= level.Cameras.Count) + _index = (level.Cameras.Count - 1); } public void Populate() @@ -72,7 +72,7 @@ public void Populate() if (IOManager.CurrentLevelAsTR1 is null) return; - if (IOManager.CurrentLevelAsTR1?.NumCameras == 0) + if (IOManager.CurrentLevelAsTR1?.Cameras.Count == 0) return; _camera = IOManager.CurrentLevelAsTR1?.Cameras[_index]; @@ -93,7 +93,7 @@ public void Apply() if (IOManager.CurrentLevelAsTR1 is null || _camera is null) return; - if (IOManager.CurrentLevelAsTR1?.NumCameras == 0) + if (IOManager.CurrentLevelAsTR1?.Cameras.Count == 0) return; _camera.X = _x; diff --git a/TRLevelToolset/Controls/DataControls/TR/TRCinematicsControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRCinematicsControl.cs index 532d3bf22..b8ac27fd1 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRCinematicsControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRCinematicsControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Cinematic Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Cinematic frame Count: " + IOManager.CurrentLevelAsTR1?.NumCinematicFrames); + ImGui.Text("Cinematic frame Count: " + IOManager.CurrentLevelAsTR1?.CinematicFrames.Count); ImGui.TreePop(); } } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRFloorDataControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRFloorDataControl.cs index 398665875..a23e84a98 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRFloorDataControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRFloorDataControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Floor Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Floor Data Size: " + IOManager.CurrentLevelAsTR1?.NumFloorData + " uint16s."); + ImGui.Text("Floor Data Size: " + IOManager.CurrentLevelAsTR1?.FloorData.Count + " uint16s."); ImGui.TreePop(); } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRRoomControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRRoomControl.cs index 46a05005d..cdc5a3bd0 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRRoomControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRRoomControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Room Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Number of Rooms: " + IOManager.CurrentLevelAsTR1?.NumRooms); + ImGui.Text("Number of Rooms: " + IOManager.CurrentLevelAsTR1?.Rooms.Count); ImGui.TreePop(); } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs index f958588f3..15446cd12 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Sound Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Sound sources count: " + IOManager.CurrentLevelAsTR1?.NumSoundSources); + ImGui.Text("Sound sources count: " + IOManager.CurrentLevelAsTR1?.SoundSources.Count); ImGui.Text("Sound details count: " + IOManager.CurrentLevelAsTR1?.NumSoundDetails); ImGui.Text("Sound samples count: " + IOManager.CurrentLevelAsTR1?.NumSamples); ImGui.Text("Sound sample indices count: " + IOManager.CurrentLevelAsTR1?.NumSampleIndices); diff --git a/TRLevelToolset/Controls/DataControls/TR/TRStaticMeshControls.cs b/TRLevelToolset/Controls/DataControls/TR/TRStaticMeshControls.cs index 48f30d090..88b141912 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRStaticMeshControls.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRStaticMeshControls.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Static Mesh Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Static mesh count: " + IOManager.CurrentLevelAsTR1?.NumStaticMeshes); + ImGui.Text("Static mesh count: " + IOManager.CurrentLevelAsTR1?.StaticMeshes.Count); ImGui.TreePop(); } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRZoneControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRZoneControl.cs index 9885081be..fdcd32aec 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRZoneControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRZoneControl.cs @@ -10,9 +10,9 @@ public void Draw() { if (ImGui.TreeNodeEx("Zone Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Box count: " + IOManager.CurrentLevelAsTR1?.NumBoxes); - ImGui.Text("Overlap count: " + IOManager.CurrentLevelAsTR1?.NumOverlaps); - ImGui.Text("Zone Group count: " + IOManager.CurrentLevelAsTR1?.Zones.Length); + ImGui.Text("Box count: " + IOManager.CurrentLevelAsTR1?.Boxes.Count); + ImGui.Text("Overlap count: " + IOManager.CurrentLevelAsTR1?.Overlaps.Count); + ImGui.Text("Zone Group count: " + IOManager.CurrentLevelAsTR1?.Zones.Count); ImGui.TreePop(); } } diff --git a/TRModelTransporter/Handlers/CinematicTransportHandler.cs b/TRModelTransporter/Handlers/CinematicTransportHandler.cs index 4f35d1946..0b4494c1a 100644 --- a/TRModelTransporter/Handlers/CinematicTransportHandler.cs +++ b/TRModelTransporter/Handlers/CinematicTransportHandler.cs @@ -41,28 +41,25 @@ public static void Export(TR3Level level, TR3ModelDefinition definition, IEnumer public static void Import(TR1Level level, TR1ModelDefinition definition, bool forceOverwrite) { // We only import frames if the level doesn't have any already. - if (level.NumCinematicFrames == 0 || forceOverwrite) + if (level.CinematicFrames.Count == 0 || forceOverwrite) { - level.CinematicFrames = definition.CinematicFrames; - level.NumCinematicFrames = (ushort)definition.CinematicFrames.Length; + level.CinematicFrames = new(definition.CinematicFrames); } } public static void Import(TR2Level level, TR2ModelDefinition definition, bool forceOverwrite) { - if (level.NumCinematicFrames == 0 || forceOverwrite) + if (level.CinematicFrames.Count == 0 || forceOverwrite) { - level.CinematicFrames = definition.CinematicFrames; - level.NumCinematicFrames = (ushort)definition.CinematicFrames.Length; + level.CinematicFrames = new(definition.CinematicFrames); } } public static void Import(TR3Level level, TR3ModelDefinition definition, bool forceOverwrite) { - if (level.NumCinematicFrames == 0 || forceOverwrite) + if (level.CinematicFrames.Count == 0 || forceOverwrite) { - level.CinematicFrames = definition.CinematicFrames; - level.NumCinematicFrames = (ushort)definition.CinematicFrames.Length; + level.CinematicFrames = new(definition.CinematicFrames); } } } diff --git a/TRRandomizerCore/Helpers/TR2SavegameTester.cs b/TRRandomizerCore/Helpers/TR2SavegameTester.cs index 37c836e7b..a98c4b9ae 100644 --- a/TRRandomizerCore/Helpers/TR2SavegameTester.cs +++ b/TRRandomizerCore/Helpers/TR2SavegameTester.cs @@ -79,7 +79,7 @@ public static int EstimateSGSize(TR2Level level) size += _flipmapStatus; size += _cdTrackStatus; - size += (int)level.NumCameras * _cameraSize; + size += level.Cameras.Count * _cameraSize; // Expand the entity list to simulate everything that could actually be present List entities = new(level.Entities); diff --git a/TRRandomizerCore/Randomizers/TR1/TR1EnvironmentRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1EnvironmentRandomizer.cs index 8299a64a3..b8801e067 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1EnvironmentRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1EnvironmentRandomizer.cs @@ -193,7 +193,7 @@ private static void UpdateDoppelgangerScript(TR1CombinedLevel level) // Bacon Lara may have been added as a trap/puzzle, so we need to ensure the script knows // where to set her up. The mods will have stored this in a temporary flag as the entity // starting room may not necessarily be where her positioning should be calculated from. - int anchorRoom = Array.FindIndex(level.Data.Rooms, r => (r.Flags & EMAddDoppelgangerFunction.AnchorRoomFlag) > 0); + int anchorRoom = level.Data.Rooms.FindIndex(r => (r.Flags & EMAddDoppelgangerFunction.AnchorRoomFlag) > 0); if (anchorRoom == -1 && level.Is(TR1LevelNames.ATLANTIS)) { // Extra check for OG Atlantis to ensure the script is configured properly. diff --git a/TRRandomizerCore/Randomizers/TR1/TR1NightModeRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1NightModeRandomizer.cs index 5e9f7beb6..f77176dfe 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1NightModeRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1NightModeRandomizer.cs @@ -79,7 +79,7 @@ private void DarkenRooms(TR1CombinedLevel level) short intensity1 = (short)(TR2Room.DarknessIntensity1 * scale); ushort intensity2 = (ushort)(TR2Room.DarknessIntensity2 * (2 - scale)); - for (int i = 0; i < level.Data.NumRooms; i++) + for (int i = 0; i < level.Data.Rooms.Count; i++) { if (_excludedRooms.ContainsKey(level.Name) && _excludedRooms[level.Name].Contains(i)) { diff --git a/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs index ca59326bf..b188251d8 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs @@ -254,7 +254,7 @@ private void ActualiseRewardRoom(TR1CombinedLevel level, TRSecretRoom } rewardRoom.Room.ApplyToLevel(level.Data); - short roomIndex = (short)(level.Data.NumRooms - 1); + short roomIndex = (short)(level.Data.Rooms.Count - 1); // Convert the temporary doors rewardRoom.DoorIndices = placeholder.DoorIndices; @@ -297,16 +297,12 @@ private void ActualiseRewardRoom(TR1CombinedLevel level, TRSecretRoom { double countedSecrets = Settings.DevelopmentMode ? _maxSecretCount : level.Script.NumSecrets; rewardRoom.CameraIndices = new List(); - List cameras = level.Data.Cameras.ToList(); for (int i = 0; i < countedSecrets; i++) { - rewardRoom.CameraIndices.Add(cameras.Count); - cameras.Add(rewardRoom.Cameras[i % rewardRoom.Cameras.Count]); + rewardRoom.CameraIndices.Add(level.Data.Cameras.Count); + level.Data.Cameras.Add(rewardRoom.Cameras[i % rewardRoom.Cameras.Count]); } - level.Data.Cameras = cameras.ToArray(); - level.Data.NumCameras = (uint)cameras.Count; - ushort cameraTarget; if (rewardRoom.CameraTarget != null && ItemFactory.CanCreateItem(level.Name, level.Data.Entities)) { @@ -536,7 +532,7 @@ private static void PopulateScriptStrings(int index, List gameStrings, s private bool TestSecretPlacement(TR1CombinedLevel level, Location location, FDControl floorData) { // Check if this secret is being added to a flipped room, as that won't work - for (int i = 0; i < level.Data.NumRooms; i++) + for (int i = 0; i < level.Data.Rooms.Count; i++) { if (level.Data.Rooms[i].AlternateRoom == location.Room) { diff --git a/TRRandomizerCore/Randomizers/TR3/TR3ItemRandomizer.cs b/TRRandomizerCore/Randomizers/TR3/TR3ItemRandomizer.cs index 8f2ad8747..1f4d6c0ba 100644 --- a/TRRandomizerCore/Randomizers/TR3/TR3ItemRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3/TR3ItemRandomizer.cs @@ -311,7 +311,7 @@ private List GetItemLocationPool(TR3CombinedLevel level, bool keyItemM if (level.HasExposureMeter) { // Don't put items underwater if it's too cold - for (int i = 0; i < level.Data.NumRooms; i++) + for (int i = 0; i < level.Data.Rooms.Count; i++) { if (level.Data.Rooms[i].ContainsWater) { diff --git a/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs b/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs index 612745340..1b0f402e7 100644 --- a/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs @@ -192,7 +192,7 @@ private void ActualiseRewardRoom(TR3CombinedLevel level, TRSecretRoom } rewardRoom.Room.ApplyToLevel(level.Data); - short roomIndex = (short)(level.Data.NumRooms - 1); + short roomIndex = (short)(level.Data.Rooms.Count - 1); // Convert the temporary doors rewardRoom.DoorIndices = placeholder.DoorIndices; @@ -232,16 +232,12 @@ private void ActualiseRewardRoom(TR3CombinedLevel level, TRSecretRoom { double countedSecrets = Settings.DevelopmentMode ? _devModeSecretCount : level.Script.NumSecrets; rewardRoom.CameraIndices = new List(); - List cameras = level.Data.Cameras.ToList(); for (int i = 0; i < countedSecrets; i++) { - rewardRoom.CameraIndices.Add(cameras.Count); - cameras.Add(rewardRoom.Cameras[i % rewardRoom.Cameras.Count]); + rewardRoom.CameraIndices.Add(level.Data.Cameras.Count); + level.Data.Cameras.Add(rewardRoom.Cameras[i % rewardRoom.Cameras.Count]); } - level.Data.Cameras = cameras.ToArray(); - level.Data.NumCameras = (uint)cameras.Count; - FDControl floorData = new(); floorData.ParseFromLevel(level.Data); @@ -511,7 +507,7 @@ private static void SetPuzzleTypeName(TR3CombinedLevel level, TR3Type itemType, private bool TestSecretPlacement(TR3CombinedLevel level, Location location, FDControl floorData) { // Check if this secret is being added to a flipped room, as that won't work - for (int i = 0; i < level.Data.NumRooms; i++) + for (int i = 0; i < level.Data.Rooms.Count; i++) { if (level.Data.Rooms[i].AlternateRoom == location.Room) { diff --git a/TRRandomizerCore/Randomizers/TR3/TR3WeatherRandomizer.cs b/TRRandomizerCore/Randomizers/TR3/TR3WeatherRandomizer.cs index ca8c957a7..005f8cfc5 100644 --- a/TRRandomizerCore/Randomizers/TR3/TR3WeatherRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3/TR3WeatherRandomizer.cs @@ -81,10 +81,9 @@ private static void SetWeatherDependencies(TR3CombinedLevel level) } } - private static void SetWeatherRooms(TR3Room[] rooms) + private static void SetWeatherRooms(List rooms) { - rooms.Where(r => r.IsSkyboxVisible) - .ToList() + rooms.FindAll(r => r.IsSkyboxVisible) .ForEach(r => r.IsWindy = true); } } diff --git a/TRRandomizerCore/Randomizers/TR3R/TR3RItemRandomizer.cs b/TRRandomizerCore/Randomizers/TR3R/TR3RItemRandomizer.cs index 3fec3eaf8..13c96dfef 100644 --- a/TRRandomizerCore/Randomizers/TR3R/TR3RItemRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3R/TR3RItemRandomizer.cs @@ -115,7 +115,7 @@ private List GetItemLocationPool(TR3RCombinedLevel level, bool keyItem if (level.Script.HasColdWater) { // Don't put items underwater if it's too cold - for (int i = 0; i < level.Data.NumRooms; i++) + for (int i = 0; i < level.Data.Rooms.Count; i++) { if (level.Data.Rooms[i].ContainsWater) { diff --git a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs index 8c03175e8..cab1f5cea 100644 --- a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs @@ -730,7 +730,7 @@ private void DeleteAnimatedTextures(L level) protected abstract List GetModels(L level); protected abstract TRMesh[] GetModelMeshes(L level, TRModel model); protected abstract TRMesh[] GetLevelMeshes(L level); - protected abstract TRStaticMesh[] GetStaticMeshes(L level); + protected abstract List GetStaticMeshes(L level); protected abstract TRMesh GetStaticMesh(L level, TRStaticMesh staticMesh); protected abstract bool IsSkybox(TRModel model); protected abstract bool IsLaraModel(TRModel model); diff --git a/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs index 04c0a0f58..f638798a7 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs @@ -145,7 +145,7 @@ protected override TRMesh GetStaticMesh(TR1Level level, TRStaticMesh staticMesh) return TRMeshUtilities.GetMesh(level, staticMesh.Mesh); } - protected override TRStaticMesh[] GetStaticMeshes(TR1Level level) + protected override List GetStaticMeshes(TR1Level level) { return level.StaticMeshes; } diff --git a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs index f0e5070f8..3f350729a 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs @@ -117,7 +117,7 @@ protected override TRMesh GetStaticMesh(TR2Level level, TRStaticMesh staticMesh) return TRMeshUtilities.GetMesh(level, staticMesh.Mesh); } - protected override TRStaticMesh[] GetStaticMeshes(TR2Level level) + protected override List GetStaticMeshes(TR2Level level) { return level.StaticMeshes; } diff --git a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs index 2d6540bf9..3af3d2e49 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs @@ -112,7 +112,7 @@ protected override TRMesh GetStaticMesh(TR3Level level, TRStaticMesh staticMesh) return TRMeshUtilities.GetMesh(level, staticMesh.Mesh); } - protected override TRStaticMesh[] GetStaticMeshes(TR3Level level) + protected override List GetStaticMeshes(TR3Level level) { return level.StaticMeshes; } diff --git a/TRRandomizerCore/Utilities/Locations/TR1LocationGenerator.cs b/TRRandomizerCore/Utilities/Locations/TR1LocationGenerator.cs index 709719c0d..070535d01 100644 --- a/TRRandomizerCore/Utilities/Locations/TR1LocationGenerator.cs +++ b/TRRandomizerCore/Utilities/Locations/TR1LocationGenerator.cs @@ -40,7 +40,7 @@ protected override List GetStaticMeshes(TR1Level level) protected override int GetRoomCount(TR1Level level) { - return level.NumRooms; + return level.Rooms.Count; } protected override short GetFlipMapRoom(TR1Level level, short room) diff --git a/TRRandomizerCore/Utilities/Locations/TR2LocationGenerator.cs b/TRRandomizerCore/Utilities/Locations/TR2LocationGenerator.cs index 261f160fd..3595fa7e4 100644 --- a/TRRandomizerCore/Utilities/Locations/TR2LocationGenerator.cs +++ b/TRRandomizerCore/Utilities/Locations/TR2LocationGenerator.cs @@ -38,7 +38,7 @@ protected override List GetStaticMeshes(TR2Level level) protected override int GetRoomCount(TR2Level level) { - return level.NumRooms; + return level.Rooms.Count; } protected override short GetFlipMapRoom(TR2Level level, short room) diff --git a/TRRandomizerCore/Utilities/Locations/TR3LocationGenerator.cs b/TRRandomizerCore/Utilities/Locations/TR3LocationGenerator.cs index 264406573..11fb52e1e 100644 --- a/TRRandomizerCore/Utilities/Locations/TR3LocationGenerator.cs +++ b/TRRandomizerCore/Utilities/Locations/TR3LocationGenerator.cs @@ -38,7 +38,7 @@ protected override List GetStaticMeshes(TR3Level level) protected override int GetRoomCount(TR3Level level) { - return level.NumRooms; + return level.Rooms.Count; } protected override short GetFlipMapRoom(TR3Level level, short room)