From 6d093dcf67b7c0dc2ea36c1f676fc7d466c7a9de Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sun, 6 Nov 2022 16:45:46 -0300 Subject: [PATCH 01/12] Started some attempts to extract the buffers so I can study them more closely and generate more tests. --- .../ExtractingBuffersOfEverything.csproj | 14 +++ ExtractingBuffersOfEverything/Program.cs | 105 +++++++++++++++++ UWRandomizerEditor/LEVDotARK/ArkLoader.cs | 6 + UWRandomizerEditor/LEVDotARK/Blocks/Block.cs | 10 +- .../Blocks/TileMapMasterObjectListBlock.cs | 10 +- .../LEVDotARK/GameObjects/GameObject.cs | 11 +- .../GameObjects/GameObjectFactory.cs | 110 +++++++++++------- .../LEVDotARK/GameObjects/MobileObject.cs | 9 ++ UWRandomizerEditor/LEVDotARK/TileInfo.cs | 2 +- UnderworldRandomizer.sln | 6 + 10 files changed, 229 insertions(+), 54 deletions(-) create mode 100644 ExtractingBuffersOfEverything/ExtractingBuffersOfEverything.csproj create mode 100644 ExtractingBuffersOfEverything/Program.cs diff --git a/ExtractingBuffersOfEverything/ExtractingBuffersOfEverything.csproj b/ExtractingBuffersOfEverything/ExtractingBuffersOfEverything.csproj new file mode 100644 index 0000000..d344892 --- /dev/null +++ b/ExtractingBuffersOfEverything/ExtractingBuffersOfEverything.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0-windows + enable + enable + + + + + + + diff --git a/ExtractingBuffersOfEverything/Program.cs b/ExtractingBuffersOfEverything/Program.cs new file mode 100644 index 0000000..758b402 --- /dev/null +++ b/ExtractingBuffersOfEverything/Program.cs @@ -0,0 +1,105 @@ +// See https://aka.ms/new-console-template for more information + +using UWRandomizerEditor; +using UWRandomizerEditor.LEVDotARK; +using static UWRandomizerEditor.Utils; + +namespace ExtractingEverything; + +public static class Program { + public static void Main() + { + var path = @"C:\Users\Karl\Desktop\UnderworldStudy\UW\DATA\LEV.ARK"; + var baseBufferPath = @"C:\Users\Karl\Desktop\UnderworldStudy\Buffers"; + + Directory.CreateDirectory(baseBufferPath); + + var Ark = new ArkLoader(path); + + // Header + Ark.header.SaveBuffer(baseBufferPath, "header.bin"); + + // Blocks + int counter_block = 0; + var blockPath = Path.Join(baseBufferPath, "Blocks"); + Directory.CreateDirectory(blockPath); + foreach (var block in Ark.blocks) + { + block.SaveBuffer(blockPath, $"Block{counter_block}_level{block.LevelNumber}_length{block.TotalBlockLength}.bin"); + counter_block++; + } + + // Tilemap Blocks + counter_block = 0; + var tilemapBlocksPath = Path.Join(baseBufferPath, "TileMaps"); + Directory.CreateDirectory(tilemapBlocksPath); + foreach (var block in Ark.TileMapObjectsBlocks) + { + var nthTileMapBlockPath = Path.Join(tilemapBlocksPath, $"TileMapBlock{counter_block}"); + Directory.CreateDirectory(nthTileMapBlockPath); + + block.SaveBuffer(nthTileMapBlockPath, $"TileMapBlock{counter_block}_fullbuffer.bin"); + StdSaveBuffer(block.TileMapBuffer, nthTileMapBlockPath, $"TileMapBuffer{counter_block}_fullbuffer.bin"); + StdSaveBuffer(block.MobileObjectInfoBuffer, nthTileMapBlockPath, + $"MobileObjectInfoBuffer{counter_block}_fullbuffer.bin"); + StdSaveBuffer(block.StaticObjectInfoBuffer, nthTileMapBlockPath, + $"StaticObjectInfoBuffer{counter_block}_fullbuffer.bin"); + StdSaveBuffer(block.FreeListMobileObjectBuffer, nthTileMapBlockPath, + $"FreeListMobileObject{counter_block}_fullbuffer.bin"); + StdSaveBuffer(block.FreeListStaticObjectBuffer, nthTileMapBlockPath, + $"FreeListStaticObject{counter_block}_fullbuffer.bin"); + + var counter_objects = 0; + // GameObjects + // foreach (var gameObject in block.AllGameObjects) + // { + // gameObject.SaveBuffer(nthTileMapBlockPath, + // $"GameObjectIdx{gameObject.IdxAtObjectArray}_ctr{counter_objects}_id{gameObject.ItemID}.bin"); + // counter_objects++; + // } + + // Save Mobile Object buffers + counter_objects = 0; + foreach (var mobileObject in block.MobileObjects) + { + mobileObject.SaveBuffer(nthTileMapBlockPath, + $"MobileObjectIdx{mobileObject.IdxAtObjectArray}_ctr{counter_objects}.bin"); + counter_objects++; + } + + // Save static Object buffers + // Doesn't reset to 0. + foreach (var staticObject in block.StaticObjects) + { + staticObject.SaveBuffer(nthTileMapBlockPath, + $"StaticObjectIdx{staticObject.IdxAtObjectArray}_ctr{counter_objects}.bin"); + counter_objects++; + } + + // Save free list Mobile objects buffers + counter_objects = 0; + foreach (var mobileFreeObject in block.FreeListMobileObject) + { + StdSaveBuffer(mobileFreeObject.Buffer, nthTileMapBlockPath, + $"mobileFreeObjectIdx{mobileFreeObject.EntryNum}_ctr{counter_objects}.bin"); + counter_objects++; + } + // Save free list Static objects buffers + foreach (var staticFreeObject in block.FreeListStaticObject) + { + StdSaveBuffer(staticFreeObject.Buffer, nthTileMapBlockPath, + $"staticFreeObjectIdx{staticFreeObject.EntryNum}_ctr{counter_objects}.bin"); + counter_objects++; + } + + // Iterate through tiles + counter_objects = 0; + foreach (var tile in block.TileInfos) + { + tile.SaveBuffer(nthTileMapBlockPath, $"TileIdx{counter_objects}Offset{tile.Offset},X{tile.XYPos[0]}Y{tile.XYPos[1]}.bin"); + counter_objects++; + } + counter_block++; + } + } +} \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/ArkLoader.cs b/UWRandomizerEditor/LEVDotARK/ArkLoader.cs index 3fab61c..b64abe8 100644 --- a/UWRandomizerEditor/LEVDotARK/ArkLoader.cs +++ b/UWRandomizerEditor/LEVDotARK/ArkLoader.cs @@ -109,6 +109,12 @@ public void LoadBlocks() if (block is TileMapMasterObjectListBlock tilemap) { TileMapObjectsBlocks[currblocktypecount] = tilemap; + tilemap.Populate_MobileObjectsFromBuffer(); + tilemap.Populate_StaticObjectsFromBuffer(); + tilemap.Populate_AllGameObjectsFromBuffer(); + tilemap.Populate_FreeListMobileObjectArrFromBuffer(); + tilemap.Populate_FreeListStaticObjectArrFromBuffer(); + tilemap.ExtractInfoFromTileMapBuffer(); } else if (block is ObjectAnimationOverlayInfoBlock obj) { diff --git a/UWRandomizerEditor/LEVDotARK/Blocks/Block.cs b/UWRandomizerEditor/LEVDotARK/Blocks/Block.cs index ca3cfae..7ab89fc 100644 --- a/UWRandomizerEditor/LEVDotARK/Blocks/Block.cs +++ b/UWRandomizerEditor/LEVDotARK/Blocks/Block.cs @@ -7,14 +7,20 @@ public abstract class Block: ISaveBinary { public byte[] blockbuffer; public int LevelNumber; - public int TotalBlockLength; + + public int TotalBlockLength + { + get + { + return blockbuffer.Length; + } + } protected Block(): this(new byte[] { }, -1){ } public Block(byte[] blockbuffer, int levelNumber) { this.blockbuffer = blockbuffer; - this.TotalBlockLength = blockbuffer.Length; this.LevelNumber = levelNumber; } diff --git a/UWRandomizerEditor/LEVDotARK/Blocks/TileMapMasterObjectListBlock.cs b/UWRandomizerEditor/LEVDotARK/Blocks/TileMapMasterObjectListBlock.cs index 8942c68..ef26163 100644 --- a/UWRandomizerEditor/LEVDotARK/Blocks/TileMapMasterObjectListBlock.cs +++ b/UWRandomizerEditor/LEVDotARK/Blocks/TileMapMasterObjectListBlock.cs @@ -309,7 +309,7 @@ public void UpdateTileMapBuffer() #region buffer definitions - protected byte[] TileMapBuffer + public byte[] TileMapBuffer { get { return blockbuffer[TileMapOffset..(TileMapOffset + TileMapLength)]; } set @@ -319,7 +319,7 @@ protected byte[] TileMapBuffer } } - protected byte[] MobileObjectInfoBuffer + public byte[] MobileObjectInfoBuffer { get { return blockbuffer[MobileObjectInfoOffset..(MobileObjectInfoOffset + MobileObjectInfoLength)]; } set @@ -329,7 +329,7 @@ protected byte[] MobileObjectInfoBuffer } } - protected byte[] StaticObjectInfoBuffer + public byte[] StaticObjectInfoBuffer { get { return blockbuffer[StaticObjectInfoOffset..(StaticObjectInfoOffset + StaticObjectInfoLength)]; } set @@ -339,7 +339,7 @@ protected byte[] StaticObjectInfoBuffer } } - protected byte[] FreeListMobileObjectBuffer + public byte[] FreeListMobileObjectBuffer { get { @@ -353,7 +353,7 @@ protected byte[] FreeListMobileObjectBuffer } } - protected byte[] FreeListStaticObjectBuffer + public byte[] FreeListStaticObjectBuffer { get { diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs index 400049d..223938d 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs @@ -6,7 +6,7 @@ // TODO: Add checks that prevent modification if id=0. namespace UWRandomizerEditor.LEVDotARK.GameObjects { - public class GameObject: IEquatable, IShouldIMove + public class GameObject: IEquatable, IShouldIMove, ISaveBinary { public const int InfoSize = 2; public const int InfoNum = 4; @@ -293,5 +293,14 @@ public virtual bool Equals(GameObject? other) return true; } + + public virtual string SaveBuffer(string? basePath = null, string filename = "") + { + if (basePath is null) + { + basePath = Settings.DefaultBinaryTestsPath; + } + return StdSaveBuffer(Buffer, basePath, filename.Length == 0 ? $@"_GameObject_{IdxAtObjectArray}" : filename); + } } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs index a2460ac..f7fbbf8 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs @@ -15,55 +15,75 @@ private static short getItemIDFromBuffer(byte[] buffer) public static GameObject CreateFromBuffer(byte[] buffer, short idxAtArray) { - // TODO: Dismember this more. This appears to be very general, and there's some intermixing short itemID = getItemIDFromBuffer(buffer); - - if (itemID <= 0x1f) // Weapons and missiles - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x20 & itemID <= 0x3f) // Armor and clothes - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x40 & itemID <= 0x7f) // Monsters + if (buffer.Length == MobileObject.TotalLength) + { return new MobileObject(buffer, idxAtArray); - if (itemID >= 0x80 & itemID <= 0x8f) // Containers - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x90 & itemID <= 0x97) // Light sources - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x98 & itemID <= 0x9f) // Wands - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0xa0 & itemID <= 0xaf) // Treasure - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0xb0 & itemID <= 0xbf) // Comestible - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0xc0 & itemID <= 0xdf) // Scenery and junk - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0xe0 & itemID <= 0xff) // Runes and bits of key - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x100 & itemID <= 0x10e) - return new Key(buffer, idxAtArray); - if (itemID == 0x10f) - return new Lock(buffer, idxAtArray); - if (itemID >= 0x110 & itemID <= 0x11f) // quest items - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x120 & itemID <= 0x12f) // Inventory items, misc stuff - return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x130 & itemID <= 0x13f) // Books and scrolls + } + + if (buffer.Length == StaticObject.TotalLength) + { return new StaticObject(buffer, idxAtArray); - if (itemID >= 0x140 & itemID <= 0x14f) // Doors - return new Door(buffer, idxAtArray); - if (itemID >= 0x150 & itemID <= 0x15f) // Furniture - return new Furniture(buffer, idxAtArray); - if (itemID >= 0x160 & itemID <= 0x16f) // Pillars, etc - return new Furniture(buffer, idxAtArray); // TODO: should be joined with furniture? - if (itemID >= 0x170 & itemID <= 0x17f) // Switches - return new TexturedGameObject(buffer, idxAtArray); - if (itemID >= 0x180 & itemID <= 0x19f) // Traps - return new Trap(buffer, idxAtArray); - if (itemID >= 0x1a0 & itemID <= 0x1bf) // Triggers - return new Trigger(buffer, idxAtArray); - if (itemID >= 0x1c0 & itemID <= 0x1cf) // Explosions, splats, fountain, silver tree - return new StaticObject(buffer, idxAtArray) {ShouldBeMoved = false}; + } - throw new ArgumentException($"GameObject with id '{itemID}' doesn't exist"); + + // if (buffer.Length == MobileObject.TotalLength) + // { + // return new MobileObject(buffer, idxAtArray); + // } + // else if (buffer.Length == StaticObject.TotalLength) + // { + // if (itemID <= 0x1f) // Weapons and missiles + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x20 & itemID <= 0x3f) // Armor and clothes + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x80 & itemID <= 0x8f) // Containers + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x90 & itemID <= 0x97) // Light sources + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x98 & itemID <= 0x9f) // Wands + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0xa0 & itemID <= 0xaf) // Treasure + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0xb0 & itemID <= 0xbf) // Comestible + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0xc0 & itemID <= 0xdf) // Scenery and junk + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0xe0 & itemID <= 0xff) // Runes and bits of key + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x100 & itemID <= 0x10e) + // return new Key(buffer, idxAtArray); + // if (itemID == 0x10f) + // return new Lock(buffer, idxAtArray); + // if (itemID >= 0x110 & itemID <= 0x11f) // quest items + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x120 & itemID <= 0x12f) // Inventory items, misc stuff + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x130 & itemID <= 0x13f) // Books and scrolls + // return new StaticObject(buffer, idxAtArray); + // if (itemID >= 0x140 & itemID <= 0x14f) // Doors + // return new Door(buffer, idxAtArray); + // if (itemID >= 0x150 & itemID <= 0x15f) // Furniture + // return new Furniture(buffer, idxAtArray); + // if (itemID >= 0x160 & itemID <= 0x16f) // Pillars, etc + // return new Furniture(buffer, idxAtArray); // TODO: should be joined with furniture? + // if (itemID >= 0x170 & itemID <= 0x17f) // Switches + // return new TexturedGameObject(buffer, idxAtArray); + // if (itemID >= 0x180 & itemID <= 0x19f) // Traps + // return new Trap(buffer, idxAtArray); + // if (itemID >= 0x1a0 & itemID <= 0x1bf) // Triggers + // return new Trigger(buffer, idxAtArray); + // if (itemID >= 0x1c0 & itemID <= 0x1cf) // Explosions, splats, fountain, silver tree + // return new StaticObject(buffer, idxAtArray) {ShouldBeMoved = false}; + // if (itemID > 0x1cf & itemID <= 0x1ff) // Not described in the text + // return new StaticObject(buffer, idxAtArray); + // + // if (itemID > 0x1ff) + // { + // throw new ArgumentException($"Invalid itemID {itemID} when creating a GameObject"); + // } + // } + throw new ArgumentException($"Invalid buffer length of {buffer.Length} when creating a GameObject"); } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs index e3f95c5..7e86efd 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs @@ -247,5 +247,14 @@ public MobileObject(short short1, short short2, short short3, short short4, byte IdxAtObjectArray = idx; UpdateEntries(); } + public override string SaveBuffer(string? basePath = null, string filename = "") + { + if (basePath is null) + { + basePath = Settings.DefaultBinaryTestsPath; + } + return StdSaveBuffer(Buffer, basePath, filename.Length == 0 ? $@"_GameObject_{IdxAtObjectArray}" : filename); + } + } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/TileInfo.cs b/UWRandomizerEditor/LEVDotARK/TileInfo.cs index 7cc8821..55c587a 100644 --- a/UWRandomizerEditor/LEVDotARK/TileInfo.cs +++ b/UWRandomizerEditor/LEVDotARK/TileInfo.cs @@ -160,7 +160,7 @@ public int FirstObjIdx public UWLinkedList ObjectChain; // Store - public int[]? XYPos + public int[] XYPos { get { diff --git a/UnderworldRandomizer.sln b/UnderworldRandomizer.sln index 8bc894d..2116a10 100644 --- a/UnderworldRandomizer.sln +++ b/UnderworldRandomizer.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ItemCombinations", "ItemCom EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWRandomizer", "UWRandomizer\UWRandomizer.csproj", "{B40CA507-E157-47FC-8A79-62EACC44AD3B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtractingBuffersOfEverything", "ExtractingBuffersOfEverything\ExtractingBuffersOfEverything.csproj", "{043DB0BB-4A3B-4F00-B89D-516FB6EB6187}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {B40CA507-E157-47FC-8A79-62EACC44AD3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B40CA507-E157-47FC-8A79-62EACC44AD3B}.Release|Any CPU.ActiveCfg = Release|Any CPU {B40CA507-E157-47FC-8A79-62EACC44AD3B}.Release|Any CPU.Build.0 = Release|Any CPU + {043DB0BB-4A3B-4F00-B89D-516FB6EB6187}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {043DB0BB-4A3B-4F00-B89D-516FB6EB6187}.Debug|Any CPU.Build.0 = Debug|Any CPU + {043DB0BB-4A3B-4F00-B89D-516FB6EB6187}.Release|Any CPU.ActiveCfg = Release|Any CPU + {043DB0BB-4A3B-4F00-B89D-516FB6EB6187}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 7657215d72f9e7c6c62855189f630418fea70f56 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:17:34 -0300 Subject: [PATCH 02/12] Changed shorts to ushorts in object classes. --- .../LEVDotARK/GameObjects/GameObject.cs | 40 +++++++++---------- .../LEVDotARK/GameObjects/MobileObject.cs | 8 ++-- .../GameObjects/QuantityGameObject.cs | 6 +-- .../GameObjects/SpecialLinkGameObject.cs | 6 +-- .../GameObjects/SpecialPropertyGameObject.cs | 6 +-- .../LEVDotARK/GameObjects/Specifics/Doors.cs | 4 +- .../GameObjects/Specifics/EnchantedArmor.cs | 4 +- .../GameObjects/Specifics/EnchantedObject.cs | 4 +- .../GameObjects/Specifics/EnchantedWand.cs | 4 +- .../LEVDotARK/GameObjects/Specifics/Key.cs | 2 +- .../LEVDotARK/GameObjects/Specifics/Lock.cs | 4 +- .../LEVDotARK/GameObjects/Specifics/Weapon.cs | 4 +- .../LEVDotARK/GameObjects/StaticObject.cs | 2 +- .../GameObjects/TexturedGameObject.cs | 6 +-- UWRandomizerEditor/LEVDotARK/TileInfo.cs | 22 ++-------- 15 files changed, 54 insertions(+), 68 deletions(-) diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs index 223938d..8157669 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObject.cs @@ -20,10 +20,10 @@ public class GameObject: IEquatable, IShouldIMove, ISaveBinary public byte[] Buffer = new byte[TotalLength]; public short[] GeneralInfo = new short[InfoNum] { 0, 0, 0, 0 }; - protected short link_specialField; - protected short objid_flagsField; - protected short positionField; - protected short quality_chainField; + public ushort link_specialField; + protected ushort objid_flagsField; + protected ushort positionField; + protected ushort quality_chainField; protected GameObject() { } @@ -41,8 +41,8 @@ public GameObject(byte[] buffer, short idxAtObjArray) // this.link_specialField = BitConverter.ToInt16(buffer, 6); } - public GameObject(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) + public GameObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) { this.objid_flagsField = objid_flagsField; this.positionField = positionField; @@ -53,10 +53,10 @@ public GameObject(short objid_flagsField, short positionField, short quality_cha public void UpdateEntries() { - this.objid_flagsField = BitConverter.ToInt16(Buffer, 0); - this.positionField = BitConverter.ToInt16(Buffer, 2); - this.quality_chainField = BitConverter.ToInt16(Buffer, 4); - this.link_specialField = BitConverter.ToInt16(Buffer, 6); + this.objid_flagsField = BitConverter.ToUInt16(Buffer, 0); + this.positionField = BitConverter.ToUInt16(Buffer, 2); + this.quality_chainField = BitConverter.ToUInt16(Buffer, 4); + this.link_specialField = BitConverter.ToUInt16(Buffer, 6); } public void UpdateBuffer() @@ -79,7 +79,7 @@ public void UpdateBuffer() public int ItemID { get { return GetBits(objid_flagsField, 0b111111111, 0); } - set { objid_flagsField = (short)SetBits(objid_flagsField, value, 0b111111111, 0); UpdateBuffer(); } + set { objid_flagsField = (ushort)SetBits(objid_flagsField, value, 0b111111111, 0); UpdateBuffer(); } } public int Flags @@ -90,7 +90,7 @@ public int Flags // return GetBits(objid_flagsField, 0b1111, 9); return GetBits(objid_flagsField, 0b111, 9); } - set { objid_flagsField = (short)SetBits(objid_flagsField, value, 0b1111, 9); UpdateBuffer(); } + set { objid_flagsField = (ushort)SetBits(objid_flagsField, value, 0b1111, 9); UpdateBuffer(); } } public int EnchantFlag @@ -127,28 +127,28 @@ public byte Zpos { // get { return (byte) (positionField & 0b1111111); } get { return (byte)GetBits(positionField, 0b1111111, 0); } - set { this.positionField = (short)SetBits(positionField, value, 0b1111111, 0); UpdateBuffer(); } + set { this.positionField = (ushort)SetBits(positionField, value, 0b1111111, 0); UpdateBuffer(); } } public byte Heading { // get { return (byte) ((positionField >> 7) & 0b111); } get { return (byte)GetBits(positionField, 0b111, 7); } - set { positionField = (short)SetBits(positionField, value, 0b111, 7); UpdateBuffer(); } + set { positionField = (ushort)SetBits(positionField, value, 0b111, 7); UpdateBuffer(); } } public byte Ypos { // get { return (byte) ((positionField >> 10) & 0b111); } get { return (byte)GetBits(positionField, 0b111, 10); } - set { positionField = (short)SetBits(positionField, value, 0b111, 10); UpdateBuffer(); } + set { positionField = (ushort)SetBits(positionField, value, 0b111, 10); UpdateBuffer(); } } public byte Xpos { // get { return (byte) ((positionField >> 13) & 0b111); } get { return (byte)GetBits(positionField, 0b111, 13); } - set { positionField = (short)SetBits(positionField, value, 0b111, 13); UpdateBuffer(); } + set { positionField = (ushort)SetBits(positionField, value, 0b111, 13); UpdateBuffer(); } } #endregion #region Third Short @@ -156,14 +156,14 @@ public byte Quality { // get { return (byte) (quality_chainField & 0b111111); } get { return (byte)GetBits(quality_chainField, 0b111111, 0); } - set { quality_chainField = (short)SetBits(quality_chainField, value, 0b111111, 0); UpdateBuffer(); } + set { quality_chainField = (ushort)SetBits(quality_chainField, value, 0b111111, 0); UpdateBuffer(); } } public short next { // get { return (byte) ((quality_chainField >> 6) & 0b1111111111); } get { return (short)GetBits(quality_chainField, 0b1111111111, 6); } - set { quality_chainField = (short)SetBits(quality_chainField, value, 0b1111111111, 6); UpdateBuffer(); } + set { quality_chainField = (ushort)SetBits(quality_chainField, value, 0b1111111111, 6); UpdateBuffer(); } } @@ -177,14 +177,14 @@ public byte Owner_or_special { // get { return (byte) (link_specialField & 0b111111); } get { return (byte)GetBits(link_specialField, 0b111111, 0); } - set { link_specialField = (short)SetBits(link_specialField, value, 0b111111, 0); UpdateBuffer(); } + set { link_specialField = (ushort)SetBits(link_specialField, value, 0b111111, 0); UpdateBuffer(); } } public short QuantityOrSpecialLinkOrSpecialProperty { // get { return (byte) ((link_specialField >> 6) & 0b1111111111); } get { return (byte)GetBits(link_specialField, 0b1111111111, 6); } - set { link_specialField = (short)SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } + set { link_specialField = (ushort)SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } } #endregion diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs index 7e86efd..719b43f 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs @@ -150,10 +150,10 @@ public int whoami public new void UpdateEntries() { // From base - objid_flagsField = BitConverter.ToInt16(Buffer, 0); - positionField = BitConverter.ToInt16(Buffer, 2); - quality_chainField = BitConverter.ToInt16(Buffer, 4); - link_specialField = BitConverter.ToInt16(Buffer, 6); + objid_flagsField = BitConverter.ToUInt16(Buffer, 0); + positionField = BitConverter.ToUInt16(Buffer, 2); + quality_chainField = BitConverter.ToUInt16(Buffer, 4); + link_specialField = BitConverter.ToUInt16(Buffer, 6); // New ones byte1_hp = Buffer[offset1]; byte2_unk = Buffer[offset2]; diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/QuantityGameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/QuantityGameObject.cs index e041ea3..dc3d127 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/QuantityGameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/QuantityGameObject.cs @@ -13,15 +13,15 @@ public short Quantity { throw new Exception("Cannot have a Quantity Game Object with quantity > 512"); } - link_specialField = (short)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); + link_specialField = (ushort)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } } public QuantityGameObject(byte[] buffer, short idx) : base(buffer, idx) { } - public QuantityGameObject(short objid_flagsField, short positionField, - short quality_chainField, short link_specialField) : base(objid_flagsField, positionField, + public QuantityGameObject(ushort objid_flagsField, ushort positionField, + ushort quality_chainField, ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialLinkGameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialLinkGameObject.cs index c8496c4..8b937bb 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialLinkGameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialLinkGameObject.cs @@ -7,14 +7,14 @@ public class SpecialLinkGameObject : StaticObject public short SpecialIdx { get { return QuantityOrSpecialLinkOrSpecialProperty; } - set { link_specialField = (short)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } + set { link_specialField = (ushort)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } } public SpecialLinkGameObject(byte[] buffer, short idx) : base(buffer, idx) { } - public SpecialLinkGameObject(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public SpecialLinkGameObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialPropertyGameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialPropertyGameObject.cs index 41cc59a..18e4747 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialPropertyGameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/SpecialPropertyGameObject.cs @@ -18,14 +18,14 @@ public short SpecialLink { throw new Exception("Cannot have a SpecialLink with value < 512"); } - link_specialField = (short)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); + link_specialField = (ushort)Utils.SetBits(link_specialField, value, 0b1111111111, 6); UpdateBuffer(); } } public SpecialPropertyGameObject(byte[] buffer, short idx) : base(buffer, idx) { } - public SpecialPropertyGameObject(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public SpecialPropertyGameObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Doors.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Doors.cs index aaa8c9e..163f263 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Doors.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Doors.cs @@ -26,7 +26,7 @@ public void RemoveLock() /// is the index of the lock. /// /// Index of the lock object - public short HasLock() + public ushort HasLock() { if (link_specialField != 0) { @@ -40,7 +40,7 @@ public short HasLock() /// Replaces sp_link (link_specialField) with the value provided. Does not check if it really points to a lock object. /// /// - public void AddLock(short lock_idx) + public void AddLock(ushort lock_idx) { // TODO: add some checks link_specialField = lock_idx; diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedArmor.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedArmor.cs index f95306b..254425d 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedArmor.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedArmor.cs @@ -19,7 +19,7 @@ public int Spell public EnchantedArmor(byte[] buffer, short idx) : base(buffer, idx) { } - public EnchantedArmor(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public EnchantedArmor(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedObject.cs index c2de186..1fd43b2 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedObject.cs @@ -37,8 +37,8 @@ public int Spell public EnchantedObject(byte[] buffer, short idx) : base(buffer, idx) { } - public EnchantedObject(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public EnchantedObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedWand.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedWand.cs index 7810124..e621031 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedWand.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/EnchantedWand.cs @@ -17,8 +17,8 @@ public EnchantedWand(byte[] buffer, short idx) : base(buffer, idx) throw new NotImplementedException(); // TODO: Need to link to SpellObject } - public EnchantedWand(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public EnchantedWand(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { throw new NotImplementedException(); } diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Key.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Key.cs index 86abd59..a73997a 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Key.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Key.cs @@ -4,7 +4,7 @@ public class Key: StaticObject { public Key(byte[] buffer, short idxAtObjArray) : base(buffer, idxAtObjArray) { } - public Key(short objid_flagsField, short positionField, short quality_chainField, short link_specialField) + public Key(ushort objid_flagsField, ushort positionField, ushort quality_chainField, ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Lock.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Lock.cs index a5c7344..0a87215 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Lock.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Lock.cs @@ -8,7 +8,7 @@ public Lock(byte[] buffer, short idxAtObjArray) : base(buffer, idxAtObjArray) { } - public Lock(short objid_flagsField, short positionField, short quality_chainField, short link_specialField) + public Lock(ushort objid_flagsField, ushort positionField, ushort quality_chainField, ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } @@ -20,7 +20,7 @@ public Lock() : base() public bool IsLocked { get { return GetBits(objid_flagsField, 0b1, 9) == 1; } - set { objid_flagsField = (short) SetBits(objid_flagsField, value ? 1 : 0, 0b1, 9); } + set { objid_flagsField = (ushort) SetBits(objid_flagsField, value ? 1 : 0, 0b1, 9); } } public byte KeyID diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Weapon.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Weapon.cs index 7bb4c7c..18ef7a3 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Weapon.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/Specifics/Weapon.cs @@ -27,8 +27,8 @@ public int Spell public EnchantedWeapon(byte[] buffer, short idx) : base(buffer, idx) { } - public EnchantedWeapon(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public EnchantedWeapon(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } } \ No newline at end of file diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/StaticObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/StaticObject.cs index 96ba212..fe9d665 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/StaticObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/StaticObject.cs @@ -4,7 +4,7 @@ public class StaticObject: GameObject { public StaticObject(byte[] buffer, short idxAtObjArray) : base(buffer, idxAtObjArray) { } - public StaticObject(short objid_flagsField, short positionField, short quality_chainField, short link_specialField) + public StaticObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/TexturedGameObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/TexturedGameObject.cs index f7bbbd1..7722548 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/TexturedGameObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/TexturedGameObject.cs @@ -14,14 +14,14 @@ public class TexturedGameObject : StaticObject public int TextureNumber { get { return Utils.GetBits(objid_flagsField, 0b1111111, 9); } - set { objid_flagsField = (short)Utils.SetBits(objid_flagsField, value, 0b1111111, 9); } + set { objid_flagsField = (ushort)Utils.SetBits(objid_flagsField, value, 0b1111111, 9); } } public TexturedGameObject(byte[] buffer, short idx) : base(buffer, idx) { } - public TexturedGameObject(short objid_flagsField, short positionField, short quality_chainField, - short link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) + public TexturedGameObject(ushort objid_flagsField, ushort positionField, ushort quality_chainField, + ushort link_specialField) : base(objid_flagsField, positionField, quality_chainField, link_specialField) { } // public new void UpdateBuffer() diff --git a/UWRandomizerEditor/LEVDotARK/TileInfo.cs b/UWRandomizerEditor/LEVDotARK/TileInfo.cs index 55c587a..410326f 100644 --- a/UWRandomizerEditor/LEVDotARK/TileInfo.cs +++ b/UWRandomizerEditor/LEVDotARK/TileInfo.cs @@ -72,7 +72,7 @@ private set _tileBuffer = value; } } - public int EntryNum; + public int EntryNum { get; set; } // TODO: Test this public int Offset @@ -82,7 +82,7 @@ public int Offset return EntryNum * Size; } } - public int LevelNum; + public int LevelNum { get; set; } public int TileType { @@ -92,16 +92,12 @@ public int TileType public int TileHeight { - // get { return (Entry >> 4) & 0b1111; } - // set { Entry |= ((value & 0b1111) << 4); UpdateBuffer(); } get { return GetBits(Entry, 0b1111, 4); } set { Entry = SetBits(Entry, value, 0b1111, 4); UpdateBuffer(); } } public int Light { - // get { return (Entry >> 8) & 0b1; } - // set { Entry |= ((value & 0b1) << 8); UpdateBuffer(); } get { return GetBits(Entry, 0b1, 8); } set { Entry = SetBits(Entry, value, 0b1, 8); UpdateBuffer(); } } @@ -109,37 +105,27 @@ public int Light // todo: recheck this. public int Bit9 { - // get { return ((Entry >> 9) & 0b1); } - // set { Entry |= ((value & 0b1) << 9); UpdateBuffer(); } get { return GetBits(Entry, 0b1, 9); } set { Entry = SetBits(Entry, value, 0b1, 9); UpdateBuffer(); } } public int FloorTextureIdx { - // get { return (Entry >> 10) & 0b1111; } - // set { Entry |= ((value & 0b1111) << 10); UpdateBuffer(); } get { return GetBits(Entry, 0b1111, 10); } set { Entry = SetBits(Entry, value, 0b1111, 10); UpdateBuffer(); } } public int NoMagic { - // get { return (Entry >> 14) & 0b1; } - // set { Entry |= ((value & 0b1) << 14); UpdateBuffer(); } get { return GetBits(Entry, 0b1, 14); } set { Entry = SetBits(Entry, value, 0b1, 14); UpdateBuffer(); } } public int DoorBit { - // get { return (Entry >> 15) & 0b1; } - // set { Entry |= ((value & 0b1) << 15); UpdateBuffer(); } get { return GetBits(Entry, 0b1, 15); } set { Entry = SetBits(Entry, value, 0b1, 15); UpdateBuffer(); } } public int WallTextureIdx { - // get { return (Entry >> 16) & 0b111111; } - // set { Entry |= ((value & 0b111111) >> 16); UpdateBuffer(); } get { return GetBits(Entry, 0b111111, 16); } set { Entry = SetBits(Entry, value, 0b111111, 16); UpdateBuffer(); } } @@ -157,8 +143,8 @@ public int FirstObjIdx } } - public UWLinkedList ObjectChain; // Store - + public UWLinkedList ObjectChain { get; } + public int[] XYPos { From 60f5f0069bcae9403c430849355926004e00bf70 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:19:35 -0300 Subject: [PATCH 03/12] Removed duplicate code about getting item ID. --- .../LEVDotARK/GameObjects/GameObjectFactory.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs index f7fbbf8..79ef866 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/GameObjectFactory.cs @@ -6,16 +6,13 @@ namespace UWRandomizerEditor.LEVDotARK.GameObjects; public static class GameObjectFactory { - private static short getItemIDFromBuffer(byte[] buffer) - { - short objid_flagsField = BitConverter.ToInt16(buffer, 0); - // TODO: Duplicated, but oh well - return (short) GetBits(objid_flagsField, 0b111111111, 0); - } - + // TODO: I'll likely need to add a reference to "FreeListOfStatic/Mobile objects" public static GameObject CreateFromBuffer(byte[] buffer, short idxAtArray) { - short itemID = getItemIDFromBuffer(buffer); + var tempObject = new StaticObject(buffer[0..8], 2); + // Just to get the itemID. I'll use this later to separate StaticObjects into different classes + int itemID = tempObject.ItemID; + if (buffer.Length == MobileObject.TotalLength) { return new MobileObject(buffer, idxAtArray); From 173d94439fdd7cbece0b8322131b483a4550ce7f Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:20:05 -0300 Subject: [PATCH 04/12] Added test that compares hank's IDs with mine. --- .../TestCompareHankWithThis.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 RandomizerUnitTests/TestCompareHankWithThis.cs diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs new file mode 100644 index 0000000..69688b2 --- /dev/null +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using NUnit.Framework; +using UWRandomizerEditor; +using UWRandomizerEditor.LEVDotARK; +using UWRandomizerEditor.LEVDotARK.GameObjects; + +namespace RandomizerUnitTests; + +[TestFixture] +public class TestArkLoading +{ + [Test] + [Category("RequiresArk")] + public void TestItemIDsBlock0() + { + var path = + @"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\Block0_objects.json"; + // var json = JsonSerializer.Deserialize(File.ReadAllText(path), Dictionary); + var json = JsonSerializer.Deserialize>>(File.ReadAllText(path)); + + var ark = new ArkLoader(Settings.DefaultArkPath); + + // For whatever reason, hank's loader has objects [0-1024], but it should have been [0-1024[, right? krokot's goes + // goes up to 1023. + Assert.True(json.Count - 1 == ark.TileMapObjectsBlocks[0].AllGameObjects.Length); + + for (int i = 0; i < json.Count - 1; i++) + { + var correct = json[i]; + + if (i < 256) + { + var compare = ark.TileMapObjectsBlocks[0].MobileObjects[i]; + Assert.True(correct["item_id"] == compare.ItemID); + } + else + { + var compare = ark.TileMapObjectsBlocks[0].StaticObjects[i - 256]; + Assert.True(correct["item_id"] == compare.ItemID); + } + + } + + // for (int i = 0) + } + + [Test] + public void TestTileInfoComparingToUltimateEditor_manual() + { + var tile = new TileInfo(1609, new byte[] {0x11, 0x20, 0x1E, 0x00}, 6436, 0); + // Some water tile near that island with a lurker nearby + var reference = new TileInfo(1609, 0, 6436, 0); + reference.TileType = (int) TileInfo.TileTypes.open; + reference.TileHeight = 1; + reference.DoorBit = 0; + reference.NoMagic = 0; + reference.FloorTextureIdx = 8; + reference.WallTextureIdx = 30; + reference.FirstObjIdx = 0; + + + Assert.True(tile.Equals(reference)); + } + + // [Test] + // public void TestObjectFromUltimateEditor_manual() + // { + // // // A torch to the west of the tile above + // // var obj = new StaticObject(new byte[] {0x91, 0x80, 0x48, 0x34, 0x28, 0x00, 0x40, 0x00}, 540); + // // var reference = new StaticObject(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, 540); + // // reference.Xpos = 1; + // // reference.Ypos = 5; + // // reference.Zpos = 72; + // // reference.IsQuant = 1; + // // reference.Invis = 0; + // // reference.EnchantFlag = 0; + // // reference.Heading = 0; + // // reference.Flags = 0; + // // reference.Quality = 40; + // // reference.Owner_or_special = 0; + // // reference.next = 0; + // // reference.ItemID = 145; + // // reference.QuantityOrSpecialLinkOrSpecialProperty = 1; + // // reference.link_specialField = 64; + // // reference.UpdateBuffer(); + // // + // // Assert.True(obj.Equals(reference)); + // } +} \ No newline at end of file From 4d58be9babfec0c8873a673755b89aa48cb8b818 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:34:09 -0300 Subject: [PATCH 05/12] Added test that compare's hank's item_id with my ItemID. Still need to double-check the export though. block0 is working fine. --- RandomizerUnitTests/TestCompareHankWithThis.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs index 69688b2..977456c 100644 --- a/RandomizerUnitTests/TestCompareHankWithThis.cs +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -13,12 +13,12 @@ public class TestArkLoading { [Test] [Category("RequiresArk")] - public void TestItemIDsBlock0() + public void TestItemIDsBlocks([Range(0, 8, 1)]int blocknum) { var path = - @"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\Block0_objects.json"; + $@"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\Block{blocknum}_objects.json"; // var json = JsonSerializer.Deserialize(File.ReadAllText(path), Dictionary); - var json = JsonSerializer.Deserialize>>(File.ReadAllText(path)); + var json = JsonSerializer.Deserialize>>(File.ReadAllText(path), new JsonSerializerOptions() {AllowTrailingCommas = true}); var ark = new ArkLoader(Settings.DefaultArkPath); @@ -33,12 +33,14 @@ public void TestItemIDsBlock0() if (i < 256) { var compare = ark.TileMapObjectsBlocks[0].MobileObjects[i]; - Assert.True(correct["item_id"] == compare.ItemID); + var correctID = correct["item_id"]; + Assert.True(correctID == compare.ItemID, $"Mobile object {i}: Correct: {correctID}. Got {compare.ItemID}"); } else { var compare = ark.TileMapObjectsBlocks[0].StaticObjects[i - 256]; - Assert.True(correct["item_id"] == compare.ItemID); + var correctID = correct["item_id"]; + Assert.True(correctID == compare.ItemID, $"Static object {i}: Correct: {correctID}. Got {compare.ItemID}"); } } From 1fabd8f351e23a78826ecdcc3afb15ad810c774d Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sun, 13 Nov 2022 08:48:44 -0300 Subject: [PATCH 06/12] Forgot to de-hardcode the index. Now all ids are a-OK. --- RandomizerUnitTests/TestCompareHankWithThis.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs index 977456c..57426b6 100644 --- a/RandomizerUnitTests/TestCompareHankWithThis.cs +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -24,7 +24,7 @@ public void TestItemIDsBlocks([Range(0, 8, 1)]int blocknum) // For whatever reason, hank's loader has objects [0-1024], but it should have been [0-1024[, right? krokot's goes // goes up to 1023. - Assert.True(json.Count - 1 == ark.TileMapObjectsBlocks[0].AllGameObjects.Length); + Assert.True(json.Count - 1 == ark.TileMapObjectsBlocks[blocknum].AllGameObjects.Length); for (int i = 0; i < json.Count - 1; i++) { @@ -32,13 +32,13 @@ public void TestItemIDsBlocks([Range(0, 8, 1)]int blocknum) if (i < 256) { - var compare = ark.TileMapObjectsBlocks[0].MobileObjects[i]; + var compare = ark.TileMapObjectsBlocks[blocknum].MobileObjects[i]; var correctID = correct["item_id"]; Assert.True(correctID == compare.ItemID, $"Mobile object {i}: Correct: {correctID}. Got {compare.ItemID}"); } else { - var compare = ark.TileMapObjectsBlocks[0].StaticObjects[i - 256]; + var compare = ark.TileMapObjectsBlocks[blocknum].StaticObjects[i - 256]; var correctID = correct["item_id"]; Assert.True(correctID == compare.ItemID, $"Static object {i}: Correct: {correctID}. Got {compare.ItemID}"); } From 733056c773a65243e088386103a3a16fc0af6b85 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Sun, 13 Nov 2022 22:43:27 -0300 Subject: [PATCH 07/12] Embedding test data and trying to make it as generic as possible. --- .../RandomizerUnitTests.csproj | 57 ++++++++++++ .../TestCompareHankWithThis.cs | 91 ++++++++++++++++--- UWRandomizerEditor/Settings.cs | 4 +- 3 files changed, 139 insertions(+), 13 deletions(-) diff --git a/RandomizerUnitTests/RandomizerUnitTests.csproj b/RandomizerUnitTests/RandomizerUnitTests.csproj index 64d1d58..d06ce63 100644 --- a/RandomizerUnitTests/RandomizerUnitTests.csproj +++ b/RandomizerUnitTests/RandomizerUnitTests.csproj @@ -18,4 +18,61 @@ + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs index 57426b6..4ec95ba 100644 --- a/RandomizerUnitTests/TestCompareHankWithThis.cs +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Text.Json; using NUnit.Framework; using UWRandomizerEditor; @@ -9,19 +11,69 @@ namespace RandomizerUnitTests; [TestFixture] -public class TestArkLoading +public class TestGameObjectLists_Cleaned { - [Test] + private const int numOfLevels = 9; + private Stream[] streams = new Stream[numOfLevels]; + private List>> jsons = new List>>(numOfLevels); + + [SetUp] [Category("RequiresArk")] - public void TestItemIDsBlocks([Range(0, 8, 1)]int blocknum) + public void Setup() { - var path = - $@"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\Block{blocknum}_objects.json"; - // var json = JsonSerializer.Deserialize(File.ReadAllText(path), Dictionary); - var json = JsonSerializer.Deserialize>>(File.ReadAllText(path), new JsonSerializerOptions() {AllowTrailingCommas = true}); + + } + +} - var ark = new ArkLoader(Settings.DefaultArkPath); +[TestFixture] +public class TestGameObjectLists_Pristine +{ + private const int numOfLevels = 9; + private Stream[] streamsPristine = new Stream[numOfLevels]; + private List>> jsonsPristine = new List>>(numOfLevels); + private ArkLoader arkPristine; + + private Stream[] streamsCleaned = new Stream[numOfLevels]; + private List>> jsonsCleaned = new List>>(numOfLevels); + private ArkLoader arkCleaned; + [SetUp] + [Category("RequiresArk")] + public void Setup() + { + for (int blocknum = 0; blocknum < numOfLevels; blocknum++) + { + // Jesus this looks ugly. But it's only Loading the jsons into the lists, and the appropriate ArkLoader isntances + streamsPristine[blocknum] = + Assembly.GetExecutingAssembly() + .GetManifestResourceStream( + $"RandomizerUnitTests.testdata.PristineUW1.Block{blocknum}_objects.json") ?? + throw new InvalidOperationException(); + jsonsPristine.Add(JsonSerializer.Deserialize>>(streamsPristine[blocknum], + new JsonSerializerOptions() {AllowTrailingCommas = true}) ?? throw new InvalidOperationException()); + arkPristine = new ArkLoader(Settings.DefaultArkPath); + + streamsCleaned[blocknum] = + Assembly.GetExecutingAssembly() + .GetManifestResourceStream( + $"RandomizerUnitTests.testdata.CleanedUW1.Block{blocknum}_objects.json") ?? + throw new InvalidOperationException(); + jsonsCleaned.Add(JsonSerializer.Deserialize>>( + streamsCleaned[blocknum], + new JsonSerializerOptions() {AllowTrailingCommas = true}) ?? throw new InvalidOperationException()); + // TODO: De-hardcode this + arkCleaned = new ArkLoader(@"C:\Users\Karl\Desktop\UnderworldStudy\UW - Copy\DATA\LEV.ARK"); + } + } + + [Test] + [Category("RequiresArk")] + // Range is [from, to], not [from, to[ + public void TestGameObjectIDs([Range(0, numOfLevels - 1, 1)] int blocknum, [Values(true, false)] bool pristine) + { + var (ark, json) = selectArkAndJson(blocknum, pristine); + // For whatever reason, hank's loader has objects [0-1024], but it should have been [0-1024[, right? krokot's goes // goes up to 1023. Assert.True(json.Count - 1 == ark.TileMapObjectsBlocks[blocknum].AllGameObjects.Length); @@ -44,10 +96,27 @@ public void TestItemIDsBlocks([Range(0, 8, 1)]int blocknum) } } + } + + private Tuple>> selectArkAndJson(int blocknum, bool pristine) + { + ArkLoader ark; + List> json; + if (pristine) + { + json = jsonsPristine[blocknum]; + ark = arkPristine; + } + else + { + json = jsonsCleaned[blocknum]; + ark = arkCleaned; + } - // for (int i = 0) + return new Tuple>>(ark, json); } - + + [Test] public void TestTileInfoComparingToUltimateEditor_manual() { diff --git a/UWRandomizerEditor/Settings.cs b/UWRandomizerEditor/Settings.cs index a4ef822..60a5547 100644 --- a/UWRandomizerEditor/Settings.cs +++ b/UWRandomizerEditor/Settings.cs @@ -7,8 +7,8 @@ namespace UWRandomizerEditor; public static class Settings { - public static readonly string DefaultArkPath = "D:\\Dropbox\\UnderworldStudy\\studies\\LEV.ARK"; - public static readonly string DefaultBinaryTestsPath = "D:\\Dropbox\\UnderworldStudy\\studies\\tests"; + public static readonly string DefaultArkPath = @"C:\Users\Karl\Desktop\UnderworldStudy\UW\DATA\LEV.ARK"; + public static readonly string DefaultBinaryTestsPath = @"C:\Users\Karl\Desktop\UnderworldStudy\Buffers"; static Settings() { From 5a818c3a4ee98456ac237213d848ba6e7328b814 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Mon, 14 Nov 2022 13:12:51 -0300 Subject: [PATCH 08/12] Added tests that check almost every property of Static Objects. --- .../TestCompareHankWithThis.cs | 138 ++++++++++-------- 1 file changed, 80 insertions(+), 58 deletions(-) diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs index 4ec95ba..53f3c4b 100644 --- a/RandomizerUnitTests/TestCompareHankWithThis.cs +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using System.Text.Json; using NUnit.Framework; @@ -11,34 +12,42 @@ namespace RandomizerUnitTests; [TestFixture] -public class TestGameObjectLists_Cleaned -{ - private const int numOfLevels = 9; - private Stream[] streams = new Stream[numOfLevels]; - private List>> jsons = new List>>(numOfLevels); - - [SetUp] - [Category("RequiresArk")] - public void Setup() - { - - } - -} - -[TestFixture] -public class TestGameObjectLists_Pristine +public class TestGameObjectProperties { private const int numOfLevels = 9; private Stream[] streamsPristine = new Stream[numOfLevels]; private List>> jsonsPristine = new List>>(numOfLevels); private ArkLoader arkPristine; - + private Stream[] streamsCleaned = new Stream[numOfLevels]; private List>> jsonsCleaned = new List>>(numOfLevels); private ArkLoader arkCleaned; - [SetUp] + public enum PossibleLevArkToTest + { + pristine = 0, + cleaned = 1 + } + + private static readonly Dictionary json_to_UWR = new Dictionary() + { + {"item_id", "ItemID"}, + {"flags", "Flags"}, + {"enchantment", "EnchantFlag"}, + {"doordir", "Doordir"}, + {"invis", "Invis"}, + {"is_quant", "IsQuant"}, + {"zpos", "Zpos"}, + {"heading", "Heading"}, + {"xpos", "Xpos"}, + {"ypos", "Ypos"}, + {"quality", "Quality"}, + {"next", "next"}, + {"owner", "Owner_or_special"}, + {"link", "QuantityOrSpecialLinkOrSpecialProperty"} + }; + + [OneTimeSetUp] [Category("RequiresArk")] public void Setup() { @@ -66,43 +75,79 @@ public void Setup() arkCleaned = new ArkLoader(@"C:\Users\Karl\Desktop\UnderworldStudy\UW - Copy\DATA\LEV.ARK"); } } - + + [Test] [Category("RequiresArk")] - // Range is [from, to], not [from, to[ - public void TestGameObjectIDs([Range(0, numOfLevels - 1, 1)] int blocknum, [Values(true, false)] bool pristine) + public void TestStaticObjectProperties( + [Range(0, numOfLevels - 1, 1)] int blocknum, // Reminder: Range is [from, to], not [from, to[ + [Values(PossibleLevArkToTest.pristine, PossibleLevArkToTest.cleaned)] + PossibleLevArkToTest pristine, + [Values("item_id", "flags", "enchantment", "doordir", "invis", "is_quant", "zpos", "heading", "ypos", "xpos", + "quality", "next", "owner", "link")] + string key + ) { var (ark, json) = selectArkAndJson(blocknum, pristine); - + // For whatever reason, hank's loader has objects [0-1024], but it should have been [0-1024[, right? krokot's goes // goes up to 1023. Assert.True(json.Count - 1 == ark.TileMapObjectsBlocks[blocknum].AllGameObjects.Length); + IterateAndCompareAttributesStaticObject(json, key, ark, json_to_UWR[key], blocknum); + } + + private void IterateAndCompareAttributesStaticObject(List> json, string correctLabel, + ArkLoader ark, string compareLabel, int blocknum) + { for (int i = 0; i < json.Count - 1; i++) { var correct = json[i]; - + if (i < 256) { var compare = ark.TileMapObjectsBlocks[blocknum].MobileObjects[i]; - var correctID = correct["item_id"]; - Assert.True(correctID == compare.ItemID, $"Mobile object {i}: Correct: {correctID}. Got {compare.ItemID}"); + var correctProperty = correct[correctLabel]; + var compareProperty = GetPropertyValue(compare, compareLabel); + Assert.True(correctProperty == compareProperty, + $"Mobile object {i}: Correct: {correctProperty}. Got {compareProperty}"); } else { var compare = ark.TileMapObjectsBlocks[blocknum].StaticObjects[i - 256]; - var correctID = correct["item_id"]; - Assert.True(correctID == compare.ItemID, $"Static object {i}: Correct: {correctID}. Got {compare.ItemID}"); + var correctProperty = correct[correctLabel]; + var compareProperty = GetPropertyValue(compare, compareLabel); + Assert.True(correctProperty == compareProperty, + $"Static object {i}: Correct: {correctProperty}. Got {compareProperty}"); } - } } - private Tuple>> selectArkAndJson(int blocknum, bool pristine) + + /// + /// This is used to get a property from StaticObject or Mobile object, which are typically bytes, shorts, ints, + /// and convert them into ints. + /// + /// + /// + /// + private static int GetPropertyValue(object obj, string propname) + { + return Convert.ToInt32(obj.GetType().GetProperty(propname).GetValue(obj, null)); + } + + /// + /// This selects if I'm using a "Pristine" UW1 (from GOG copy) or a "Cleaned" UW1 (from Ultimate Editor) + /// + /// + /// + /// + private Tuple>> selectArkAndJson(int blocknum, + PossibleLevArkToTest pristine) { ArkLoader ark; List> json; - if (pristine) + if (pristine == PossibleLevArkToTest.pristine) { json = jsonsPristine[blocknum]; ark = arkPristine; @@ -115,8 +160,10 @@ private Tuple>> selectArkAndJson(int blo return new Tuple>>(ark, json); } +} - +public class ManualTests +{ [Test] public void TestTileInfoComparingToUltimateEditor_manual() { @@ -130,33 +177,8 @@ public void TestTileInfoComparingToUltimateEditor_manual() reference.FloorTextureIdx = 8; reference.WallTextureIdx = 30; reference.FirstObjIdx = 0; - + Assert.True(tile.Equals(reference)); } - - // [Test] - // public void TestObjectFromUltimateEditor_manual() - // { - // // // A torch to the west of the tile above - // // var obj = new StaticObject(new byte[] {0x91, 0x80, 0x48, 0x34, 0x28, 0x00, 0x40, 0x00}, 540); - // // var reference = new StaticObject(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, 540); - // // reference.Xpos = 1; - // // reference.Ypos = 5; - // // reference.Zpos = 72; - // // reference.IsQuant = 1; - // // reference.Invis = 0; - // // reference.EnchantFlag = 0; - // // reference.Heading = 0; - // // reference.Flags = 0; - // // reference.Quality = 40; - // // reference.Owner_or_special = 0; - // // reference.next = 0; - // // reference.ItemID = 145; - // // reference.QuantityOrSpecialLinkOrSpecialProperty = 1; - // // reference.link_specialField = 64; - // // reference.UpdateBuffer(); - // // - // // Assert.True(obj.Equals(reference)); - // } } \ No newline at end of file From 2d03e3467bdb2697318dd5ca57638839c07f9190 Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Mon, 14 Nov 2022 13:13:36 -0300 Subject: [PATCH 09/12] Modified MobileObject to fill in its base class buffer with the simplified buffer. --- UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs index 719b43f..99d6572 100644 --- a/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs +++ b/UWRandomizerEditor/LEVDotARK/GameObjects/MobileObject.cs @@ -172,11 +172,11 @@ public int whoami byte_NPCwhoami = Buffer[offset15]; } - // todo: don't forget to check if these calls to virtual functions will mess stuff up. public MobileObject(byte[] buffer, short idx) { // Debug.Assert(buffer.Length == TotalLength); this.Buffer = buffer; + base.Buffer = buffer[..8]; // In case this is cast as a GameObject, it'll preserve the base buffer this.IdxAtObjectArray = idx; UpdateEntries(); } @@ -186,6 +186,7 @@ public MobileObject(byte[] baseBuffer, byte byte1_hp, byte unk2, byte unk3, shor byte unk7, byte unk8, short NPChome, byte heading, byte hunger, byte whoami, short idx) { baseBuffer.CopyTo(Buffer, 0); + base.Buffer = baseBuffer; byte[] extra = new byte[ExtraLength] { byte1_hp, @@ -221,6 +222,8 @@ public MobileObject(short short1, short short2, short short3, short short4, byte BitConverter.GetBytes(short2).CopyTo(baseBuffer, 2*1); BitConverter.GetBytes(short3).CopyTo(baseBuffer, 2*2); BitConverter.GetBytes(short4).CopyTo(baseBuffer, 2*3); + base.Buffer = baseBuffer; + byte[] extra = new byte[ExtraLength] { byte1_hp, From 44c331b3ef9e834d94be0aa2aefb573ef4a24eaa Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Mon, 14 Nov 2022 16:51:16 -0300 Subject: [PATCH 10/12] Added some studies on Free Lists --- ExtractingBuffersOfEverything/Program.cs | 66 +++++++++++++++--------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/ExtractingBuffersOfEverything/Program.cs b/ExtractingBuffersOfEverything/Program.cs index 758b402..14fa0de 100644 --- a/ExtractingBuffersOfEverything/Program.cs +++ b/ExtractingBuffersOfEverything/Program.cs @@ -50,14 +50,6 @@ public static void Main() $"FreeListStaticObject{counter_block}_fullbuffer.bin"); var counter_objects = 0; - // GameObjects - // foreach (var gameObject in block.AllGameObjects) - // { - // gameObject.SaveBuffer(nthTileMapBlockPath, - // $"GameObjectIdx{gameObject.IdxAtObjectArray}_ctr{counter_objects}_id{gameObject.ItemID}.bin"); - // counter_objects++; - // } - // Save Mobile Object buffers counter_objects = 0; foreach (var mobileObject in block.MobileObjects) @@ -75,23 +67,51 @@ public static void Main() $"StaticObjectIdx{staticObject.IdxAtObjectArray}_ctr{counter_objects}.bin"); counter_objects++; } - - // Save free list Mobile objects buffers - counter_objects = 0; - foreach (var mobileFreeObject in block.FreeListMobileObject) - { - StdSaveBuffer(mobileFreeObject.Buffer, nthTileMapBlockPath, - $"mobileFreeObjectIdx{mobileFreeObject.EntryNum}_ctr{counter_objects}.bin"); - counter_objects++; - } - // Save free list Static objects buffers - foreach (var staticFreeObject in block.FreeListStaticObject) + + using (StreamWriter sw = new StreamWriter(Path.Join(tilemapBlocksPath, + $"FreeListObjectDescription_block{counter_block}.txt"))) { - StdSaveBuffer(staticFreeObject.Buffer, nthTileMapBlockPath, - $"staticFreeObjectIdx{staticFreeObject.EntryNum}_ctr{counter_objects}.bin"); - counter_objects++; + var setMobile = new HashSet(); // To get which values are referenced in the end + int MobileDuplicateCounter = 0; + // Save free list Mobile objects buffers + counter_objects = 0; + foreach (var mobileFreeObject in block.FreeListMobileObject) + { + sw.WriteLine($"Mobile Free Object entry {counter_objects} has value {mobileFreeObject.Entry}"); + StdSaveBuffer(mobileFreeObject.Buffer, nthTileMapBlockPath, + $"mobileFreeObjectIdx{mobileFreeObject.EntryNum}_ctr{counter_objects}.bin"); + counter_objects++; + MobileDuplicateCounter += setMobile.Add(mobileFreeObject.Entry) ? 0 : 1; // Reminder: Add returns false if element is already present + } + + var setStatic = new HashSet(); + int StaticDuplicateCounter = 0; + // Save free list Static objects buffers + foreach (var staticFreeObject in block.FreeListStaticObject) + { + sw.WriteLine($"Static Free Object entry {counter_objects} has value {staticFreeObject.Entry}"); + StdSaveBuffer(staticFreeObject.Buffer, nthTileMapBlockPath, + $"staticFreeObjectIdx{staticFreeObject.EntryNum}_ctr{counter_objects}.bin"); + counter_objects++; + StaticDuplicateCounter += setStatic.Add(staticFreeObject.Entry) ? 0 : 1; // Reminder: Add returns false if element is already present + } + + sw.WriteLine($"Summary: Mobile list contains {block.FreeListMobileObject.Length} entries of which" + + $" {MobileDuplicateCounter} are duplicates." + + $" Indexes present in Mobile List: {string.Join(",", setMobile.OrderBy(x => x))}." + ); + var allMobileIdxs = Enumerable.Range(0, 255).ToHashSet(); + allMobileIdxs.ExceptWith(setMobile); + sw.WriteLine($"Indexes not present: {string.Join(",", allMobileIdxs)}"); + + sw.WriteLine($"Summary: Static list contains {block.FreeListStaticObject.Length} entries of which" + + $" {StaticDuplicateCounter} are duplicates." + + $" Indexes present in Mobile List: {string.Join(",", setStatic.OrderBy(x => x))}"); + var allStaticIdxs = Enumerable.Range(256, 1024 - 256).ToHashSet(); + allStaticIdxs.ExceptWith(setStatic); + sw.WriteLine($"Indexes not present: {string.Join(",", allStaticIdxs)}"); } - + // Iterate through tiles counter_objects = 0; foreach (var tile in block.TileInfos) From fb7491335ea7bc567cd80cd094e9de6b9a4ef78a Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:20:52 -0300 Subject: [PATCH 11/12] Finished up adding exports for other blocks from lev.ark --- ExtractingBuffersOfEverything/Program.cs | 94 ++++++++++++++++++++---- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/ExtractingBuffersOfEverything/Program.cs b/ExtractingBuffersOfEverything/Program.cs index 14fa0de..f4323c5 100644 --- a/ExtractingBuffersOfEverything/Program.cs +++ b/ExtractingBuffersOfEverything/Program.cs @@ -1,35 +1,39 @@ // See https://aka.ms/new-console-template for more information +using System.Net.Mime; using UWRandomizerEditor; using UWRandomizerEditor.LEVDotARK; using static UWRandomizerEditor.Utils; namespace ExtractingEverything; -public static class Program { +public static class Program +{ public static void Main() { var path = @"C:\Users\Karl\Desktop\UnderworldStudy\UW\DATA\LEV.ARK"; var baseBufferPath = @"C:\Users\Karl\Desktop\UnderworldStudy\Buffers"; Directory.CreateDirectory(baseBufferPath); - + var Ark = new ArkLoader(path); - + // Header Ark.header.SaveBuffer(baseBufferPath, "header.bin"); - + // Blocks int counter_block = 0; var blockPath = Path.Join(baseBufferPath, "Blocks"); Directory.CreateDirectory(blockPath); foreach (var block in Ark.blocks) { - block.SaveBuffer(blockPath, $"Block{counter_block}_level{block.LevelNumber}_length{block.TotalBlockLength}.bin"); + block.SaveBuffer(blockPath, + $"Block{counter_block}_level{block.LevelNumber}_length{block.TotalBlockLength}.bin"); counter_block++; } - - // Tilemap Blocks + + #region TilemapBlocks + counter_block = 0; var tilemapBlocksPath = Path.Join(baseBufferPath, "TileMaps"); Directory.CreateDirectory(tilemapBlocksPath); @@ -37,7 +41,7 @@ public static void Main() { var nthTileMapBlockPath = Path.Join(tilemapBlocksPath, $"TileMapBlock{counter_block}"); Directory.CreateDirectory(nthTileMapBlockPath); - + block.SaveBuffer(nthTileMapBlockPath, $"TileMapBlock{counter_block}_fullbuffer.bin"); StdSaveBuffer(block.TileMapBuffer, nthTileMapBlockPath, $"TileMapBuffer{counter_block}_fullbuffer.bin"); StdSaveBuffer(block.MobileObjectInfoBuffer, nthTileMapBlockPath, @@ -48,7 +52,7 @@ public static void Main() $"FreeListMobileObject{counter_block}_fullbuffer.bin"); StdSaveBuffer(block.FreeListStaticObjectBuffer, nthTileMapBlockPath, $"FreeListStaticObject{counter_block}_fullbuffer.bin"); - + var counter_objects = 0; // Save Mobile Object buffers counter_objects = 0; @@ -58,7 +62,7 @@ public static void Main() $"MobileObjectIdx{mobileObject.IdxAtObjectArray}_ctr{counter_objects}.bin"); counter_objects++; } - + // Save static Object buffers // Doesn't reset to 0. foreach (var staticObject in block.StaticObjects) @@ -81,7 +85,10 @@ public static void Main() StdSaveBuffer(mobileFreeObject.Buffer, nthTileMapBlockPath, $"mobileFreeObjectIdx{mobileFreeObject.EntryNum}_ctr{counter_objects}.bin"); counter_objects++; - MobileDuplicateCounter += setMobile.Add(mobileFreeObject.Entry) ? 0 : 1; // Reminder: Add returns false if element is already present + MobileDuplicateCounter += + setMobile.Add(mobileFreeObject.Entry) + ? 0 + : 1; // Reminder: Add returns false if element is already present } var setStatic = new HashSet(); @@ -93,7 +100,10 @@ public static void Main() StdSaveBuffer(staticFreeObject.Buffer, nthTileMapBlockPath, $"staticFreeObjectIdx{staticFreeObject.EntryNum}_ctr{counter_objects}.bin"); counter_objects++; - StaticDuplicateCounter += setStatic.Add(staticFreeObject.Entry) ? 0 : 1; // Reminder: Add returns false if element is already present + StaticDuplicateCounter += + setStatic.Add(staticFreeObject.Entry) + ? 0 + : 1; // Reminder: Add returns false if element is already present } sw.WriteLine($"Summary: Mobile list contains {block.FreeListMobileObject.Length} entries of which" + @@ -103,7 +113,7 @@ public static void Main() var allMobileIdxs = Enumerable.Range(0, 255).ToHashSet(); allMobileIdxs.ExceptWith(setMobile); sw.WriteLine($"Indexes not present: {string.Join(",", allMobileIdxs)}"); - + sw.WriteLine($"Summary: Static list contains {block.FreeListStaticObject.Length} entries of which" + $" {StaticDuplicateCounter} are duplicates." + $" Indexes present in Mobile List: {string.Join(",", setStatic.OrderBy(x => x))}"); @@ -116,10 +126,66 @@ public static void Main() counter_objects = 0; foreach (var tile in block.TileInfos) { - tile.SaveBuffer(nthTileMapBlockPath, $"TileIdx{counter_objects}Offset{tile.Offset},X{tile.XYPos[0]}Y{tile.XYPos[1]}.bin"); + tile.SaveBuffer(nthTileMapBlockPath, + $"TileIdx{counter_objects}Offset{tile.Offset},X{tile.XYPos[0]}Y{tile.XYPos[1]}.bin"); counter_objects++; } + + counter_block++; + + } + #endregion + + #region TextureMappingBlock + + counter_block = 0; + var TextureMappingBlocksPath = Path.Join(baseBufferPath, "TextureMappingBlock"); + Directory.CreateDirectory(TextureMappingBlocksPath); + foreach (var textMapBlock in Ark.TextMapBlocks) + { + textMapBlock.SaveBuffer(TextureMappingBlocksPath, $"fullbuffer_{counter_block}.bin"); counter_block++; } + + #endregion + + #region ObjectAnimationOverlayMap + + counter_block = 0; + var ObjectAnimationOverlayMapPath = Path.Join(baseBufferPath, "ObjectAnimationOverlayBlock"); + Directory.CreateDirectory(ObjectAnimationOverlayMapPath); + foreach (var objAnimBlock in Ark.ObjAnimBlocks) + { + objAnimBlock.SaveBuffer(ObjectAnimationOverlayMapPath, $"fullbuffer_{counter_block}.bin"); + counter_block++; + } + + #endregion + + #region MapNotesBlock + + counter_block = 0; + var MapNotesBlockPath = Path.Join(baseBufferPath, "MapNotesBlock"); + Directory.CreateDirectory(MapNotesBlockPath); + foreach (var mapNotesBlock in Ark.MapNotesBlocks) + { + mapNotesBlock.SaveBuffer(MapNotesBlockPath, $"fullbuffer_{counter_block}.bin"); + counter_block++; + } + + #endregion + + #region AutomapInfosBlock + + counter_block = 0; + var AutomapInfosBlockPath = Path.Join(baseBufferPath, "AutomapInfosBlock"); + Directory.CreateDirectory(AutomapInfosBlockPath); + foreach (var automapInfosBlock in Ark.AutomapBlocks) + { + automapInfosBlock.SaveBuffer(AutomapInfosBlockPath, $"fullbuffer_{counter_block}.bin"); + counter_block++; + } + + #endregion } } \ No newline at end of file From 27071dd9f62f80ea5f427538e53bbe19481560bc Mon Sep 17 00:00:00 2001 From: Karl Clinckspoor <30571394+KarlClinckspoor@users.noreply.github.com> Date: Mon, 14 Nov 2022 20:55:13 -0300 Subject: [PATCH 12/12] Removed EmbeddedResource for json files, should be accepted by Github actions. --- .../RandomizerUnitTests.csproj | 57 ------------------- .../TestCompareHankWithThis.cs | 31 ++++++---- 2 files changed, 20 insertions(+), 68 deletions(-) diff --git a/RandomizerUnitTests/RandomizerUnitTests.csproj b/RandomizerUnitTests/RandomizerUnitTests.csproj index d06ce63..64d1d58 100644 --- a/RandomizerUnitTests/RandomizerUnitTests.csproj +++ b/RandomizerUnitTests/RandomizerUnitTests.csproj @@ -18,61 +18,4 @@ - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/RandomizerUnitTests/TestCompareHankWithThis.cs b/RandomizerUnitTests/TestCompareHankWithThis.cs index 53f3c4b..0896002 100644 --- a/RandomizerUnitTests/TestCompareHankWithThis.cs +++ b/RandomizerUnitTests/TestCompareHankWithThis.cs @@ -15,11 +15,15 @@ namespace RandomizerUnitTests; public class TestGameObjectProperties { private const int numOfLevels = 9; - private Stream[] streamsPristine = new Stream[numOfLevels]; + // Removing this to temporarily avoid problems with building in github actions. Keeping the same for now. + // TODO: Can I put the .json test files without problems? + // private Stream[] streamsPristine = new Stream[numOfLevels]; + private String[] streamsPristine = new String[numOfLevels]; private List>> jsonsPristine = new List>>(numOfLevels); private ArkLoader arkPristine; - private Stream[] streamsCleaned = new Stream[numOfLevels]; + // private Stream[] streamsCleaned = new Stream[numOfLevels]; + private String[] streamsCleaned = new String[numOfLevels]; private List>> jsonsCleaned = new List>>(numOfLevels); private ArkLoader arkCleaned; @@ -54,20 +58,25 @@ public void Setup() for (int blocknum = 0; blocknum < numOfLevels; blocknum++) { // Jesus this looks ugly. But it's only Loading the jsons into the lists, and the appropriate ArkLoader isntances + // streamsPristine[blocknum] = + // Assembly.GetExecutingAssembly() + // .GetManifestResourceStream( + // $"RandomizerUnitTests.testdata.PristineUW1.Block{blocknum}_objects.json") ?? + // throw new InvalidOperationException(); streamsPristine[blocknum] = - Assembly.GetExecutingAssembly() - .GetManifestResourceStream( - $"RandomizerUnitTests.testdata.PristineUW1.Block{blocknum}_objects.json") ?? - throw new InvalidOperationException(); + File.ReadAllText( + @$"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\PristineUW1\Block{blocknum}_objects.json"); jsonsPristine.Add(JsonSerializer.Deserialize>>(streamsPristine[blocknum], new JsonSerializerOptions() {AllowTrailingCommas = true}) ?? throw new InvalidOperationException()); arkPristine = new ArkLoader(Settings.DefaultArkPath); - streamsCleaned[blocknum] = - Assembly.GetExecutingAssembly() - .GetManifestResourceStream( - $"RandomizerUnitTests.testdata.CleanedUW1.Block{blocknum}_objects.json") ?? - throw new InvalidOperationException(); + // streamsCleaned[blocknum] = + // Assembly.GetExecutingAssembly() + // .GetManifestResourceStream( + // $"RandomizerUnitTests.testdata.CleanedUW1.Block{blocknum}_objects.json") ?? + // throw new InvalidOperationException(); + streamsCleaned[blocknum] = File.ReadAllText( + @$"C:\Users\Karl\Desktop\UnderworldStudy\UnderworldRandomizer\RandomizerUnitTests\testdata\CleanedUW1\Block{blocknum}_objects.json"); jsonsCleaned.Add(JsonSerializer.Deserialize>>( streamsCleaned[blocknum], new JsonSerializerOptions() {AllowTrailingCommas = true}) ?? throw new InvalidOperationException());