From 6d192673508190bad34ac689ed01c0041204e031 Mon Sep 17 00:00:00 2001 From: MattFiler Date: Sat, 17 Feb 2024 13:51:56 +0000 Subject: [PATCH 01/72] more memory paranoia --- CathodeLib/Scripts/CATHODE/PAK2.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/PAK2.cs b/CathodeLib/Scripts/CATHODE/PAK2.cs index 27a1a6f..61a1b60 100644 --- a/CathodeLib/Scripts/CATHODE/PAK2.cs +++ b/CathodeLib/Scripts/CATHODE/PAK2.cs @@ -12,6 +12,11 @@ public class PAK2 : CathodeFile public static new Implementation Implementation = Implementation.CREATE | Implementation.LOAD | Implementation.SAVE; public PAK2(string path) : base(path) { } + ~PAK2() + { + Entries.Clear(); + } + #region FILE_IO override protected bool LoadInternal() { @@ -85,6 +90,11 @@ override protected bool SaveInternal() #region STRUCTURES public class File { + ~File() + { + Content = null; + } + public string Filename = ""; public byte[] Content; } From a404a88ef07832bb8c3dd6f93f6d6c2d94f0bdb3 Mon Sep 17 00:00:00 2001 From: MattFiler Date: Sat, 17 Feb 2024 14:55:29 +0000 Subject: [PATCH 02/72] ditto --- CathodeLib/Scripts/CATHODE/Movers.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index ada7240..b19c9b9 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -23,6 +23,12 @@ public Movers(string path) : base(path) { } private List _writeList = new List(); + ~Movers() + { + Entries.Clear(); + _writeList.Clear(); + } + #region FILE_IO override protected bool LoadInternal() { @@ -224,6 +230,13 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public UInt32 Unknowns70_; public UInt32 Unknowns71_; //320 + + ~MOVER_DESCRIPTOR() + { + gpuConstants = null; + renderConstants = null; + entity = null; + } }; [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -265,6 +278,11 @@ public class GPU_CONSTANTS //As best I can tell, this is 80 bytes long public float UnknownValue3_; public float UnknownValue4_; //144 + + ~GPU_CONSTANTS() + { + blankSpace1 = null; + } } [StructLayout(LayoutKind.Sequential, Pack = 1)] @@ -292,6 +310,13 @@ used in [MarshalAs(UnmanagedType.ByValArray, SizeConst = 36)] public byte[] blankSpace3; //244 + + ~RENDER_CONSTANTS() + { + Unknowns2_ = null; + UnknownMinMax_ = null; + blankSpace3 = null; + } } #endregion } From 084abda3c4f346bd3e46dc70c01f4e483c4e8277 Mon Sep 17 00:00:00 2001 From: MattFiler Date: Sat, 17 Feb 2024 18:01:39 +0000 Subject: [PATCH 03/72] turns out we can ignore most of collision.map --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 33 +++++++-------------- CathodeLib/Scripts/CATHODE/Movers.cs | 2 +- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index c18ba0b..4df72aa 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -23,19 +23,19 @@ override protected bool LoadInternal() { //It seems typically in this file at the start there are a bunch of empty entries, and then there are a bunch of unresolvable ones, and then a bunch that can be resolved. + //first 18 are always null? + //always first 247 are the same? 18 null and the rest in required assets? + reader.BaseStream.Position = 4; int entryCount = reader.ReadInt32(); for (int i = 0; i < entryCount; i++) { Entry entry = new Entry(); - entry.unk0 = reader.ReadInt32(); //flag? - entry.Unknown1_ = reader.ReadInt32(); //some sort of index ? + reader.BaseStream.Position += 8; entry.ID = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); - entry.Unknown2_ = reader.ReadInt32(); //Is sometimes -1 and other times a small positive integer. Is this tree node parent? - entry.CollisionHKXEntryIndex = reader.ReadInt16(); - entry.Unknown3_ = reader.ReadInt16(); //Most of the time it is -1. - entry.MVRZoneIDThing = reader.ReadInt32(); + reader.BaseStream.Position += 8; + entry.zoneID = reader.ReadInt32(); reader.BaseStream.Position += 16; Entries.Add(entry); } @@ -52,12 +52,11 @@ override protected bool SaveInternal() writer.Write(Entries.Count); for (int i = 0; i < Entries.Count; i++) { - writer.Write(Entries[i].Unknown1_); + writer.Write(new byte[8]); Utilities.Write(writer, Entries[i].ID); Utilities.Write(writer, Entries[i].entity); - writer.Write(Entries[i].CollisionHKXEntryIndex); - writer.Write(Entries[i].Unknown3_); - writer.Write(Entries[i].MVRZoneIDThing); + writer.Write(new byte[8]); + writer.Write(Entries[i].zoneID); writer.Write(new byte[16]); } } @@ -68,19 +67,9 @@ override protected bool SaveInternal() #region STRUCTURES public class Entry { - public int unk0 = 0; //flags? - public int Unknown1_ = -1; // Is this tree node id? - - public ShortGuid ID = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid, as a result, we can't resolve a lot of them. Does the game care about the value? I doubt it. We definitely don't. - + public ShortGuid ID = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid public CommandsEntityReference entity = new CommandsEntityReference(); - - public int Unknown2_= -1; // NOTE: Is sometimes -1 and other times a small positive integer. Is this tree node parent? - - public Int16 CollisionHKXEntryIndex = -1; // NOTE: Most of the time is a positive integer, sometimes -1. - - public Int16 Unknown3_ = -1; // NOTE: Most of the time it is -1. - public int MVRZoneIDThing = 0; // NOTE: This is CollisionMapThingIDs[0] from alien_mvr_entry + public int zoneID = 0; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering }; #endregion } diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index b19c9b9..c3abd23 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -219,7 +219,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public float emissive_val2; //emissive surface val2 public float emissive_val3; //emissive surface val3 //296 - public ShortGuid zoneID; //zone id? RenderableScene::create_instance, RenderableScene::initialize + public ShortGuid zoneID; //zone id? RenderableScene::create_instance, RenderableScene::initialize - note in Collision.MAP we have this val too and it is defo zones public ShortGuid zoneActivator; //zone activator? RenderableScene::create_instance, RenderableScene::initialize //304 public UInt32 Unknowns61_; //uVar3 in reserve_light_light_master_sets, val of LightMasterSet, or an incrementer From 5129e96d5fd3460b37ced85db72827ed58c6582b Mon Sep 17 00:00:00 2001 From: MattFiler Date: Sat, 17 Feb 2024 18:36:11 +0000 Subject: [PATCH 04/72] committing comments --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 2 ++ CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 4df72aa..c68395a 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -26,6 +26,8 @@ override protected bool LoadInternal() //first 18 are always null? //always first 247 are the same? 18 null and the rest in required assets? + //note: some of the things we skip here actually contain useful info, but the game doesn't read it so there's no point us bothering with it + reader.BaseStream.Position = 4; int entryCount = reader.ReadInt32(); for (int i = 0; i < entryCount; i++) diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index d193378..38d489b 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -22,6 +22,9 @@ public class PhysicsMaps : CathodeFile public static new Implementation Implementation = Implementation.CREATE | Implementation.LOAD | Implementation.SAVE; public PhysicsMaps(string path) : base(path) { } + //NOTE: clearing out this file does not cause a crash, and it does not break physics objects like boxes + // ... it does however break doors... + #region FILE_IO override protected bool LoadInternal() { @@ -88,9 +91,10 @@ public class Entry //This is the entity ID and instance ID for the actual instanced composite entity (basically, a step down from the instance above). public CommandsEntityReference entity; - public Vector4 Row0; // NOTE: This is a 3x4 matrix, seems to have rotation data on the leftmost 3x3 matrix, and position - public Vector4 Row1; // on the rightmost 3x1 matrix. - public Vector4 Row2; + public Vector4 Row0; //mattf: setting to zero breaks stuff // NOTE: This is a 3x4 matrix, seems to have rotation data on the leftmost 3x3 matrix, and position + public Vector4 Row1; //mattf: setting to zero breaks stuff // on the rightmost 3x1 matrix. + + public Vector4 Row2; //mattf: setting to zero doesn't seem to do nothing: unused? }; #endregion } From ab00438e8742074b3cd8c80c63b98775f261a682 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 24 Feb 2024 15:30:59 +0000 Subject: [PATCH 05/72] various resource investigations --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 12 +++++----- CathodeLib/Scripts/CATHODE/Commands.cs | 22 +++++++++---------- .../CATHODE/CommandsPAK/Components/Entity.cs | 6 ++--- .../CommandsPAK/Components/ParameterData.cs | 6 ++--- .../Components/ResourceReference.cs | 18 +++++++-------- CathodeLib/Scripts/CATHODE/Movers.cs | 6 ++--- CathodeLib/Scripts/CATHODE/Resources.cs | 21 +++++++++++------- 7 files changed, 48 insertions(+), 43 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index c68395a..99c7ded 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -34,10 +34,10 @@ override protected bool LoadInternal() { Entry entry = new Entry(); reader.BaseStream.Position += 8; - entry.ID = Utilities.Consume(reader); + entry.id = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); reader.BaseStream.Position += 8; - entry.zoneID = reader.ReadInt32(); + entry.zone_id = Utilities.Consume(reader); reader.BaseStream.Position += 16; Entries.Add(entry); } @@ -55,10 +55,10 @@ override protected bool SaveInternal() for (int i = 0; i < Entries.Count; i++) { writer.Write(new byte[8]); - Utilities.Write(writer, Entries[i].ID); + Utilities.Write(writer, Entries[i].id); Utilities.Write(writer, Entries[i].entity); writer.Write(new byte[8]); - writer.Write(Entries[i].zoneID); + Utilities.Write(writer, Entries[i].zone_id); writer.Write(new byte[16]); } } @@ -69,9 +69,9 @@ override protected bool SaveInternal() #region STRUCTURES public class Entry { - public ShortGuid ID = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid + public ShortGuid id = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid public CommandsEntityReference entity = new CommandsEntityReference(); - public int zoneID = 0; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering + public ShortGuid zone_id = ShortGuid.Invalid; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering }; #endregion } diff --git a/CathodeLib/Scripts/CATHODE/Commands.cs b/CathodeLib/Scripts/CATHODE/Commands.cs index b91e9fc..235f710 100644 --- a/CathodeLib/Scripts/CATHODE/Commands.cs +++ b/CathodeLib/Scripts/CATHODE/Commands.cs @@ -264,9 +264,9 @@ override protected bool LoadInternal() ResourceReference resource = new ResourceReference(); resource.position = new Vector3(reader_parallel.ReadSingle(), reader_parallel.ReadSingle(), reader_parallel.ReadSingle()); resource.rotation = new Vector3(reader_parallel.ReadSingle(), reader_parallel.ReadSingle(), reader_parallel.ReadSingle()); - resource.resourceID = new ShortGuid(reader_parallel); - resource.entryType = CommandsUtils.GetResourceEntryType(reader_parallel.ReadBytes(4)); - switch (resource.entryType) + resource.resource_id = new ShortGuid(reader_parallel); + resource.resource_type = CommandsUtils.GetResourceEntryType(reader_parallel.ReadBytes(4)); + switch (resource.resource_type) { case ResourceType.RENDERABLE_INSTANCE: resource.index = reader_parallel.ReadInt32(); @@ -445,18 +445,18 @@ override protected bool LoadInternal() if (composite.functions[x].parameters[y].name != resParamID) continue; cResource resourceParam = (cResource)composite.functions[x].parameters[y].content; - resourceParam.value.AddRange(resourceRefs.Where(o => o.resourceID == resourceParam.shortGUID)); - resourceRefs.RemoveAll(o => o.resourceID == resourceParam.shortGUID); + resourceParam.value.AddRange(resourceRefs.Where(o => o.resource_id == resourceParam.shortGUID)); + resourceRefs.RemoveAll(o => o.resource_id == resourceParam.shortGUID); } } //Check to see if this resource applies directly to an ENTITY for (int x = 0; x < composite.functions.Count; x++) { - composite.functions[x].resources.AddRange(resourceRefs.Where(o => o.resourceID == composite.functions[x].shortGUID)); - resourceRefs.RemoveAll(o => o.resourceID == composite.functions[x].shortGUID); + composite.functions[x].resources.AddRange(resourceRefs.Where(o => o.resource_id == composite.functions[x].shortGUID)); + resourceRefs.RemoveAll(o => o.resource_id == composite.functions[x].shortGUID); } //Any that are left over will be applied to PhysicsSystem entities - if (resourceRefs.Count == 1 && resourceRefs[0].entryType == ResourceType.DYNAMIC_PHYSICS_SYSTEM) + if (resourceRefs.Count == 1 && resourceRefs[0].resource_type == ResourceType.DYNAMIC_PHYSICS_SYSTEM) { FunctionEntity physEnt = composite.functions.FirstOrDefault(o => o.function == physEntID); if (physEnt != null) physEnt.resources.Add(resourceRefs[0]); @@ -931,9 +931,9 @@ override protected bool SaveInternal() writer.Write(resourceReferences[i][p].rotation.Y); writer.Write(resourceReferences[i][p].rotation.Z); #endif - writer.Write(resourceReferences[i][p].resourceID.ToUInt32()); //Sometimes this is the entity ID that uses the resource, other times it's the "resource" parameter ID link - writer.Write(CommandsUtils.GetResourceEntryTypeGUID(resourceReferences[i][p].entryType).ToUInt32()); - switch (resourceReferences[i][p].entryType) + writer.Write(resourceReferences[i][p].resource_id.ToUInt32()); //Sometimes this is the entity ID that uses the resource, other times it's the "resource" parameter ID link + writer.Write(CommandsUtils.GetResourceEntryTypeGUID(resourceReferences[i][p].resource_type).ToUInt32()); + switch (resourceReferences[i][p].resource_type) { case ResourceType.RENDERABLE_INSTANCE: writer.Write(resourceReferences[i][p].index); diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index de2579b..de249ef 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -279,8 +279,8 @@ public ResourceReference AddResource(ResourceType type) if (rr == null) { rr = new ResourceReference(type); - rr.resourceID = shortGUID; - switch (rr.entryType) + rr.resource_id = shortGUID; + switch (rr.resource_type) { case ResourceType.DYNAMIC_PHYSICS_SYSTEM: case ResourceType.RENDERABLE_INSTANCE: @@ -296,7 +296,7 @@ public ResourceReference AddResource(ResourceType type) /* Find a resource reference of type */ public ResourceReference GetResource(ResourceType type) { - return resources.FirstOrDefault(o => o.entryType == type); + return resources.FirstOrDefault(o => o.resource_type == type); } public override string ToString() diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs index 52f12d5..a05991d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs @@ -268,8 +268,8 @@ public ResourceReference AddResource(ResourceType type) if (rr == null) { rr = new ResourceReference(type); - rr.resourceID = shortGUID; - switch (rr.entryType) + rr.resource_id = shortGUID; + switch (rr.resource_type) { case ResourceType.DYNAMIC_PHYSICS_SYSTEM: case ResourceType.RENDERABLE_INSTANCE: @@ -285,7 +285,7 @@ public ResourceReference AddResource(ResourceType type) /* Find a resource reference of type */ public ResourceReference GetResource(ResourceType type) { - return value.FirstOrDefault(o => o.entryType == type); + return value.FirstOrDefault(o => o.resource_type == type); } } [Serializable] diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs index 8ac36d7..ca9a4e2 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs @@ -27,7 +27,7 @@ public ResourceReference(ResourceType type) index = 0; break; } - entryType = type; + resource_type = type; } public static bool operator ==(ResourceReference x, ResourceReference y) @@ -37,8 +37,8 @@ public ResourceReference(ResourceType type) if (x.position != y.position) return false; if (x.rotation != y.rotation) return false; - if (x.resourceID != y.resourceID) return false; - if (x.entryType != y.entryType) return false; + if (x.resource_id != y.resource_id) return false; + if (x.resource_type != y.resource_type) return false; if (x.index != y.index) return false; if (x.count != y.count) return false; if (x.collisionID != y.collisionID) return false; @@ -60,8 +60,8 @@ public override bool Equals(object obj) return obj is ResourceReference reference && EqualityComparer.Default.Equals(position, reference.position) && EqualityComparer.Default.Equals(rotation, reference.rotation) && - EqualityComparer.Default.Equals(resourceID, reference.resourceID) && - entryType == reference.entryType && + EqualityComparer.Default.Equals(resource_id, reference.resource_id) && + resource_type == reference.resource_type && index == reference.index && count == reference.count && EqualityComparer.Default.Equals(collisionID, reference.collisionID); @@ -72,8 +72,8 @@ public override int GetHashCode() int hashCode = -1286985782; hashCode = hashCode * -1521134295 + position.GetHashCode(); hashCode = hashCode * -1521134295 + rotation.GetHashCode(); - hashCode = hashCode * -1521134295 + resourceID.GetHashCode(); - hashCode = hashCode * -1521134295 + entryType.GetHashCode(); + hashCode = hashCode * -1521134295 + resource_id.GetHashCode(); + hashCode = hashCode * -1521134295 + resource_type.GetHashCode(); hashCode = hashCode * -1521134295 + index.GetHashCode(); hashCode = hashCode * -1521134295 + count.GetHashCode(); hashCode = hashCode * -1521134295 + collisionID.GetHashCode(); @@ -83,8 +83,8 @@ public override int GetHashCode() public Vector3 position = new Vector3(0, 0, 0); public Vector3 rotation = new Vector3(0, 0, 0); - public ShortGuid resourceID; //TODO: we could deprecate this, and just write it knowing what we know with our object structure - public ResourceType entryType; + public ShortGuid resource_id; //this can be translated to a string sometimes, like DYNAMIC_PHYSICS_SYSTEM + public ResourceType resource_type; public int index = -1; public int count = 1; diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index c3abd23..616bca3 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -204,7 +204,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public UInt32 renderableElementIndex; //reds.bin index public UInt32 renderableElementCount; //reds.bin count - public UInt32 resourcesIndex; + public UInt32 resource_index; //This is the index value from Resources.bin //256 public Vector3 Unknowns5_; public UInt32 visibility; // pulled from iOS dump - should be visibility var? @@ -219,8 +219,8 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public float emissive_val2; //emissive surface val2 public float emissive_val3; //emissive surface val3 //296 - public ShortGuid zoneID; //zone id? RenderableScene::create_instance, RenderableScene::initialize - note in Collision.MAP we have this val too and it is defo zones - public ShortGuid zoneActivator; //zone activator? RenderableScene::create_instance, RenderableScene::initialize + public ShortGuid primary_zone_id; //zone id? RenderableScene::create_instance, RenderableScene::initialize - note in Collision.MAP we have this val too and it is defo zones + public ShortGuid secondary_zone_id; //zone activator? RenderableScene::create_instance, RenderableScene::initialize - this is another zone id, perhaps the one that is linked for preloading? //304 public UInt32 Unknowns61_; //uVar3 in reserve_light_light_master_sets, val of LightMasterSet, or an incrementer public UInt16 Unknown17_; // TODO: It is -1 most of the time, but some times it isn't. diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index 4b18865..ced29d7 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using CATHODE.Scripting; using CathodeLib; +using static CATHODE.Resources; namespace CATHODE { @@ -28,11 +30,10 @@ override protected bool LoadInternal() { Resource resource = new Resource(); - //TODO: I don't think this is as it seems... the composite_instance_id value often translates to a ShortGuid string, frequently Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM... - // ... and notably the number of entries that translate to DYNAMIC_PHYSICS_SYSTEM match the number of entries in PHYSICS.MAP (which defines the systems) + resource.unk = Utilities.Consume(reader); //this seems to be some kind of incrementing thing? + resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM + resource.index = reader.ReadInt32(); - resource.Entity = Utilities.Consume(reader); - resource.IndexFromMVREntry = reader.ReadInt32(); Entries.Add(resource); } } @@ -51,8 +52,9 @@ override protected bool SaveInternal() for (int i = 0; i < Entries.Count; i++) { - Utilities.Write(writer, Entries[i].Entity); - writer.Write(Entries[i].IndexFromMVREntry); + Utilities.Write(writer, Entries[i].unk); + Utilities.Write(writer, Entries[i].resource_id); + writer.Write(Entries[i].index); } } return true; @@ -62,8 +64,11 @@ override protected bool SaveInternal() #region STRUCTURES public class Resource { - public CommandsEntityReference Entity; - public int IndexFromMVREntry; // NOTE: This is an entry index in this file itself. + public ShortGuid unk; + + public ShortGuid resource_id; + + public int index; }; #endregion } From 7da5c41c8810f9d38067541385649cabc1f44c1d Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 24 Feb 2024 16:12:14 +0000 Subject: [PATCH 06/72] instance id --- CathodeLib/Scripts/CATHODE/Resources.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index ced29d7..06da2ef 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -29,11 +29,9 @@ override protected bool LoadInternal() for (int i = 0; i < entryCount; i++) { Resource resource = new Resource(); - - resource.unk = Utilities.Consume(reader); //this seems to be some kind of incrementing thing? + resource.composite_instance_id = Utilities.Consume(reader); resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM resource.index = reader.ReadInt32(); - Entries.Add(resource); } } @@ -52,7 +50,7 @@ override protected bool SaveInternal() for (int i = 0; i < Entries.Count; i++) { - Utilities.Write(writer, Entries[i].unk); + Utilities.Write(writer, Entries[i].composite_instance_id); Utilities.Write(writer, Entries[i].resource_id); writer.Write(Entries[i].index); } @@ -64,8 +62,7 @@ override protected bool SaveInternal() #region STRUCTURES public class Resource { - public ShortGuid unk; - + public ShortGuid composite_instance_id; public ShortGuid resource_id; public int index; From e53669ef7ff59d4975b7f3cc5a3957b80ad0fb8e Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 25 Feb 2024 09:06:28 +0000 Subject: [PATCH 07/72] renaming a couple bits --- CathodeLib/Scripts/CATHODE/Movers.cs | 14 +++++++------- CathodeLib/Scripts/CATHODE/Resources.cs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 616bca3..b5bcc73 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -194,15 +194,15 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public Matrix4x4 transform; //64 - public GPU_CONSTANTS gpuConstants; + public GPU_CONSTANTS gpu_constants; //144 public UInt64 fogsphere_val1; // 0xa0 in RenderableFogSphereInstance public UInt64 fogsphere_val2; // 0xa8 in RenderableFogSphereInstance //160 - public RENDER_CONSTANTS renderConstants; + public RENDER_CONSTANTS render_constants; //244 - public UInt32 renderableElementIndex; //reds.bin index - public UInt32 renderableElementCount; //reds.bin count + public UInt32 renderable_element_index; //reds.bin index + public UInt32 renderable_element_count; //reds.bin count public UInt32 resource_index; //This is the index value from Resources.bin //256 @@ -213,7 +213,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public CommandsEntityReference entity; //The entity in the Commands file //280 - public Int32 environmentMapIndex; //environment_map.bin index - converted to short in code + public Int32 environment_map_index; //environment_map.bin index - converted to short in code //284 public float emissive_val1; //emissive surface val1 public float emissive_val2; //emissive surface val2 @@ -233,8 +233,8 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce ~MOVER_DESCRIPTOR() { - gpuConstants = null; - renderConstants = null; + gpu_constants = null; + render_constants = null; entity = null; } }; diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index 06da2ef..0778399 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -31,7 +31,7 @@ override protected bool LoadInternal() Resource resource = new Resource(); resource.composite_instance_id = Utilities.Consume(reader); resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM - resource.index = reader.ReadInt32(); + resource.index = reader.ReadInt32(); //these entries are sorted by composite_instance_id, so the index doesn't go up as you would expect - the index is relative to mvr Entries.Add(resource); } } From a60d8667cbdf5a3d7d6e858476cda1d0cfc2000b Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 25 Feb 2024 15:58:43 +0000 Subject: [PATCH 08/72] misc test --- CathodeLib/Scripts/CATHODE/Movers.cs | 4 ++++ CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index b5bcc73..6705054 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -219,8 +219,12 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public float emissive_val2; //emissive surface val2 public float emissive_val3; //emissive surface val3 //296 + + //If primary zone ID or secondary zone ID are zero, they are not applied to a zone. it seems like the game hacks this by setting the primary id to 1 to add it to a sort of "global zone", for entities that are spawned but not in a zone. + public ShortGuid primary_zone_id; //zone id? RenderableScene::create_instance, RenderableScene::initialize - note in Collision.MAP we have this val too and it is defo zones public ShortGuid secondary_zone_id; //zone activator? RenderableScene::create_instance, RenderableScene::initialize - this is another zone id, perhaps the one that is linked for preloading? + //304 public UInt32 Unknowns61_; //uVar3 in reserve_light_light_master_sets, val of LightMasterSet, or an incrementer public UInt16 Unknown17_; // TODO: It is -1 most of the time, but some times it isn't. diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index 38d489b..5867f25 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Runtime.InteropServices; using CathodeLib; using System.Collections.Generic; @@ -38,6 +38,12 @@ override protected bool LoadInternal() entry.physics_system_index = reader.ReadInt32(); reader.BaseStream.Position += 4; entry.resource_type = Utilities.Consume(reader); + + if (entry.resource_type != ShortGuidUtils.Generate("DYNAMIC_PHYSICS_SYSTEM")) + { + string sdffds = ""; + } + entry.composite_instance_id = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); entry.Row0 = Utilities.Consume(reader); From 67d20808b9ddfb211b32ca07b0c9130d47475014 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 27 Feb 2024 21:04:43 +0000 Subject: [PATCH 09/72] don't cache commands save cache --- CathodeLib/Scripts/CATHODE/Commands.cs | 4 ++-- .../CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Commands.cs b/CathodeLib/Scripts/CATHODE/Commands.cs index 235f710..59fa4dc 100644 --- a/CathodeLib/Scripts/CATHODE/Commands.cs +++ b/CathodeLib/Scripts/CATHODE/Commands.cs @@ -722,7 +722,7 @@ override protected bool SaveInternal() stringStartRaw[3] = 0x80; writer.Write(stringStartRaw); string str = ((cString)parameters[i]).value.Replace("\u0092", "'"); - writer.Write(ShortGuidUtils.Generate(str).ToUInt32()); + writer.Write(ShortGuidUtils.Generate(str, false).ToUInt32()); for (int x = 0; x < str.Length; x++) writer.Write(str[x]); writer.Write((char)0x00); Utilities.Align(writer, 4); @@ -782,7 +782,7 @@ override protected bool SaveInternal() { int scriptStartPos = (int)writer.BaseStream.Position / 4; - Utilities.Write(writer, ShortGuidUtils.Generate(Entries[i].name)); + Utilities.Write(writer, ShortGuidUtils.Generate(Entries[i].name, false)); for (int x = 0; x < Entries[i].name.Length; x++) writer.Write(Entries[i].name[x]); writer.Write((char)0x00); Utilities.Align(writer, 4); diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs index 1212c8a..f446b2a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs @@ -49,13 +49,10 @@ public static void LinkCommands(Commands commands) } /* Generate a ShortGuid to interface with the Cathode scripting system */ - public static ShortGuid Generate(string value) + public static ShortGuid Generate(string value, bool cache = true) { - return Generate(value, true); - } - private static ShortGuid Generate(string value, bool cache = true) - { - if (_vanilla.cache.ContainsKey(value)) return _vanilla.cache[value]; + if (_vanilla.cache.ContainsKey(value)) + return _vanilla.cache[value]; SHA1Managed sha1 = new SHA1Managed(); byte[] hash1 = sha1.ComputeHash(Encoding.UTF8.GetBytes(value)); From d0e1de9753c86abaec843c2ed0f22322965bdc6f Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 27 Feb 2024 21:23:18 +0000 Subject: [PATCH 10/72] optionally save purge states --- .../CommandsPAK/Components/TypeEnums.cs | 1 + .../CommandsPAK/Helpers/CommandsUtils.cs | 48 ++++++++++++++++++- .../CommandsPAK/Helpers/CustomTable.cs | 41 ++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index fa4251f..2da8456 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -1105,6 +1105,7 @@ public enum CustomEndTables // Doing this will cause issues with backwards compatibility. ENTITY_NAMES, SHORT_GUIDS, + COMPOSITE_PURGE_STATES, //Add new entries here diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 369b198..3c7f69e 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -1,4 +1,5 @@ using CATHODE.Scripting.Internal; +using CathodeLib; using System; using System.Collections.Generic; using System.Linq; @@ -10,14 +11,55 @@ namespace CATHODE.Scripting //Helpful lookup tables for various Cathode Commands types public static class CommandsUtils { + public static CompositePurgeTable PurgedComposites => _purged; + private static CompositePurgeTable _purged; + + public static Commands LinkedCommands => _commands; + private static Commands _commands; + static CommandsUtils() { + _purged = new CompositePurgeTable(); + SetupFunctionTypeLUT(); SetupDataTypeLUT(); SetupObjectTypeLUT(); SetupResourceEntryTypeLUT(); } + /* Optionally, link a Commands file which can be used to save purge states to */ + public static void LinkCommands(Commands commands) + { + if (_commands != null) + { + _commands.OnLoadSuccess -= LoadPurgeStates; + _commands.OnSaveSuccess -= SavePurgeStates; + } + + _commands = commands; + if (_commands == null) return; + + _commands.OnLoadSuccess += LoadPurgeStates; + _commands.OnSaveSuccess += SavePurgeStates; + + LoadPurgeStates(_commands.Filepath); + } + + /* Pull non-vanilla entity names from the CommandsPAK */ + private static void LoadPurgeStates(string filepath) + { + _purged = (CompositePurgeTable)CustomTable.ReadTable(filepath, CustomEndTables.COMPOSITE_PURGE_STATES); + if (_purged == null) _purged = new CompositePurgeTable(); + Console.WriteLine("Registered " + _purged.purged.Count + " pre-purged composites!"); + } + + /* Write non-vanilla entity names to the CommandsPAK */ + private static void SavePurgeStates(string filepath) + { + CustomTable.WriteTable(filepath, CustomEndTables.COMPOSITE_PURGE_STATES, _purged); + Console.WriteLine("Stored " + _purged.purged.Count + " pre-purged composites!"); + } + #region FUNCTION_TYPE_UTILS /* Function Types */ private static Dictionary _functionTypeLUT = new Dictionary(); @@ -257,8 +299,12 @@ private static void GenerateHierarchiesRecursive(Commands commands, Entity ent, } /* CA's CAGE doesn't properly tidy up hierarchies pointing to deleted entities - so we can do that to save confusion */ - public static void PurgeDeadLinks(Commands commands, Composite composite) + public static void PurgeDeadLinks(Commands commands, Composite composite, bool force = false) { + if (!force && LinkedCommands == commands && _purged.purged.Contains(composite.shortGUID)) + return; + _purged.purged.Add(composite.shortGUID); + int originalUnknownCount = 0; int originalProxyCount = 0; int newProxyCount = 0; diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index c0399d1..064323a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -60,6 +60,9 @@ public static void WriteTable(string filepath, CustomEndTables table, Table cont case CustomEndTables.SHORT_GUIDS: ((GuidNameTable)toWrite[tableType]).Write(writer); break; + case CustomEndTables.COMPOSITE_PURGE_STATES: + ((CompositePurgeTable)toWrite[tableType]).Write(writer); + break; } } } @@ -103,6 +106,9 @@ public static Table ReadTable(string filepath, CustomEndTables table) case CustomEndTables.SHORT_GUIDS: data = new GuidNameTable(reader); break; + case CustomEndTables.COMPOSITE_PURGE_STATES: + data = new CompositePurgeTable(reader); + break; } } return data; @@ -228,4 +234,39 @@ public override void Write(BinaryWriter writer) } } } + public class CompositePurgeTable : CustomTable.Table + { + public CompositePurgeTable(BinaryReader reader = null) : base(reader) + { + type = CustomEndTables.COMPOSITE_PURGE_STATES; + } + + public List purged; + + protected override void Read(BinaryReader reader) + { + if (reader == null) + { + purged = new List(); + return; + } + + int count = reader.ReadInt32(); + purged = new List(count); + for (int i = 0; i < count; i++) + { + ShortGuid compositeID = Utilities.Consume(reader); + purged.Add(compositeID); + } + } + + public override void Write(BinaryWriter writer) + { + writer.Write(purged.Count); + for (int i = 0; i < purged.Count; i++) + { + Utilities.Write(writer, purged[i]); + } + } + } } From 0875b4f5b52edf49062c640983b0b8da1d3a77d1 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 27 Feb 2024 21:58:37 +0000 Subject: [PATCH 11/72] comment --- .../Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 3c7f69e..202c92a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -11,6 +11,7 @@ namespace CATHODE.Scripting //Helpful lookup tables for various Cathode Commands types public static class CommandsUtils { + //NOTE: This list is exposed publicly, because it is up to your app to manage it. public static CompositePurgeTable PurgedComposites => _purged; private static CompositePurgeTable _purged; @@ -302,7 +303,10 @@ private static void GenerateHierarchiesRecursive(Commands commands, Entity ent, public static void PurgeDeadLinks(Commands commands, Composite composite, bool force = false) { if (!force && LinkedCommands == commands && _purged.purged.Contains(composite.shortGUID)) + { + Console.WriteLine("Skipping purge, as this composite is listed within the purged table."); return; + } _purged.purged.Add(composite.shortGUID); int originalUnknownCount = 0; @@ -400,7 +404,11 @@ public static void PurgeDeadLinks(Commands commands, Composite composite, bool f (originalTriggerCount - newTriggerCount) + (originalAnimCount - newAnimCount) + (originalLinkCount - newLinkCount) == 0) + { + Console.WriteLine("Purge found nothing to clear up."); return; + } + Console.WriteLine( "Purged all dead hierarchies and entities in " + composite.name + "!" + "\n - " + originalUnknownCount + " unknown entities" + From 0264b6d013ed4ac28e76c061203e84e11716b6d7 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 27 Feb 2024 22:00:57 +0000 Subject: [PATCH 12/72] only manage externally --- CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 202c92a..0b8971c 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -307,7 +307,6 @@ public static void PurgeDeadLinks(Commands commands, Composite composite, bool f Console.WriteLine("Skipping purge, as this composite is listed within the purged table."); return; } - _purged.purged.Add(composite.shortGUID); int originalUnknownCount = 0; int originalProxyCount = 0; From 2ba72e8f94535c9f21453c4ac83b6d01fd5aaf45 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 13 Mar 2024 22:16:54 +0000 Subject: [PATCH 13/72] order resource entries --- CathodeLib/Scripts/CATHODE/Resources.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index 0778399..e6b014f 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -40,6 +40,8 @@ override protected bool LoadInternal() override protected bool SaveInternal() { + Entries = Entries.OrderBy(o => o.composite_instance_id).ToList(); + using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); From f0c4c4af2dc2b0576a55a651e49745302a9ff0d0 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 20 Mar 2024 18:54:53 +0000 Subject: [PATCH 14/72] change inherited type temp --- .../CommandsPAK/Helpers/CommandsUtils.cs | 4 ++++ .../CATHODE/CommandsPAK/Helpers/EntityUtils.cs | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 0b8971c..5e5c7f9 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -85,6 +85,10 @@ public static FunctionType GetFunctionType(byte[] tag) { return GetFunctionType(new ShortGuid(tag)); } + public static FunctionType GetFunctionType(FunctionEntity ent) + { + return GetFunctionType(ent.function); + } public static FunctionType GetFunctionType(ShortGuid tag) { SetupFunctionTypeLUT(); diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs index af4121b..e655daa 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs @@ -109,7 +109,9 @@ private static void ApplyDefaults(Entity entity, FunctionType currentType, bool { inheritance.Add(currentType); if (!includeInheritedMembers) break; - currentType = GetBaseFunction(currentType); + FunctionType? bf = GetBaseFunction(currentType); + if (bf == null) break; + currentType = bf.Value; } inheritance.Reverse(); @@ -129,11 +131,11 @@ private static void ApplyDefaults(Entity entity, FunctionType currentType, bool } /* Gets the function this function inherits from - you can keep calling this down to EntityMethodInterface */ - public static FunctionType GetBaseFunction(FunctionEntity entity) + public static FunctionType? GetBaseFunction(FunctionEntity entity) { - return GetBaseFunction(CommandsUtils.GetFunctionType(entity.function)); + return GetBaseFunction(CommandsUtils.GetFunctionType(entity)); } - public static FunctionType GetBaseFunction(FunctionType type) + public static FunctionType? GetBaseFunction(FunctionType type) { return GetBaseFunctionInternal(type); } @@ -154,19 +156,19 @@ private static void SaveCustomNames(string filepath) } /* Gets the base function for this function type */ - private static FunctionType GetBaseFunctionInternal(FunctionType type) + private static FunctionType? GetBaseFunctionInternal(FunctionType type) { switch (type) { //These types have no inheritance - perhaps they are unused? case FunctionType.CharacterMonitor: - case FunctionType.WEAPON_DidHitSomethingFilter: + case FunctionType.WEAPON_DidHitSomethingFilter: //this is used case FunctionType.VariableEnumString: case FunctionType.SetEnumString: case FunctionType.NetworkProxy: - case FunctionType.DebugPositionMarker: + case FunctionType.DebugPositionMarker: //this is used default: - throw new Exception(); + return null; //This is as far as we go, but it actually inherits from EntityResourceInterface case FunctionType.EntityMethodInterface: From 066544f048e2695ef4fb13edca2cad8fdf36994f Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 20 Mar 2024 19:11:23 +0000 Subject: [PATCH 15/72] remove unused types --- .../CommandsPAK/Components/TypeEnums.cs | 8 ++--- .../CommandsPAK/Helpers/EntityUtils.cs | 31 ++++++++----------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index 2da8456..eb7e24f 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -130,7 +130,7 @@ public enum FunctionType Character, CharacterAttachmentNode, CharacterCommand, - CharacterMonitor, + //CharacterMonitor, CharacterShivaArms, CharacterTypeMonitor, Checkpoint, @@ -515,7 +515,7 @@ public enum FunctionType NavMeshWalkablePlatform, NetPlayerCounter, NetworkedTimer, - NetworkProxy, + //NetworkProxy, NonInteractiveWater, NonPersistentBool, NonPersistentInt, @@ -684,7 +684,7 @@ public enum FunctionType SetBool, SetColour, SetEnum, - SetEnumString, + //SetEnumString, SetFloat, SetGamepadAxes, SetGameplayTips, @@ -830,7 +830,7 @@ public enum FunctionType VariableBool, VariableColour, VariableEnum, - VariableEnumString, + //VariableEnumString, VariableFilterObject, VariableFlashScreenColour, VariableFloat, diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs index e655daa..af15ebb 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs @@ -109,9 +109,7 @@ private static void ApplyDefaults(Entity entity, FunctionType currentType, bool { inheritance.Add(currentType); if (!includeInheritedMembers) break; - FunctionType? bf = GetBaseFunction(currentType); - if (bf == null) break; - currentType = bf.Value; + currentType = GetBaseFunction(currentType); } inheritance.Reverse(); @@ -131,11 +129,11 @@ private static void ApplyDefaults(Entity entity, FunctionType currentType, bool } /* Gets the function this function inherits from - you can keep calling this down to EntityMethodInterface */ - public static FunctionType? GetBaseFunction(FunctionEntity entity) + public static FunctionType GetBaseFunction(FunctionEntity entity) { return GetBaseFunction(CommandsUtils.GetFunctionType(entity)); } - public static FunctionType? GetBaseFunction(FunctionType type) + public static FunctionType GetBaseFunction(FunctionType type) { return GetBaseFunctionInternal(type); } @@ -156,19 +154,15 @@ private static void SaveCustomNames(string filepath) } /* Gets the base function for this function type */ - private static FunctionType? GetBaseFunctionInternal(FunctionType type) + private static FunctionType GetBaseFunctionInternal(FunctionType type) { switch (type) { - //These types have no inheritance - perhaps they are unused? - case FunctionType.CharacterMonitor: - case FunctionType.WEAPON_DidHitSomethingFilter: //this is used - case FunctionType.VariableEnumString: - case FunctionType.SetEnumString: - case FunctionType.NetworkProxy: - case FunctionType.DebugPositionMarker: //this is used - default: - return null; + //These are best guesses + case FunctionType.WEAPON_DidHitSomethingFilter: + return FunctionType.ScriptInterface; + case FunctionType.DebugPositionMarker: + return FunctionType.SensorInterface; //This is as far as we go, but it actually inherits from EntityResourceInterface case FunctionType.EntityMethodInterface: @@ -1799,6 +1793,7 @@ private static void SaveCustomNames(string filepath) case FunctionType.ZoneLoaded: return FunctionType.ScriptInterface; } + throw new Exception("Unhandled function type"); } /* Applies all default parameter data to a Function entity (DESTRUCTIVE!) */ @@ -7671,9 +7666,9 @@ private static void ApplyDefaultsInternal(Entity entity, FunctionType type) case FunctionType.BlendLowResFrame: entity.AddParameter("blend_value", new cFloat(0.0f), ParameterVariant.PARAMETER); //float break; - case FunctionType.CharacterMonitor: - entity.AddParameter("character", new cFloat(), ParameterVariant.INPUT); //ResourceID - break; + //case FunctionType.CharacterMonitor: + // entity.AddParameter("character", new cFloat(), ParameterVariant.INPUT); //ResourceID + // break; case FunctionType.AreaHitMonitor: entity.AddParameter("on_flamer_hit", new cFloat(), ParameterVariant.TARGET); // entity.AddParameter("on_shotgun_hit", new cFloat(), ParameterVariant.TARGET); // From aa977b7a8abe93f5670bf128a718ba2ab3d53610 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 9 Apr 2024 22:32:37 +0100 Subject: [PATCH 16/72] GetParentLinks --- .../CATHODE/CommandsPAK/Components/Entity.cs | 52 +++++++++++++++---- .../CommandsPAK/Helpers/CommandsUtils.cs | 4 +- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index de249ef..1edac0d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -182,7 +182,29 @@ public void RemoveParameterLink(string parameter, Entity childEntity, string chi ShortGuid parameter_id = ShortGuidUtils.Generate(parameter); ShortGuid childParameter_id = ShortGuidUtils.Generate(childParameter); //TODO: do we want to do RemoveAll? should probably just remove the first - childLinks.RemoveAll(o => o.parentParamID == parameter_id && o.childID == childEntity.shortGUID && o.childParamID == childParameter_id); + childLinks.RemoveAll(o => o.thisParamID == parameter_id && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameter_id); + } + + /* Find all links in to this entity (pass in the composite this entity is within) */ + public List GetParentLinks(Composite containedComposite) + { + List connections = new List(); + containedComposite.GetEntities().ForEach(ent => { + ent.childLinks.ForEach(link => + { + if (link.linkedEntityID == shortGUID) + { + connections.Add(new EntityConnector() + { + ID = link.ID, + thisParamID = link.linkedParamID, + linkedParamID = link.thisParamID, + linkedEntityID = ent.shortGUID + }); + } + }); + }); + return connections; } } } @@ -450,18 +472,28 @@ public Event(ShortGuid start, ShortGuid end) [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct EntityConnector { - public EntityConnector(ShortGuid childEntityID, ShortGuid parentParam, ShortGuid childParam) + public EntityConnector(ShortGuid linkedEntity, ShortGuid param, ShortGuid linkedParam) { - connectionID = ShortGuidUtils.GenerateRandom(); - parentParamID = parentParam; - childParamID = childParam; - childID = childEntityID; + ID = ShortGuidUtils.GenerateRandom(); + + thisParamID = param; + linkedParamID = linkedParam; + linkedEntityID = linkedEntity; } + public EntityConnector(Entity linkedEntity, string param, string linkedParam) + { + ID = ShortGuidUtils.GenerateRandom(); + + thisParamID = ShortGuidUtils.Generate(param); + linkedParamID = ShortGuidUtils.Generate(linkedParam); + linkedEntityID = linkedEntity.shortGUID; + } + + public ShortGuid ID; //The unique ID for this connection - public ShortGuid connectionID; //The unique ID for this connection - public ShortGuid parentParamID; //The ID of the parameter we're providing out - public ShortGuid childParamID; //The ID of the parameter we're providing into the child - public ShortGuid childID; //The ID of the entity we're linking to to provide the value for + public ShortGuid thisParamID; //The ID of the parameter + public ShortGuid linkedParamID; //The ID of the parameter we're connecting to + public ShortGuid linkedEntityID; //The ID of the entity we're connecting to that has the linked parameter } /// diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 5e5c7f9..c59f792 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -393,13 +393,15 @@ public static void PurgeDeadLinks(Commands commands, Composite composite, bool f { List childLinksPurged = new List(); for (int x = 0; x < entities[i].childLinks.Count; x++) - if (composite.GetEntityByID(entities[i].childLinks[x].childID) != null) + if (composite.GetEntityByID(entities[i].childLinks[x].linkedEntityID) != null) childLinksPurged.Add(entities[i].childLinks[x]); originalLinkCount += entities[i].childLinks.Count; newLinkCount += childLinksPurged.Count; entities[i].childLinks = childLinksPurged; } + //TODO: Clear aliases with no parameters/links in or out? + if (originalUnknownCount + (originalFuncCount - newFuncCount) + (originalProxyCount - newProxyCount) + From ded6f2a54f461d1d7bfb59176fda7bdf9ed485d4 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 24 Apr 2024 19:50:28 +0100 Subject: [PATCH 17/72] various utilities --- .../CommandsPAK/Components/Composite.cs | 6 ++++ .../CATHODE/CommandsPAK/Components/Entity.cs | 30 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs index 02760c3..fb08d1a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs @@ -57,6 +57,12 @@ public List GetEntities() return toReturn; } + /* Returns a collection of function entities in the composite matching the given type */ + public List GetFunctionEntitiesOfType(FunctionType type) + { + return functions.FindAll(o => o.function == CommandsUtils.GetFunctionTypeGUID(type)); + } + /* Add a new function entity */ public FunctionEntity AddFunction(FunctionType function, bool autopopulateParameters = false) { diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 1edac0d..11fd8a4 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -185,7 +185,7 @@ public void RemoveParameterLink(string parameter, Entity childEntity, string chi childLinks.RemoveAll(o => o.thisParamID == parameter_id && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameter_id); } - /* Find all links in to this entity (pass in the composite this entity is within) */ + /* Utility: Find all links in to this entity (pass in the composite this entity is within) */ public List GetParentLinks(Composite containedComposite) { List connections = new List(); @@ -206,6 +206,34 @@ public List GetParentLinks(Composite containedComposite) }); return connections; } + + /* Utility: Remove all child links out from the given parameter */ + public void RemoveAllParameterLinksOut(string parameter) + { + ShortGuid parameter_id = ShortGuidUtils.Generate(parameter); + childLinks.RemoveAll(o => o.thisParamID == parameter_id); + } + + /* Utility: Remove all child links in to the given parameter */ + public void RemoveAllParameterLinksIn(string parameter, Composite comp) + { + ShortGuid parameter_id = ShortGuidUtils.Generate(parameter); + List links_in = GetParentLinks(comp); + foreach (EntityConnector link in links_in) + { + if (link.linkedParamID != parameter_id) continue; + Entity ent = comp.GetEntityByID(link.linkedEntityID); + if (ent == null) continue; + ent.childLinks.RemoveAll(o => o.ID == link.ID); + } + } + + /* Utility: Remove all child links in to and out of the given parameter */ + public void RemoveAllParameterLinks(string parameter, Composite comp) + { + RemoveAllParameterLinksIn(parameter, comp); + RemoveAllParameterLinksOut(parameter); + } } } namespace CATHODE.Scripting From 1fd455d2f2d4368d35a3c8e016d2491436e818d6 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 24 Apr 2024 20:07:15 +0100 Subject: [PATCH 18/72] further util --- .../CommandsPAK/Components/Composite.cs | 6 ++++++ .../CATHODE/CommandsPAK/Components/Entity.cs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs index fb08d1a..aa24a97 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs @@ -63,6 +63,12 @@ public List GetFunctionEntitiesOfType(FunctionType type) return functions.FindAll(o => o.function == CommandsUtils.GetFunctionTypeGUID(type)); } + /* Removes all function entities in the composite matching the given type */ + public void RemoveAllFunctionEntitiesOfType(FunctionType type) + { + functions.RemoveAll(o => o.function == CommandsUtils.GetFunctionTypeGUID(type)); + } + /* Add a new function entity */ public FunctionEntity AddFunction(FunctionType function, bool autopopulateParameters = false) { diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 11fd8a4..9b6359c 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -213,6 +213,10 @@ public void RemoveAllParameterLinksOut(string parameter) ShortGuid parameter_id = ShortGuidUtils.Generate(parameter); childLinks.RemoveAll(o => o.thisParamID == parameter_id); } + public void RemoveAllParameterLinksOut() + { + childLinks.Clear(); + } /* Utility: Remove all child links in to the given parameter */ public void RemoveAllParameterLinksIn(string parameter, Composite comp) @@ -227,6 +231,16 @@ public void RemoveAllParameterLinksIn(string parameter, Composite comp) ent.childLinks.RemoveAll(o => o.ID == link.ID); } } + public void RemoveAllParameterLinksIn(Composite comp) + { + List links_in = GetParentLinks(comp); + foreach (EntityConnector link in links_in) + { + Entity ent = comp.GetEntityByID(link.linkedEntityID); + if (ent == null) continue; + ent.childLinks.RemoveAll(o => o.ID == link.ID); + } + } /* Utility: Remove all child links in to and out of the given parameter */ public void RemoveAllParameterLinks(string parameter, Composite comp) @@ -234,6 +248,13 @@ public void RemoveAllParameterLinks(string parameter, Composite comp) RemoveAllParameterLinksIn(parameter, comp); RemoveAllParameterLinksOut(parameter); } + + /* Utility: Remove all child links in to and out of the given parameter */ + public void RemoveAllParameterLinks(Composite comp) + { + RemoveAllParameterLinksIn(comp); + RemoveAllParameterLinksOut(); + } } } namespace CATHODE.Scripting From c4f1b6f915124d8017e1d461f0640d4788ad6e09 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 24 Apr 2024 21:24:21 +0100 Subject: [PATCH 19/72] more utils --- .../CATHODE/CommandsPAK/Components/Entity.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 9b6359c..f1a2d60 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -73,6 +73,29 @@ public Parameter GetParameter(ShortGuid id) return parameters.FirstOrDefault(o => o.name == id); } + /* Get all links out matching the given name */ + public List GetLinksOut(string name) + { + ShortGuid id = ShortGuidUtils.Generate(name); + return GetLinksOut(id); + } + public List GetLinksOut(ShortGuid id) + { + return childLinks.FindAll(o => o.thisParamID == id); + } + + /* Get all links in matching the given name */ + public List GetLinksIn(string name, Composite comp) + { + ShortGuid id = ShortGuidUtils.Generate(name); + return GetLinksIn(id, comp); + } + public List GetLinksIn(ShortGuid id, Composite comp) + { + List parent_links = GetParentLinks(comp); + return parent_links.FindAll(o => o.linkedParamID == id && o.linkedEntityID == this.shortGUID); + } + /* Add a data-supplying parameter to the entity */ /* public Parameter AddParameter(string name, T data, ParameterVariant variant = ParameterVariant.PARAMETER) @@ -543,6 +566,11 @@ public EntityConnector(Entity linkedEntity, string param, string linkedParam) public ShortGuid thisParamID; //The ID of the parameter public ShortGuid linkedParamID; //The ID of the parameter we're connecting to public ShortGuid linkedEntityID; //The ID of the entity we're connecting to that has the linked parameter + + public Entity GetEntity(Composite comp) + { + return comp.GetEntityByID(linkedEntityID); + } } /// From 59460fba95fa818e4c835e33ca197f76cad4cd47 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 8 May 2024 21:41:13 +0100 Subject: [PATCH 20/72] throw on non phys --- CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index 5867f25..085dc63 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -37,12 +37,10 @@ override protected bool LoadInternal() Entry entry = new Entry(); entry.physics_system_index = reader.ReadInt32(); reader.BaseStream.Position += 4; - entry.resource_type = Utilities.Consume(reader); + entry.resource_type = Utilities.Consume(reader); if (entry.resource_type != ShortGuidUtils.Generate("DYNAMIC_PHYSICS_SYSTEM")) - { - string sdffds = ""; - } + throw new Exception("Unexpected resource type! Expected DYNAMIC_PHYSICS_SYSTEM."); entry.composite_instance_id = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); From 2efe501ea1901eb65f76214484b650d0a908bbf3 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 18 May 2024 12:18:31 +0100 Subject: [PATCH 21/72] correctly handle phys maps position/rotation --- CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 47 +++++++++++++++++------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index 085dc63..4a0953c 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -1,10 +1,9 @@ using System.IO; -using System.Runtime.InteropServices; using CathodeLib; using System.Collections.Generic; using CATHODE.Scripting; using System; -using System.Linq; + #if UNITY_EDITOR || UNITY_STANDALONE_WIN using UnityEngine; #else @@ -44,9 +43,28 @@ override protected bool LoadInternal() entry.composite_instance_id = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); - entry.Row0 = Utilities.Consume(reader); - entry.Row1 = Utilities.Consume(reader); - entry.Row2 = Utilities.Consume(reader); + + Vector4 Row0 = Utilities.Consume(reader); + Vector4 Row1 = Utilities.Consume(reader); + Vector4 Row2 = Utilities.Consume(reader); + double[,] matrix = new double[,] + { + {Row0.X, Row0.Y, Row0.Z, Row0.W}, + {Row1.X, Row1.Y, Row1.Z, Row1.W}, + {Row2.X, Row2.Y, Row2.Z, Row2.W}, + }; + + entry.Position = new Vector3( + (float)matrix[0, 3], + (float)matrix[1, 3], + (float)matrix[2, 3] + ); + entry.Rotation = Quaternion.CreateFromRotationMatrix(new Matrix4x4( + (float)matrix[0, 0], (float)matrix[0, 1], (float)matrix[0, 2], 0, + (float)matrix[1, 0], (float)matrix[1, 1], (float)matrix[1, 2], 0, + (float)matrix[2, 0], (float)matrix[2, 1], (float)matrix[2, 2], 0, + 0, 0, 0, 1 + )); reader.BaseStream.Position += 8; Entries.Add(entry); @@ -69,9 +87,15 @@ override protected bool SaveInternal() Utilities.Write(writer, Entries[i].resource_type); Utilities.Write(writer, Entries[i].composite_instance_id); Utilities.Write(writer, Entries[i].entity); - Utilities.Write(writer, Entries[i].Row0); - Utilities.Write(writer, Entries[i].Row1); - Utilities.Write(writer, Entries[i].Row2); + + Matrix4x4 rotationMatrix4x4 = Matrix4x4.CreateFromQuaternion(Entries[i].Rotation); + Vector4 Row0 = new Vector4(rotationMatrix4x4.M11, rotationMatrix4x4.M12, rotationMatrix4x4.M13, Entries[i].Position.X); + Vector4 Row1 = new Vector4(rotationMatrix4x4.M21, rotationMatrix4x4.M22, rotationMatrix4x4.M23, Entries[i].Position.Y); + Vector4 Row2 = new Vector4(rotationMatrix4x4.M31, rotationMatrix4x4.M32, rotationMatrix4x4.M33, Entries[i].Position.Z); + + Utilities.Write(writer, Row0); + Utilities.Write(writer, Row1); + Utilities.Write(writer, Row2); writer.Write(new byte[8]); } } @@ -95,10 +119,9 @@ public class Entry //This is the entity ID and instance ID for the actual instanced composite entity (basically, a step down from the instance above). public CommandsEntityReference entity; - public Vector4 Row0; //mattf: setting to zero breaks stuff // NOTE: This is a 3x4 matrix, seems to have rotation data on the leftmost 3x3 matrix, and position - public Vector4 Row1; //mattf: setting to zero breaks stuff // on the rightmost 3x1 matrix. - - public Vector4 Row2; //mattf: setting to zero doesn't seem to do nothing: unused? + //This is the worldspace position of the composite instance + public Vector3 Position; + public Quaternion Rotation; }; #endregion } From 8efab836b3aa713590da4c77f27397331c4a065d Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 19 May 2024 08:23:41 +0100 Subject: [PATCH 22/72] add some maths utils and other stuff --- CathodeLib/Scripts/CATHODE/Commands.cs | 4 +- .../CATHODE/CommandsPAK/Components/Entity.cs | 2 +- .../CommandsPAK/Components/ParameterData.cs | 4 +- CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 3 - CathodeLib/Scripts/Utilities.cs | 67 +++++++++++++++++++ 5 files changed, 74 insertions(+), 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Commands.cs b/CathodeLib/Scripts/CATHODE/Commands.cs index 59fa4dc..42c2400 100644 --- a/CathodeLib/Scripts/CATHODE/Commands.cs +++ b/CathodeLib/Scripts/CATHODE/Commands.cs @@ -455,7 +455,7 @@ override protected bool LoadInternal() composite.functions[x].resources.AddRange(resourceRefs.Where(o => o.resource_id == composite.functions[x].shortGUID)); resourceRefs.RemoveAll(o => o.resource_id == composite.functions[x].shortGUID); } - //Any that are left over will be applied to PhysicsSystem entities + //Any that are left over will be applied to PhysicsSystem entities - really these just exist in the composite, but it's easier for us to track this way if (resourceRefs.Count == 1 && resourceRefs[0].resource_type == ResourceType.DYNAMIC_PHYSICS_SYSTEM) { FunctionEntity physEnt = composite.functions.FirstOrDefault(o => o.function == physEntID); @@ -574,6 +574,7 @@ override protected bool SaveInternal() Entries[i].functions[x].AddResource(ResourceType.EXCLUSIVE_MASTER_STATE_RESOURCE); break; + //NOTE: Really, DYNAMIC_PHYSICS_SYSTEM isn't actually on the entity, it's on the composite case FunctionType.PhysicsSystem: Parameter dps_index = Entries[i].functions[x].GetParameter("system_index"); if (dps_index == null) @@ -583,6 +584,7 @@ override protected bool SaveInternal() } Entries[i].functions[x].AddResource(ResourceType.DYNAMIC_PHYSICS_SYSTEM).index = ((cInteger)dps_index.content).value; break; + case FunctionType.EnvironmentModelReference: Parameter rsc = Entries[i].functions[x].GetParameter("resource"); if (rsc == null) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index f1a2d60..05a94ee 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -373,7 +373,7 @@ public ResourceReference AddResource(ResourceType type) if (rr == null) { rr = new ResourceReference(type); - rr.resource_id = shortGUID; + rr.resource_id = type == ResourceType.DYNAMIC_PHYSICS_SYSTEM ? ShortGuidUtils.Generate("DYNAMIC_PHYSICS_SYSTEM") : shortGUID; switch (rr.resource_type) { case ResourceType.DYNAMIC_PHYSICS_SYSTEM: diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs index a05991d..99319c7 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ParameterData.cs @@ -161,7 +161,9 @@ public cTransform(Vector3 position, Vector3 rotation) if (x == null) return y; if (y == null) return x; - return new cTransform(x.position + y.position, x.rotation + y.rotation); + + + return new cTransform(x.position + y.position, x.rotation.AddEulerAngles(y.rotation)); } public override string ToString() diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index 4a0953c..ea31e17 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -21,9 +21,6 @@ public class PhysicsMaps : CathodeFile public static new Implementation Implementation = Implementation.CREATE | Implementation.LOAD | Implementation.SAVE; public PhysicsMaps(string path) : base(path) { } - //NOTE: clearing out this file does not cause a crash, and it does not break physics objects like boxes - // ... it does however break doors... - #region FILE_IO override protected bool LoadInternal() { diff --git a/CathodeLib/Scripts/Utilities.cs b/CathodeLib/Scripts/Utilities.cs index 239811e..7aa2c0e 100644 --- a/CathodeLib/Scripts/Utilities.cs +++ b/CathodeLib/Scripts/Utilities.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; @@ -315,6 +316,45 @@ public class PAKContent } } + public static class MathsUtils + { + public static (decimal, decimal, decimal) ToYawPitchRoll(this Quaternion q) + { + decimal yaw = Convert.ToDecimal(Math.Atan2(2 * (q.Y * q.W + q.X * q.Z), 1 - 2 * (q.Y * q.Y + q.X * q.X)) * (180 / Math.PI)); + decimal pitch = Convert.ToDecimal(Math.Asin(2 * (q.X * q.W - q.Z * q.Y)) * (180 / Math.PI)); + decimal roll = Convert.ToDecimal(Math.Atan2(2 * (q.Z * q.W + q.X * q.Y), 1 - 2 * (q.X * q.X + q.Z * q.Z)) * (180 / Math.PI)); + + return (yaw, pitch, roll); + } + + public static Vector3 AddEulerAngles(this Vector3 euler1, Vector3 euler2) + { + Vector3 result = euler1 + euler2; + result = NormalizeEulerAngles(result); + return result; + } + private static Vector3 NormalizeEulerAngles(Vector3 angles) + { + angles.X = NormalizeAngle(angles.X); + angles.Y = NormalizeAngle(angles.Y); + angles.Z = NormalizeAngle(angles.Z); + return angles; + } + private static float NormalizeAngle(float angle) + { + angle = angle % 360; + if (angle > 180) + { + angle -= 360; + } + if (angle < -180) + { + angle += 360; + } + return angle; + } + } + public static class BigEndianUtils { public static Int64 ReadInt64(BinaryReader Reader, bool bigEndian = true) @@ -436,6 +476,33 @@ public CommandsEntityReference(EntityPath hierarchy) entity_id = hierarchy.GetPointedEntityID(); composite_instance_id = hierarchy.GenerateInstance(); } + + public override bool Equals(object obj) + { + if (!(obj is CommandsEntityReference)) return false; + return (CommandsEntityReference)obj == this; + } + + public static bool operator ==(CommandsEntityReference x, CommandsEntityReference y) + { + if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); + if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); + if (x.entity_id != y.entity_id) return false; + if (x.composite_instance_id != y.composite_instance_id) return false; + return true; + } + public static bool operator !=(CommandsEntityReference x, CommandsEntityReference y) + { + return !(x == y); + } + + public override int GetHashCode() + { + int hashCode = -539839184; + hashCode = hashCode * -1521134295 + entity_id.GetHashCode(); + hashCode = hashCode * -1521134295 + composite_instance_id.GetHashCode(); + return hashCode; + } } /* From a139e08d1e2a1efdf056cc3a9769059f14cdb4d3 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 19 May 2024 08:51:15 +0100 Subject: [PATCH 23/72] speed up a bit --- .../Scripts/CATHODE/CommandsPAK/Components/Composite.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs index aa24a97..e874718 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs @@ -60,13 +60,15 @@ public List GetEntities() /* Returns a collection of function entities in the composite matching the given type */ public List GetFunctionEntitiesOfType(FunctionType type) { - return functions.FindAll(o => o.function == CommandsUtils.GetFunctionTypeGUID(type)); + ShortGuid guid = CommandsUtils.GetFunctionTypeGUID(type); + return functions.FindAll(o => o.function == guid); } /* Removes all function entities in the composite matching the given type */ public void RemoveAllFunctionEntitiesOfType(FunctionType type) { - functions.RemoveAll(o => o.function == CommandsUtils.GetFunctionTypeGUID(type)); + ShortGuid guid = CommandsUtils.GetFunctionTypeGUID(type); + functions.RemoveAll(o => o.function == guid); } /* Add a new function entity */ From 9babe5e56e3112c17a5291367199817058fbb40e Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 19 May 2024 21:40:24 +0100 Subject: [PATCH 24/72] sub sort resources --- CathodeLib/Scripts/CATHODE/Resources.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index e6b014f..c54662b 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -40,7 +40,7 @@ override protected bool LoadInternal() override protected bool SaveInternal() { - Entries = Entries.OrderBy(o => o.composite_instance_id).ToList(); + Entries = Entries.OrderBy(o => o.composite_instance_id).ThenBy(o => o.resource_id).ToList(); using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { From f638be185cbda61752bffaca342b9bc03665ab34 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 21 May 2024 21:41:57 +0100 Subject: [PATCH 25/72] rename to entityid --- CathodeLib/Scripts/CATHODE/Commands.cs | 4 ++-- .../CATHODE/CommandsPAK/Components/ResourceReference.cs | 8 ++++---- CathodeLib/Scripts/CATHODE/Movers.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Commands.cs b/CathodeLib/Scripts/CATHODE/Commands.cs index 42c2400..a716ce7 100644 --- a/CathodeLib/Scripts/CATHODE/Commands.cs +++ b/CathodeLib/Scripts/CATHODE/Commands.cs @@ -274,7 +274,7 @@ override protected bool LoadInternal() break; case ResourceType.COLLISION_MAPPING: resource.index = reader_parallel.ReadInt32(); - resource.collisionID = new ShortGuid(reader_parallel); + resource.entityID = new ShortGuid(reader_parallel); break; case ResourceType.ANIMATED_MODEL: case ResourceType.DYNAMIC_PHYSICS_SYSTEM: @@ -943,7 +943,7 @@ override protected bool SaveInternal() break; case ResourceType.COLLISION_MAPPING: writer.Write(resourceReferences[i][p].index); - writer.Write(resourceReferences[i][p].collisionID.ToUInt32()); + writer.Write(resourceReferences[i][p].entityID.ToUInt32()); break; case ResourceType.ANIMATED_MODEL: case ResourceType.DYNAMIC_PHYSICS_SYSTEM: diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs index ca9a4e2..8edee9d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ResourceReference.cs @@ -41,7 +41,7 @@ public ResourceReference(ResourceType type) if (x.resource_type != y.resource_type) return false; if (x.index != y.index) return false; if (x.count != y.count) return false; - if (x.collisionID != y.collisionID) return false; + if (x.entityID != y.entityID) return false; return true; } @@ -64,7 +64,7 @@ public override bool Equals(object obj) resource_type == reference.resource_type && index == reference.index && count == reference.count && - EqualityComparer.Default.Equals(collisionID, reference.collisionID); + EqualityComparer.Default.Equals(entityID, reference.entityID); } public override int GetHashCode() @@ -76,7 +76,7 @@ public override int GetHashCode() hashCode = hashCode * -1521134295 + resource_type.GetHashCode(); hashCode = hashCode * -1521134295 + index.GetHashCode(); hashCode = hashCode * -1521134295 + count.GetHashCode(); - hashCode = hashCode * -1521134295 + collisionID.GetHashCode(); + hashCode = hashCode * -1521134295 + entityID.GetHashCode(); return hashCode; } @@ -89,6 +89,6 @@ public override int GetHashCode() public int index = -1; public int count = 1; - public ShortGuid collisionID = new ShortGuid("FF-FF-FF-FF"); + public ShortGuid entityID = new ShortGuid("FF-FF-FF-FF"); } } diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 6705054..0cc7f4f 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -204,7 +204,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public UInt32 renderable_element_index; //reds.bin index public UInt32 renderable_element_count; //reds.bin count - public UInt32 resource_index; //This is the index value from Resources.bin + public int resource_index; //This is the index value from Resources.bin //256 public Vector3 Unknowns5_; public UInt32 visibility; // pulled from iOS dump - should be visibility var? From d1bd578c57f60209502665a11dbd0630b5d7486f Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Thu, 23 May 2024 23:55:15 +0100 Subject: [PATCH 26/72] misc indexes and stuff --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 22 ++++++++++++++++++- .../CommandsPAK/Helpers/CommandsUtils.cs | 2 +- CathodeLib/Scripts/CATHODE/Movers.cs | 8 +++---- CathodeLib/Scripts/CATHODE/Resources.cs | 22 +++++++++---------- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 99c7ded..658ead8 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -1,8 +1,9 @@ -using CATHODE.Scripting; +using CATHODE.Scripting; using CathodeLib; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.InteropServices; namespace CATHODE @@ -47,6 +48,8 @@ override protected bool LoadInternal() override protected bool SaveInternal() { + Entries = Entries.OrderBy(o => o.entity.entity_id.ToUInt32() + o.id.ToUInt32()).ThenBy(o => o.entity.composite_instance_id.ToUInt32()).ThenBy(o => o.zone_id.ToUInt32()).ToList(); + using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); @@ -72,6 +75,23 @@ public class Entry public ShortGuid id = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid public CommandsEntityReference entity = new CommandsEntityReference(); public ShortGuid zone_id = ShortGuid.Invalid; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering + + public override bool Equals(object obj) + { + return obj is Entry entry && + EqualityComparer.Default.Equals(id, entry.id) && + EqualityComparer.Default.Equals(entity, entry.entity) && + EqualityComparer.Default.Equals(zone_id, entry.zone_id); + } + + public override int GetHashCode() + { + int hashCode = 1001543423; + hashCode = hashCode * -1521134295 + id.GetHashCode(); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(entity); + hashCode = hashCode * -1521134295 + zone_id.GetHashCode(); + return hashCode; + } }; #endregion } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index c59f792..c32b806 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -244,7 +244,7 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li entity = currentFlowgraphToSearch.GetEntityByID(hierarchyCopy[i]); if (entity == null) break; - if (includeShortGuids) hierarchyString += "[" + entity.shortGUID + "] "; + if (includeShortGuids) hierarchyString += "[" + entity.shortGUID.ToByteString() + "] "; hierarchyString += EntityUtils.GetName(currentFlowgraphToSearch.shortGUID, entity.shortGUID); if (i >= hierarchyCopy.Count - 2) break; //Last is always 00-00-00-00 hierarchyString += " -> "; diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 0cc7f4f..2f4c850 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -200,6 +200,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public UInt64 fogsphere_val2; // 0xa8 in RenderableFogSphereInstance //160 public RENDER_CONSTANTS render_constants; + //244 public UInt32 renderable_element_index; //reds.bin index public UInt32 renderable_element_count; //reds.bin count @@ -212,7 +213,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public CommandsEntityReference entity; //The entity in the Commands file - //280 + //280 public Int32 environment_map_index; //environment_map.bin index - converted to short in code //284 public float emissive_val1; //emissive surface val1 @@ -221,9 +222,8 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce //296 //If primary zone ID or secondary zone ID are zero, they are not applied to a zone. it seems like the game hacks this by setting the primary id to 1 to add it to a sort of "global zone", for entities that are spawned but not in a zone. - - public ShortGuid primary_zone_id; //zone id? RenderableScene::create_instance, RenderableScene::initialize - note in Collision.MAP we have this val too and it is defo zones - public ShortGuid secondary_zone_id; //zone activator? RenderableScene::create_instance, RenderableScene::initialize - this is another zone id, perhaps the one that is linked for preloading? + public ShortGuid primary_zone_id; + public ShortGuid secondary_zone_id; //304 public UInt32 Unknowns61_; //uVar3 in reserve_light_light_master_sets, val of LightMasterSet, or an incrementer diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index c54662b..5b7731d 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -26,35 +26,37 @@ override protected bool LoadInternal() int entryCount = reader.ReadInt32(); reader.BaseStream.Position += 4; + Resource[] entries = new Resource[entryCount]; for (int i = 0; i < entryCount; i++) { Resource resource = new Resource(); resource.composite_instance_id = Utilities.Consume(reader); resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM - resource.index = reader.ReadInt32(); //these entries are sorted by composite_instance_id, so the index doesn't go up as you would expect - the index is relative to mvr - Entries.Add(resource); + int index = reader.ReadInt32(); + entries[index] = resource; } + Entries = entries.ToList(); } return true; } override protected bool SaveInternal() { - Entries = Entries.OrderBy(o => o.composite_instance_id).ThenBy(o => o.resource_id).ToList(); + List orderedEntries = Entries.OrderBy(o => o.composite_instance_id).ThenBy(o => o.resource_id).ToList(); using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); writer.Write(new byte[4] { 0xCC, 0xBA, 0xED, 0xFE }); writer.Write((Int32)1); - writer.Write(Entries.Count); + writer.Write(orderedEntries.Count); writer.Write((Int32)0); - for (int i = 0; i < Entries.Count; i++) + for (int i = 0; i < orderedEntries.Count; i++) { - Utilities.Write(writer, Entries[i].composite_instance_id); - Utilities.Write(writer, Entries[i].resource_id); - writer.Write(Entries[i].index); + Utilities.Write(writer, orderedEntries[i].composite_instance_id); + Utilities.Write(writer, orderedEntries[i].resource_id); + writer.Write(Entries.IndexOf(orderedEntries[i])); } } return true; @@ -66,8 +68,6 @@ public class Resource { public ShortGuid composite_instance_id; public ShortGuid resource_id; - - public int index; }; #endregion } From e2bab6e808fc562284e64fb4056af3e3fe6260da Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 26 May 2024 14:09:56 +0100 Subject: [PATCH 27/72] EntityHandle and zone ID --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 8 +++-- .../CATHODE/CommandsPAK/Components/Entity.cs | 36 +++++++++++-------- .../CommandsPAK/Helpers/CommandsUtils.cs | 6 ++-- CathodeLib/Scripts/Utilities.cs | 2 +- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 658ead8..8f2f982 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -1,4 +1,4 @@ -using CATHODE.Scripting; +using CATHODE.Scripting; using CathodeLib; using System; using System.Collections.Generic; @@ -41,6 +41,10 @@ override protected bool LoadInternal() entry.zone_id = Utilities.Consume(reader); reader.BaseStream.Position += 16; Entries.Add(entry); + + //uint test1 = entry.entity.entity_id.ToUInt32() + entry.id.ToUInt32() + entry.entity.composite_instance_id.ToUInt32() + entry.zone_id.ToUInt32(); + + //Console.WriteLine(test1 + " -> " + entry.entity.entity_id.ToUInt32() + " -> " + entry.id.ToUInt32() + " -> " + entry.entity.composite_instance_id.ToUInt32() + " -> " + entry.zone_id.ToUInt32()); } } return true; @@ -48,7 +52,7 @@ override protected bool LoadInternal() override protected bool SaveInternal() { - Entries = Entries.OrderBy(o => o.entity.entity_id.ToUInt32() + o.id.ToUInt32()).ThenBy(o => o.entity.composite_instance_id.ToUInt32()).ThenBy(o => o.zone_id.ToUInt32()).ToList(); + //Entries = Entries.OrderBy(o => o.entity.entity_id.ToUInt32() + o.id.ToUInt32()).ThenBy(o => o.entity.composite_instance_id.ToUInt32()).ThenBy(o => o.zone_id.ToUInt32()).ToList(); using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 05a94ee..e8b5ff2 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -419,7 +419,7 @@ public ProxyEntity(ShortGuid shortGUID) : base(shortGUID, EntityVariant.PROXY) { } public ShortGuid function; //The "function" value on the entity we're proxying - public EntityPath proxy = new EntityPath(); //A path to the entity we're proxying + public EntityHandle proxy = new EntityHandle(); //A path to the entity we're proxying } [Serializable] public class AliasEntity : Entity @@ -437,7 +437,7 @@ public AliasEntity(ShortGuid shortGUID, List hierarchy = null) : base if (hierarchy != null) this.alias.path = hierarchy; } - public EntityPath alias = new EntityPath(); //A path to the entity we're an alias of + public EntityHandle alias = new EntityHandle(); //A path to the entity we're an alias of } #region SPECIAL FUNCTION ENTITIES @@ -471,7 +471,7 @@ public class Connection public ShortGuid parameterSubID; //if parameterID is position, this might be x for example //The path to the connected entity which has the above parameter - public EntityPath connectedEntity = new EntityPath(); + public EntityHandle connectedEntity = new EntityHandle(); } [Serializable] @@ -520,7 +520,7 @@ public TriggerSequence(ShortGuid id, bool autoGenerateParameters = false) : base public class Entity { public float timing = 0.0f; - public EntityPath connectedEntity = new EntityPath(); + public EntityHandle connectedEntity = new EntityHandle(); } [Serializable] public class Event @@ -579,12 +579,12 @@ public Entity GetEntity(Composite comp) /// [Serializable] #if DEBUG - [JsonConverter(typeof(EntityPathConverter))] + [JsonConverter(typeof(EntityHandleConverter))] #endif - public class EntityPath + public class EntityHandle { - public EntityPath() { } - public EntityPath(List _path) + public EntityHandle() { } + public EntityHandle(List _path) { path = _path; @@ -593,7 +593,7 @@ public EntityPath(List _path) } public List path = new List(); - public static bool operator ==(EntityPath x, EntityPath y) + public static bool operator ==(EntityHandle x, EntityHandle y) { if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); @@ -605,14 +605,14 @@ public EntityPath(List _path) } return true; } - public static bool operator !=(EntityPath x, EntityPath y) + public static bool operator !=(EntityHandle x, EntityHandle y) { return !(x == y); } public override bool Equals(object obj) { - return obj is EntityPath hierarchy && + return obj is EntityHandle hierarchy && EqualityComparer>.Default.Equals(this.path, hierarchy.path); } @@ -733,19 +733,25 @@ public ShortGuid GenerateInstance() path.Add(ShortGuid.Invalid); return instanceGenerated; } + + /* Generate a zone ID (use this when the EntityHandle points to a Zone entity) */ + public ShortGuid GenerateZoneID() + { + return new ShortGuid(0 + GenerateInstance().ToUInt32() + GetPointedEntityID().ToUInt32() + 1); + } } #if DEBUG - public class EntityPathConverter : JsonConverter + public class EntityHandleConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - writer.WriteValue(((EntityPath)value).GetAsString()); + writer.WriteValue(((EntityHandle)value).GetAsString()); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - EntityPath e = new EntityPath(); + EntityHandle e = new EntityHandle(); List vals = reader.Value.ToString().Split(new[] { " -> " }, StringSplitOptions.None).ToList(); for (int i = 0; i < vals.Count; i++) e.path.Add(new ShortGuid(vals[i])); return e; @@ -753,7 +759,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override bool CanConvert(Type objectType) { - return objectType == typeof(EntityPath); + return objectType == typeof(EntityHandle); } } #endif diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index c32b806..9ada5e3 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -270,9 +270,9 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li /* Generate all possible hierarchies for an entity */ private static List> _hierarchies = new List>(); - public static List GenerateHierarchies(Commands commands, Composite composite, Entity entity) + public static List GenerateHierarchies(Commands commands, Composite composite, Entity entity) { - List hierarchies = new List(); + List hierarchies = new List(); _hierarchies.Clear(); GenerateHierarchiesRecursive(commands, null, commands.EntryPoints[0], composite, new List()); @@ -280,7 +280,7 @@ public static List GenerateHierarchies(Commands commands, Composite for (int i = 0; i < _hierarchies.Count; i++) { _hierarchies[i].Add(entity.shortGUID); - hierarchies.Add(new EntityPath(_hierarchies[i])); + hierarchies.Add(new EntityHandle(_hierarchies[i])); } return hierarchies; diff --git a/CathodeLib/Scripts/Utilities.cs b/CathodeLib/Scripts/Utilities.cs index 7aa2c0e..93b0d29 100644 --- a/CathodeLib/Scripts/Utilities.cs +++ b/CathodeLib/Scripts/Utilities.cs @@ -471,7 +471,7 @@ public class CommandsEntityReference public ShortGuid composite_instance_id = ShortGuid.Invalid; //The instance of the composite this entity is in when created via hierarchy public CommandsEntityReference() { } - public CommandsEntityReference(EntityPath hierarchy) + public CommandsEntityReference(EntityHandle hierarchy) { entity_id = hierarchy.GetPointedEntityID(); composite_instance_id = hierarchy.GenerateInstance(); From 95c0e93a59809ff8ad6e3af1650b24c246ea2fc5 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 26 May 2024 14:22:28 +0100 Subject: [PATCH 28/72] renaming --- .../Scripts/CATHODE/CharacterAccessorySets.cs | 4 +-- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 10 +++---- .../CATHODE/CommandsPAK/Components/Entity.cs | 30 +++++++++---------- .../CommandsPAK/Helpers/CommandsUtils.cs | 6 ++-- CathodeLib/Scripts/CATHODE/Movers.cs | 2 +- CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 4 +-- CathodeLib/Scripts/Utilities.cs | 14 ++++----- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CharacterAccessorySets.cs b/CathodeLib/Scripts/CATHODE/CharacterAccessorySets.cs index 338bb5c..623ae48 100644 --- a/CathodeLib/Scripts/CATHODE/CharacterAccessorySets.cs +++ b/CathodeLib/Scripts/CATHODE/CharacterAccessorySets.cs @@ -25,7 +25,7 @@ override protected bool LoadInternal() for (int i = 0; i < entryCount; i++) { Entry entry = new Entry(); - entry.character = Utilities.Consume(reader); + entry.character = Utilities.Consume(reader); entry.shirt_composite = Utilities.Consume(reader); entry.trousers_composite = Utilities.Consume(reader); @@ -112,7 +112,7 @@ override protected bool SaveInternal() #region STRUCTURES public class Entry { - public CommandsEntityReference character = new CommandsEntityReference(); + public EntityHandle character = new EntityHandle(); public ShortGuid shirt_composite = ShortGuid.Invalid; public ShortGuid trousers_composite = ShortGuid.Invalid; diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 8f2f982..5b25b58 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -36,7 +36,7 @@ override protected bool LoadInternal() Entry entry = new Entry(); reader.BaseStream.Position += 8; entry.id = Utilities.Consume(reader); - entry.entity = Utilities.Consume(reader); + entry.entity = Utilities.Consume(reader); reader.BaseStream.Position += 8; entry.zone_id = Utilities.Consume(reader); reader.BaseStream.Position += 16; @@ -63,7 +63,7 @@ override protected bool SaveInternal() { writer.Write(new byte[8]); Utilities.Write(writer, Entries[i].id); - Utilities.Write(writer, Entries[i].entity); + Utilities.Write(writer, Entries[i].entity); writer.Write(new byte[8]); Utilities.Write(writer, Entries[i].zone_id); writer.Write(new byte[16]); @@ -77,14 +77,14 @@ override protected bool SaveInternal() public class Entry { public ShortGuid id = ShortGuid.Invalid; //This is the name of the entity hashed via ShortGuid - public CommandsEntityReference entity = new CommandsEntityReference(); + public EntityHandle entity = new EntityHandle(); public ShortGuid zone_id = ShortGuid.Invalid; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering public override bool Equals(object obj) { return obj is Entry entry && EqualityComparer.Default.Equals(id, entry.id) && - EqualityComparer.Default.Equals(entity, entry.entity) && + EqualityComparer.Default.Equals(entity, entry.entity) && EqualityComparer.Default.Equals(zone_id, entry.zone_id); } @@ -92,7 +92,7 @@ public override int GetHashCode() { int hashCode = 1001543423; hashCode = hashCode * -1521134295 + id.GetHashCode(); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(entity); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(entity); hashCode = hashCode * -1521134295 + zone_id.GetHashCode(); return hashCode; } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index e8b5ff2..5b97d0d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -419,7 +419,7 @@ public ProxyEntity(ShortGuid shortGUID) : base(shortGUID, EntityVariant.PROXY) { } public ShortGuid function; //The "function" value on the entity we're proxying - public EntityHandle proxy = new EntityHandle(); //A path to the entity we're proxying + public EntityPath proxy = new EntityPath(); //A path to the entity we're proxying } [Serializable] public class AliasEntity : Entity @@ -437,7 +437,7 @@ public AliasEntity(ShortGuid shortGUID, List hierarchy = null) : base if (hierarchy != null) this.alias.path = hierarchy; } - public EntityHandle alias = new EntityHandle(); //A path to the entity we're an alias of + public EntityPath alias = new EntityPath(); //A path to the entity we're an alias of } #region SPECIAL FUNCTION ENTITIES @@ -471,7 +471,7 @@ public class Connection public ShortGuid parameterSubID; //if parameterID is position, this might be x for example //The path to the connected entity which has the above parameter - public EntityHandle connectedEntity = new EntityHandle(); + public EntityPath connectedEntity = new EntityPath(); } [Serializable] @@ -520,7 +520,7 @@ public TriggerSequence(ShortGuid id, bool autoGenerateParameters = false) : base public class Entity { public float timing = 0.0f; - public EntityHandle connectedEntity = new EntityHandle(); + public EntityPath connectedEntity = new EntityPath(); } [Serializable] public class Event @@ -579,12 +579,12 @@ public Entity GetEntity(Composite comp) /// [Serializable] #if DEBUG - [JsonConverter(typeof(EntityHandleConverter))] + [JsonConverter(typeof(EntityPathConverter))] #endif - public class EntityHandle + public class EntityPath { - public EntityHandle() { } - public EntityHandle(List _path) + public EntityPath() { } + public EntityPath(List _path) { path = _path; @@ -593,7 +593,7 @@ public EntityHandle(List _path) } public List path = new List(); - public static bool operator ==(EntityHandle x, EntityHandle y) + public static bool operator ==(EntityPath x, EntityPath y) { if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); @@ -605,14 +605,14 @@ public EntityHandle(List _path) } return true; } - public static bool operator !=(EntityHandle x, EntityHandle y) + public static bool operator !=(EntityPath x, EntityPath y) { return !(x == y); } public override bool Equals(object obj) { - return obj is EntityHandle hierarchy && + return obj is EntityPath hierarchy && EqualityComparer>.Default.Equals(this.path, hierarchy.path); } @@ -742,16 +742,16 @@ public ShortGuid GenerateZoneID() } #if DEBUG - public class EntityHandleConverter : JsonConverter + public class EntityPathConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - writer.WriteValue(((EntityHandle)value).GetAsString()); + writer.WriteValue(((EntityPath)value).GetAsString()); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - EntityHandle e = new EntityHandle(); + EntityPath e = new EntityPath(); List vals = reader.Value.ToString().Split(new[] { " -> " }, StringSplitOptions.None).ToList(); for (int i = 0; i < vals.Count; i++) e.path.Add(new ShortGuid(vals[i])); return e; @@ -759,7 +759,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override bool CanConvert(Type objectType) { - return objectType == typeof(EntityHandle); + return objectType == typeof(EntityPath); } } #endif diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 9ada5e3..c32b806 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -270,9 +270,9 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li /* Generate all possible hierarchies for an entity */ private static List> _hierarchies = new List>(); - public static List GenerateHierarchies(Commands commands, Composite composite, Entity entity) + public static List GenerateHierarchies(Commands commands, Composite composite, Entity entity) { - List hierarchies = new List(); + List hierarchies = new List(); _hierarchies.Clear(); GenerateHierarchiesRecursive(commands, null, commands.EntryPoints[0], composite, new List()); @@ -280,7 +280,7 @@ public static List GenerateHierarchies(Commands commands, Composit for (int i = 0; i < _hierarchies.Count; i++) { _hierarchies[i].Add(entity.shortGUID); - hierarchies.Add(new EntityHandle(_hierarchies[i])); + hierarchies.Add(new EntityPath(_hierarchies[i])); } return hierarchies; diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 2f4c850..aca272d 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -211,7 +211,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public UInt32 visibility; // pulled from iOS dump - should be visibility var? //272 - public CommandsEntityReference entity; //The entity in the Commands file + public EntityHandle entity; //The entity in the Commands file //280 public Int32 environment_map_index; //environment_map.bin index - converted to short in code diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index ea31e17..256269a 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -39,7 +39,7 @@ override protected bool LoadInternal() throw new Exception("Unexpected resource type! Expected DYNAMIC_PHYSICS_SYSTEM."); entry.composite_instance_id = Utilities.Consume(reader); - entry.entity = Utilities.Consume(reader); + entry.entity = Utilities.Consume(reader); Vector4 Row0 = Utilities.Consume(reader); Vector4 Row1 = Utilities.Consume(reader); @@ -114,7 +114,7 @@ public class Entry public ShortGuid composite_instance_id; //This is the entity ID and instance ID for the actual instanced composite entity (basically, a step down from the instance above). - public CommandsEntityReference entity; + public EntityHandle entity; //This is the worldspace position of the composite instance public Vector3 Position; diff --git a/CathodeLib/Scripts/Utilities.cs b/CathodeLib/Scripts/Utilities.cs index 93b0d29..a3b8b9e 100644 --- a/CathodeLib/Scripts/Utilities.cs +++ b/CathodeLib/Scripts/Utilities.cs @@ -465,13 +465,13 @@ public OffsetPair(long _go, int _ec) /// The instance ID identifies the hierarchy the composite was created at. This can be generated with GenerateInstance. /// [StructLayout(LayoutKind.Sequential, Pack = 1)] - public class CommandsEntityReference + public class EntityHandle { public ShortGuid entity_id = ShortGuid.Invalid; //The ID of the entity within its written composite public ShortGuid composite_instance_id = ShortGuid.Invalid; //The instance of the composite this entity is in when created via hierarchy - public CommandsEntityReference() { } - public CommandsEntityReference(EntityHandle hierarchy) + public EntityHandle() { } + public EntityHandle(EntityPath hierarchy) { entity_id = hierarchy.GetPointedEntityID(); composite_instance_id = hierarchy.GenerateInstance(); @@ -479,11 +479,11 @@ public CommandsEntityReference(EntityHandle hierarchy) public override bool Equals(object obj) { - if (!(obj is CommandsEntityReference)) return false; - return (CommandsEntityReference)obj == this; + if (!(obj is EntityHandle)) return false; + return (EntityHandle)obj == this; } - public static bool operator ==(CommandsEntityReference x, CommandsEntityReference y) + public static bool operator ==(EntityHandle x, EntityHandle y) { if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); @@ -491,7 +491,7 @@ public override bool Equals(object obj) if (x.composite_instance_id != y.composite_instance_id) return false; return true; } - public static bool operator !=(CommandsEntityReference x, CommandsEntityReference y) + public static bool operator !=(EntityHandle x, EntityHandle y) { return !(x == y); } From bd8145b0c9971397690bf22c716547758e915f51 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 26 May 2024 15:52:05 +0100 Subject: [PATCH 29/72] check param --- .../CATHODE/CommandsPAK/Components/Entity.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 5b97d0d..c64e851 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -387,10 +387,17 @@ public ResourceReference AddResource(ResourceType type) return rr; } - /* Find a resource reference of type */ - public ResourceReference GetResource(ResourceType type) + /* Find a resource reference of type on the entity - will also check the "resource" parameter second if alsoCheckParameter is true */ + public ResourceReference GetResource(ResourceType type, bool alsoCheckParameter = false) { - return resources.FirstOrDefault(o => o.resource_type == type); + ResourceReference resource = resources.FirstOrDefault(o => o.resource_type == type); + if (alsoCheckParameter && resource == null) + { + Parameter resourceParam = GetParameter("resource"); + if (resourceParam != null && resourceParam.content != null && resourceParam.content.dataType == DataType.RESOURCE) + resource = ((cResource)resourceParam.content).GetResource(ResourceType.COLLISION_MAPPING); + } + return resource; } public override string ToString() From 24d2da8555553965e9dab89bc50b4f4ff5e58e00 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 26 May 2024 16:39:28 +0100 Subject: [PATCH 30/72] instanced position calculation --- .../CommandsPAK/Components/ShortGuid.cs | 3 ++- .../CommandsPAK/Helpers/CommandsUtils.cs | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs index 5522269..f7c7606 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs @@ -17,7 +17,8 @@ namespace CATHODE.Scripting public struct ShortGuid : IComparable { public static readonly ShortGuid Invalid = new ShortGuid(0); - public static readonly ShortGuid InitialiserBase = new ShortGuid("FE-5B-F0-4A"); + public static readonly ShortGuid InitialiserBase = new ShortGuid(1257266174); //"FE-5B-F0-4A" + public static readonly ShortGuid Max = new ShortGuid(4294967295); //"FF-FF-FF-FF" public bool IsInvalid => val == Invalid.val; diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index c32b806..38a2c2a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Text; using System.Threading.Tasks; @@ -303,6 +304,28 @@ private static void GenerateHierarchiesRecursive(Commands commands, Entity ent, }); } + /* Calculate an instanced entity's worldspace position & rotation */ + public static (Vector3, Quaternion) CalculateInstancedPosition(EntityPath hierarchy) + { + cTransform globalTransform = new cTransform(); + Composite comp = _commands.EntryPoints[0]; + for (int x = 0; x < hierarchy.path.Count; x++) + { + FunctionEntity compInst = comp.functions.FirstOrDefault(o => o.shortGUID == hierarchy.path[x]); + if (compInst == null) + break; + + Parameter positionParam = compInst.GetParameter("position"); + if (positionParam != null && positionParam.content != null && positionParam.content.dataType == DataType.TRANSFORM) + globalTransform += (cTransform)positionParam.content; + + comp = _commands.GetComposite(compInst.function); + if (comp == null) + break; + } + return (globalTransform.position, Quaternion.CreateFromYawPitchRoll(globalTransform.rotation.Y * (float)Math.PI / 180.0f, globalTransform.rotation.X * (float)Math.PI / 180.0f, globalTransform.rotation.Z * (float)Math.PI / 180.0f)); + } + /* CA's CAGE doesn't properly tidy up hierarchies pointing to deleted entities - so we can do that to save confusion */ public static void PurgeDeadLinks(Commands commands, Composite composite, bool force = false) { From 574a1c0d30c6f329e0824816e29d3623f8b13b72 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 28 May 2024 18:17:41 +0100 Subject: [PATCH 31/72] prependpath --- .../Scripts/CATHODE/CommandsPAK/Components/Entity.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index c64e851..35dabc7 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -746,6 +746,14 @@ public ShortGuid GenerateZoneID() { return new ShortGuid(0 + GenerateInstance().ToUInt32() + GetPointedEntityID().ToUInt32() + 1); } + + /* Updates this path to have the path to another entity prepended to it */ + public void PrependPath(EntityPath otherPath) + { + int length = otherPath.path[otherPath.path.Count - 1] == ShortGuid.Invalid ? otherPath.path.Count - 2 : otherPath.path.Count - 1; + for (int i = 0; i < length; i++) + path.Insert(i, otherPath.path[i]); + } } #if DEBUG From 50cf1c6ef91907e1f57bc9e9f4c9aa81e9741ab5 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 29 May 2024 18:12:01 +0100 Subject: [PATCH 32/72] handle empty path --- CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 35dabc7..afc0dae 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -595,7 +595,7 @@ public EntityPath(List _path) { path = _path; - if (path[path.Count - 1] != ShortGuid.Invalid) + if (path.Count == 0 || path[path.Count - 1] != ShortGuid.Invalid) path.Add(ShortGuid.Invalid); } public List path = new List(); From a9cd6e904f6b19316911b1e9022e4eaa4c0058d1 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 1 Jun 2024 17:56:19 +0100 Subject: [PATCH 33/72] ignore 18 empty collision mappings --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 37 ++++++++++++++++----- CathodeLib/Scripts/CATHODE/Movers.cs | 6 +++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 5b25b58..b633adb 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -24,14 +24,20 @@ override protected bool LoadInternal() { //It seems typically in this file at the start there are a bunch of empty entries, and then there are a bunch of unresolvable ones, and then a bunch that can be resolved. - //first 18 are always null? + //first 18 are always null + //always first 247 are the same? 18 null and the rest in required assets? //note: some of the things we skip here actually contain useful info, but the game doesn't read it so there's no point us bothering with it + + + + //NOTE: skipping first 18 as they're always empty, at least, for what we parse reader.BaseStream.Position = 4; int entryCount = reader.ReadInt32(); - for (int i = 0; i < entryCount; i++) + reader.BaseStream.Position += (48 * 18); + for (int i = 0; i < entryCount - 18; i++) { Entry entry = new Entry(); reader.BaseStream.Position += 8; @@ -41,10 +47,6 @@ override protected bool LoadInternal() entry.zone_id = Utilities.Consume(reader); reader.BaseStream.Position += 16; Entries.Add(entry); - - //uint test1 = entry.entity.entity_id.ToUInt32() + entry.id.ToUInt32() + entry.entity.composite_instance_id.ToUInt32() + entry.zone_id.ToUInt32(); - - //Console.WriteLine(test1 + " -> " + entry.entity.entity_id.ToUInt32() + " -> " + entry.id.ToUInt32() + " -> " + entry.entity.composite_instance_id.ToUInt32() + " -> " + entry.zone_id.ToUInt32()); } } return true; @@ -57,8 +59,11 @@ override protected bool SaveInternal() using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); - writer.Write(Entries.Count * 80); - writer.Write(Entries.Count); + writer.Write((Entries.Count + 18) * 48); + writer.Write(Entries.Count + 18); + + writer.Write(new byte[18 * 48]); + for (int i = 0; i < Entries.Count; i++) { writer.Write(new byte[8]); @@ -80,6 +85,22 @@ public class Entry public EntityHandle entity = new EntityHandle(); public ShortGuid zone_id = ShortGuid.Invalid; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering + //todo: there's also hull mappings here which the game seemingly SHOULD use, but we can rewrite without them... very weird. ignoring them for now... + + public static bool operator ==(Entry x, Entry y) + { + if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); + if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); + if (x.id != y.id) return false; + if (x.zone_id != y.zone_id) return false; + if (x.entity != y.entity) return false; + return true; + } + public static bool operator !=(Entry x, Entry y) + { + return !(x == y); + } + public override bool Equals(object obj) { return obj is Entry entry && diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index aca272d..20e0737 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -227,7 +227,11 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce //304 public UInt32 Unknowns61_; //uVar3 in reserve_light_light_master_sets, val of LightMasterSet, or an incrementer - public UInt16 Unknown17_; // TODO: It is -1 most of the time, but some times it isn't. + + + public UInt16 Unknown17_; // TODO: flags? always "65535" on BSP_LV426 1 and 2 + + //310 public UInt16 instanceTypeFlags; //ushort - used for bitwise flags depending on mover RENDERABLE_INSTANCE::Type. Environment types seem to use first bit to decide if its position comes from MVR. //312 From 8a30d26b14fbd7b9ba0a95a1cdda533deadd4cae Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 1 Jun 2024 18:44:58 +0100 Subject: [PATCH 34/72] comment --- CathodeLib/Scripts/CATHODE/Movers.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 20e0737..4d7c56c 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -32,6 +32,8 @@ public Movers(string path) : base(path) { } #region FILE_IO override protected bool LoadInternal() { + //todo: first 12 always renderable but not linked to commands -> they are always the same models + using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { reader.BaseStream.Position += 4; From 7d2cbaea3fa0c18f51dab7a9847f74f3d28d5850 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 1 Jun 2024 20:51:20 +0100 Subject: [PATCH 35/72] light stuff --- CathodeLib/Scripts/CATHODE/AlphaLightLevel.cs | 25 ++- CathodeLib/Scripts/CATHODE/Lights.cs | 152 +++++++++++------- 2 files changed, 116 insertions(+), 61 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/AlphaLightLevel.cs b/CathodeLib/Scripts/CATHODE/AlphaLightLevel.cs index e2fdf26..93b7c77 100644 --- a/CathodeLib/Scripts/CATHODE/AlphaLightLevel.cs +++ b/CathodeLib/Scripts/CATHODE/AlphaLightLevel.cs @@ -20,7 +20,19 @@ override protected bool LoadInternal() { using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { - //todo + reader.BaseStream.Position += 8; + + //NOTE: these values are always 64/128/256 i think + int count = reader.ReadInt32(); + int length = reader.ReadInt32() * 8; + + for (int i = 0; i < count; i++) + { + Entries.Add(new Entry() + { + content = reader.ReadBytes(length) + }); + } } return true; } @@ -31,8 +43,13 @@ override protected bool SaveInternal() { writer.BaseStream.SetLength(0); Utilities.WriteString("alph", writer); - - //todo + writer.Write(0); + writer.Write(Entries.Count); + writer.Write(Entries.Count); + for (int i = 0; i < Entries.Count; i++) + { + writer.Write(Entries[i].content); + } } return true; } @@ -41,7 +58,7 @@ override protected bool SaveInternal() #region STRUCTURES public class Entry { - //todo + public byte[] content; }; #endregion } diff --git a/CathodeLib/Scripts/CATHODE/Lights.cs b/CathodeLib/Scripts/CATHODE/Lights.cs index 08882de..0b0a12e 100644 --- a/CathodeLib/Scripts/CATHODE/Lights.cs +++ b/CathodeLib/Scripts/CATHODE/Lights.cs @@ -1,4 +1,4 @@ -using CathodeLib; +using CathodeLib; using System; using System.Collections.Generic; using System.IO; @@ -9,7 +9,20 @@ namespace CATHODE.EXPERIMENTAL /* DATA/ENV/PRODUCTION/x/WORLD/LIGHTS.BIN */ public class Lights : CathodeFile { - public List Entries = new List(); + //NOTE: we can read this file in/out, but we don't really know the data yet. + + public List Indexes = new List(); + public List Values = new List(); + + public int UnknownValue0; + public int UnknownValue1; + public int UnknownValue2; + public int UnknownValue3; + public int UnknownValue4; + public int UnknownValue5; + public int UnknownValue6; + public int UnknownValue7; + public static new Implementation Implementation = Implementation.NONE; public Lights(string path) : base(path) { } @@ -22,26 +35,65 @@ override protected bool LoadInternal() int entryCount = reader.ReadInt32(); for (int i = 0; i < entryCount; i++) { - Light entry = new Light(); - entry.MoverIndex = reader.ReadInt32(); - Entries.Add(entry); + Indexes.Add(reader.ReadInt32()); //I think this is MVR index } - for (int i = 0; i < entryCount; i++) + int nextCount = reader.ReadInt16(); + + //Assertions + if (nextCount != (entryCount * 2) - 1) { - //TODO: Really not sure on almost all of this structure yet - Entries[i].unk1 = reader.ReadSingle(); - Entries[i].unk2 = reader.ReadSingle(); - Entries[i].unk3 = reader.ReadSingle(); - Entries[i].unk4 = reader.ReadSingle(); - Entries[i].unk5 = reader.ReadSingle(); - Entries[i].unk6 = reader.ReadSingle(); - Entries[i].OffsetOrIndex = reader.ReadInt32(); - Entries[i].LightIndex0 = reader.ReadInt16(); - Entries[i].unk7 = reader.ReadInt16(); - Entries[i].LightIndex1 = reader.ReadInt16(); - Entries[i].unk8 = reader.ReadInt16(); + string gdsfdsf = ""; + } + + for (int i = 0; i < nextCount; i++) + { + short[] array = new short[18]; + for (int x = 0; x < 18; x++) + array[x] = reader.ReadInt16(); + Values.Add(array); + + //Assertions + if (array[17] != 0) + { + string sdsdfd = ""; + } + if (array[16] != 0 && array[16] != 1) + { + string sdsdfd = ""; + } + if (array[15] < 0) + { + string sdsdfd = ""; + } + if (array[14] < 0) + { + //i think this is an index + string sdsdfd = ""; + } + } + + //Additional unknowns + UnknownValue0 = reader.ReadChar(); + UnknownValue1 = reader.ReadInt32(); + UnknownValue2 = reader.ReadInt32(); + UnknownValue3 = reader.ReadInt32(); + UnknownValue4 = reader.ReadInt32(); + UnknownValue5 = reader.ReadInt32(); + UnknownValue6 = reader.ReadInt32(); + UnknownValue7 = reader.ReadInt16(); + + //Assertions + if (UnknownValue0 != 0 || + UnknownValue1 != 0 || + UnknownValue2 != 0 || + UnknownValue3 != 0 || + UnknownValue4 != 0 || + UnknownValue5 != 0 || + UnknownValue6 != 0 || + UnknownValue7 != 0) + { + string dfdf = ""; } - //TODO: we also leave some data behind here } return true; } @@ -50,54 +102,40 @@ override protected bool SaveInternal() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { - //writer.BaseStream.SetLength(0); + //TODO: this data is ordered by array entry -4 and then -3 i think + + writer.BaseStream.SetLength(0); Utilities.WriteString("ligt", writer); writer.Write(4); - writer.Write(Entries.Count); - for (int i = 0; i < Entries.Count; i++) - { - writer.Write((Int32)Entries[i].MoverIndex); - } - for (int i = 0; i < Entries.Count; i++) + writer.Write(Indexes.Count); + for (int i = 0; i < Indexes.Count; i++) + writer.Write(Indexes[i]); + writer.Write((Int16)Values.Count); + for (int i = 0; i < Values.Count; i++) { - writer.Write(Entries[i].unk1); - writer.Write(Entries[i].unk2); - writer.Write(Entries[i].unk3); - writer.Write(Entries[i].unk4); - writer.Write(Entries[i].unk5); - writer.Write(Entries[i].unk6); - writer.Write((Int32)Entries[i].OffsetOrIndex); - writer.Write((Int16)Entries[i].LightIndex0); - writer.Write((Int16)Entries[i].unk7); - writer.Write((Int16)Entries[i].LightIndex1); - writer.Write((Int16)Entries[i].unk8); + if (Values[i].Length != 18) + throw new Exception("Entry was of unexpected length."); + + for (int x = 0; x < Values[i].Length; x++) + writer.Write((Int16)Values[i][x]); } - //TODO: another block here i don't know - //writer.Write(new byte[27]); //it seems like you have a 27-byte buffer at the end? + + writer.Write((char)UnknownValue0); + writer.Write(UnknownValue1); + writer.Write(UnknownValue2); + writer.Write(UnknownValue3); + writer.Write(UnknownValue4); + writer.Write(UnknownValue5); + writer.Write(UnknownValue6); + writer.Write((Int16)UnknownValue7); + } return true; } #endregion #region STRUCTURES - public class Light - { - public int MoverIndex; //Index of the mover in the MODELS.MVR file - - public float unk1; - public float unk2; - public float unk3; - public float unk4; - public float unk5; - public float unk6; - - public int OffsetOrIndex; - - public int LightIndex0; - public int unk7; - public int LightIndex1; - public int unk8; - }; + #endregion } } \ No newline at end of file From bb4db1d857457c7e2892807d97d42369de250ba0 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 1 Jun 2024 21:47:40 +0100 Subject: [PATCH 36/72] env map --- CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs | 13 +++++++------ CathodeLib/Scripts/Level.cs | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs index 2fc6506..81bcd6e 100644 --- a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs +++ b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs @@ -9,10 +9,11 @@ namespace CATHODE public class EnvironmentMaps : CathodeFile { public List Entries = new List(); - public static new Implementation Implementation = Implementation.LOAD | Implementation.SAVE; + public static new Implementation Implementation = Implementation.LOAD | Implementation.SAVE | Implementation.CREATE; public EnvironmentMaps(string path) : base(path) { } - private int _unknownValue = 12; //TODO: need to figure out what this val is to be able to create file from scratch + //This is the number of environment maps in the level. We should never reference an index higher than this. + public int EnvironmentMapCount = 0; #region FILE_IO override protected bool LoadInternal() @@ -21,14 +22,14 @@ override protected bool LoadInternal() { reader.BaseStream.Position += 8; int entryCount = reader.ReadInt32(); - _unknownValue = reader.ReadInt32(); for (int i = 0; i < entryCount; i++) { Mapping entry = new Mapping(); - entry.EnvMapIndex = reader.ReadInt32(); entry.MoverIndex = reader.ReadInt32(); + entry.EnvMapIndex = reader.ReadInt32(); Entries.Add(entry); } + EnvironmentMapCount = reader.ReadInt32(); } return true; } @@ -41,12 +42,12 @@ override protected bool SaveInternal() Utilities.WriteString("envm", writer); writer.Write(1); writer.Write(Entries.Count); - writer.Write(_unknownValue); //TODO: what is this value? need to know for making new files. for (int i = 0; i < Entries.Count; i++) { - writer.Write(Entries[i].EnvMapIndex); writer.Write(Entries[i].MoverIndex); + writer.Write(Entries[i].EnvMapIndex); } + writer.Write(EnvironmentMapCount); } return true; } diff --git a/CathodeLib/Scripts/Level.cs b/CathodeLib/Scripts/Level.cs index 6af3141..1a90305 100644 --- a/CathodeLib/Scripts/Level.cs +++ b/CathodeLib/Scripts/Level.cs @@ -164,14 +164,17 @@ public void Save() /* UPDATE MOVER INDEXES */ //Get links to mover entries as actual objects + /* List lightMovers = new List(); for (int i = 0; i < Lights.Entries.Count; i++) lightMovers.Add(Movers.GetAtWriteIndex(Lights.Entries[i].MoverIndex)); + */ List envMapMovers = new List(); for (int i = 0; i < EnvironmentMaps.Entries.Count; i++) envMapMovers.Add(Movers.GetAtWriteIndex(EnvironmentMaps.Entries[i].MoverIndex)); Movers.Save(); + /* //Update mover indexes for light refs List lights = new List(); for (int i = 0; i < Lights.Entries.Count; i++) @@ -181,6 +184,7 @@ public void Save() } Lights.Entries = lights; Lights.Save(); + */ //Update mover indexes for envmap refs List envMaps = new List(); From a5091f1ebbdcf11ed05de543622164affa664201 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 1 Jun 2024 22:49:07 +0100 Subject: [PATCH 37/72] comments --- CathodeLib/Scripts/CATHODE/Movers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 4d7c56c..38eb3c1 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -38,7 +38,7 @@ override protected bool LoadInternal() { reader.BaseStream.Position += 4; int entryCount = reader.ReadInt32(); - _entryCountUnk = reader.ReadInt32(); //a count of something - not sure what + _entryCountUnk = reader.ReadInt32(); //a count of something - not sure what. not sure if it's actually used by the game reader.BaseStream.Position += 20; Entries = new List(Utilities.ConsumeArray(reader, entryCount)); } @@ -216,7 +216,7 @@ RenderableElementSet is always paired with a MOVER_DESCRIPTOR (see RenderableSce public EntityHandle entity; //The entity in the Commands file //280 - public Int32 environment_map_index; //environment_map.bin index - converted to short in code + public Int32 environment_map_index = -1; //environment_map.bin index - converted to short in code //284 public float emissive_val1; //emissive surface val1 public float emissive_val2; //emissive surface val2 From 6301fdd9230786755459edba7c0858c3ed4bc660 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 3 Jun 2024 22:14:03 +0100 Subject: [PATCH 38/72] collision map wip test --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 82 +++++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index b633adb..3c3acab 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -20,6 +20,13 @@ public CollisionMaps(string path) : base(path) { } #region FILE_IO override protected bool LoadInternal() { + int minUnk1 = 0; + int minUnk2 = 0; + int minColIn = 0; + + List flags = new List(); + Dictionary> dictest = new Dictionary>(); + using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { //It seems typically in this file at the start there are a bunch of empty entries, and then there are a bunch of unresolvable ones, and then a bunch that can be resolved. @@ -32,7 +39,6 @@ override protected bool LoadInternal() - //NOTE: skipping first 18 as they're always empty, at least, for what we parse reader.BaseStream.Position = 4; int entryCount = reader.ReadInt32(); @@ -40,15 +46,61 @@ override protected bool LoadInternal() for (int i = 0; i < entryCount - 18; i++) { Entry entry = new Entry(); - reader.BaseStream.Position += 8; + + entry.UnknownFlag = reader.ReadInt32(); //NOTE: if you filter by this value, all the UnknownIndex1s increment, UnknownIndex2s/collision_index don't increment but are grouped by -1s and non -1s, + + //todo: compare flag value across levels + + entry.UnknownIndex1= reader.ReadInt32(); entry.id = Utilities.Consume(reader); entry.entity = Utilities.Consume(reader); - reader.BaseStream.Position += 8; + entry.UnknownIndex2 = reader.ReadInt32(); + entry.collision_index = reader.ReadInt16(); + entry.UnknownValue = reader.ReadInt16(); entry.zone_id = Utilities.Consume(reader); reader.BaseStream.Position += 16; Entries.Add(entry); + + if (minUnk1 < entry.UnknownIndex1) + minUnk1 = entry.UnknownIndex1; + if (minUnk2 < entry.UnknownIndex2) + minUnk2 = entry.UnknownIndex2; + if (minColIn < entry.collision_index) + minColIn = entry.collision_index; + + if (!flags.Contains(entry.UnknownFlag)) + flags.Add(entry.UnknownFlag); + + if (entry.collision_index != -1 && entry.UnknownIndex1 == -1 && entry.UnknownIndex2 == -1 && entry.UnknownValue == -1) + { + string sdfsdf = ""; + } + + if (entry.UnknownIndex1 == -1 && entry.UnknownIndex2 == -1 && entry.UnknownValue == -1) + { + string sdfsdf = ""; + } + + string flagBin = BitConverter.ToString(BitConverter.GetBytes(entry.UnknownFlag)); + if (!dictest.ContainsKey(flagBin)) + dictest.Add(flagBin, new List()); + + dictest[flagBin].Add(entry.UnknownIndex1 + " -> " + entry.UnknownIndex2 + " -> " + entry.collision_index); + + //if (entry.UnknownFlag == -1073737335) + // Console.WriteLine(entry.UnknownIndex1); + + if (entry.UnknownFlag == 4429) + Console.WriteLine(entry.UnknownIndex1); + + //if (entry.UnknownFlag == -1073737405) + // Console.WriteLine(entry.UnknownIndex1); + + //Console.WriteLine(entry.UnknownFlag + " -> " + entry.UnknownIndex1 + " -> " + entry.UnknownIndex2 + " -> " + entry.collision_index + " -> " + entry.UnknownValue); } } + + return true; } @@ -66,10 +118,23 @@ override protected bool SaveInternal() for (int i = 0; i < Entries.Count; i++) { - writer.Write(new byte[8]); + //writer.Write(-268427008); + //writer.Write(-1); + + writer.Write(Entries[i].UnknownFlag); + writer.Write(Entries[i].UnknownIndex1); + Utilities.Write(writer, Entries[i].id); Utilities.Write(writer, Entries[i].entity); - writer.Write(new byte[8]); + + writer.Write(-1); + //writer.Write(Entries[i].UnknownIndex2); + + writer.Write((Int16)Entries[i].collision_index); + + writer.Write((short)-1); + //writer.Write((Int16)Entries[i].UnknownValue); + Utilities.Write(writer, Entries[i].zone_id); writer.Write(new byte[16]); } @@ -85,7 +150,12 @@ public class Entry public EntityHandle entity = new EntityHandle(); public ShortGuid zone_id = ShortGuid.Invalid; //this maps the entity to a zone ID. interestingly, this seems to be the point of truth for the zone rendering - //todo: there's also hull mappings here which the game seemingly SHOULD use, but we can rewrite without them... very weird. ignoring them for now... + public int collision_index = -1; //maps to havok hkx entry + + public int UnknownFlag = 0; + public int UnknownIndex1 = -1; + public int UnknownIndex2 = -1; + public int UnknownValue = -1; public static bool operator ==(Entry x, Entry y) { From 44a93275551e921c5ed82bdf5fcf9cfad3282432 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 21 Aug 2024 20:55:48 +0100 Subject: [PATCH 39/72] pushing test stuff from a while ago --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 6 +++--- CathodeLib/Scripts/CATHODE/PhysicsMaps.cs | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 3c3acab..26619ea 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -1,4 +1,4 @@ -using CATHODE.Scripting; +using CATHODE.Scripting; using CathodeLib; using System; using System.Collections.Generic; @@ -90,8 +90,8 @@ override protected bool LoadInternal() //if (entry.UnknownFlag == -1073737335) // Console.WriteLine(entry.UnknownIndex1); - if (entry.UnknownFlag == 4429) - Console.WriteLine(entry.UnknownIndex1); + //if (entry.UnknownFlag == 4429) + // Console.WriteLine(entry.UnknownIndex1); //if (entry.UnknownFlag == -1073737405) // Console.WriteLine(entry.UnknownIndex1); diff --git a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs index 256269a..56f652a 100644 --- a/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs +++ b/CathodeLib/Scripts/CATHODE/PhysicsMaps.cs @@ -72,6 +72,8 @@ override protected bool LoadInternal() override protected bool SaveInternal() { + //Entries = Entries.OrderBy(o => o.physics_system_index).ToList(); + using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); @@ -104,7 +106,7 @@ override protected bool SaveInternal() public class Entry { //Should match system_index on the PhysicsSystem entity. - public int physics_system_index; + public int physics_system_index; //TODO: is this the havok index? collision.map points to havok indexes, so would make sense //DYNAMIC_PHYSICS_SYSTEM public ShortGuid resource_type; From 1828e264ff31193e51a39c119f3c732588032674 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 21 Aug 2024 21:27:58 +0100 Subject: [PATCH 40/72] comments --- .../Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index eb7e24f..7824b41 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -893,10 +893,10 @@ public enum ResourceType { COLLISION_MAPPING, //Links to data in COLLISION.MAP DYNAMIC_PHYSICS_SYSTEM, //Links to data in PHYSICS.MAP - EXCLUSIVE_MASTER_STATE_RESOURCE, // ?? -> this seems to define some sort of change of NAV_MESH state using EXCLUSIVE_MASTER_RESOURCE_INDICES - NAV_MESH_BARRIER_RESOURCE, + EXCLUSIVE_MASTER_STATE_RESOURCE, // ?? -> this seems to define a change of STATE index somehow, linking to EXCLUSIVE_MASTER_RESOURCE_INDICES + NAV_MESH_BARRIER_RESOURCE, // ?? RENDERABLE_INSTANCE, //Links to data in REDS.BIN - TRAVERSAL_SEGMENT, + TRAVERSAL_SEGMENT, //Links to STATE_x/TRAVERSAL (according to Dan - not actually looked into it) ANIMATED_MODEL, //Links to data in ENVIRONMENT_ANIMATION.DAT // Any below this point are referenced in code, but not used in the vanilla game's CommandsPAKs From 7577707f6c1514a33f424a133fcdb26c44b85cb5 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Fri, 23 Aug 2024 13:01:23 +0100 Subject: [PATCH 41/72] traversals and some exclusive master state indexes --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 2 +- .../CommandsPAK/Components/TypeEnums.cs | 14 +-- CathodeLib/Scripts/CATHODE/Movers.cs | 3 +- .../Scripts/CATHODE/PathBarrierResources.cs | 4 +- CathodeLib/Scripts/CATHODE/Traversals.cs | 97 +++++++++++++++++++ CathodeLib/Scripts/Level.cs | 24 +++-- 6 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 CathodeLib/Scripts/CATHODE/Traversals.cs diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 26619ea..152e2c8 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -1,4 +1,4 @@ -using CATHODE.Scripting; +using CATHODE.Scripting; using CathodeLib; using System; using System.Collections.Generic; diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index 7824b41..de21a55 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -891,13 +891,13 @@ public enum FunctionType /* Resource reference types */ public enum ResourceType { - COLLISION_MAPPING, //Links to data in COLLISION.MAP - DYNAMIC_PHYSICS_SYSTEM, //Links to data in PHYSICS.MAP - EXCLUSIVE_MASTER_STATE_RESOURCE, // ?? -> this seems to define a change of STATE index somehow, linking to EXCLUSIVE_MASTER_RESOURCE_INDICES - NAV_MESH_BARRIER_RESOURCE, // ?? - RENDERABLE_INSTANCE, //Links to data in REDS.BIN - TRAVERSAL_SEGMENT, //Links to STATE_x/TRAVERSAL (according to Dan - not actually looked into it) - ANIMATED_MODEL, //Links to data in ENVIRONMENT_ANIMATION.DAT + COLLISION_MAPPING, // Links to data in COLLISION.MAP + DYNAMIC_PHYSICS_SYSTEM, // Links to data in PHYSICS.MAP + EXCLUSIVE_MASTER_STATE_RESOURCE, // Written to RESOURCES.BIN and then index referenced in EXCLUSIVE_MASTER_RESOURCE_INDICES + NAV_MESH_BARRIER_RESOURCE, // ?? -> perhaps linking to PATH_BARRIER_RESOURCES? + RENDERABLE_INSTANCE, // Links to data in REDS.BIN + TRAVERSAL_SEGMENT, // Perhaps links to STATE_x/TRAVERSAL, but we don't bother writing any entries here as it's only populated in the unused AUTOGENERATION by CAGE + ANIMATED_MODEL, // Links to data in ENVIRONMENT_ANIMATION.DAT // Any below this point are referenced in code, but not used in the vanilla game's CommandsPAKs CATHODE_COVER_SEGMENT, diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 38eb3c1..7dd0a94 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -32,7 +32,7 @@ public Movers(string path) : base(path) { } #region FILE_IO override protected bool LoadInternal() { - //todo: first 12 always renderable but not linked to commands -> they are always the same models + //note: first 12 always renderable but not linked to commands -> they are always the same models across every level using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { @@ -42,6 +42,7 @@ override protected bool LoadInternal() reader.BaseStream.Position += 20; Entries = new List(Utilities.ConsumeArray(reader, entryCount)); } + _writeList.AddRange(Entries); return true; } diff --git a/CathodeLib/Scripts/CATHODE/PathBarrierResources.cs b/CathodeLib/Scripts/CATHODE/PathBarrierResources.cs index 1e07ff4..fc5a888 100644 --- a/CathodeLib/Scripts/CATHODE/PathBarrierResources.cs +++ b/CathodeLib/Scripts/CATHODE/PathBarrierResources.cs @@ -45,7 +45,7 @@ override protected bool SaveInternal() { reader.Write((Int32)Entries[i].resourcesBinIndex); reader.Write((Int32)(i + 1)); - reader.Write((Int16)Entries[i].unk1); + reader.Write((Int16)Entries[i].unk1); reader.Write((Int16)Entries[i].unk2); } } @@ -57,7 +57,7 @@ override protected bool SaveInternal() public class Entry { public int resourcesBinIndex; - public int unk1; + public int unk1; //todo: perhaps this is a ShortGuid instance thing? public int unk2; } #endregion diff --git a/CathodeLib/Scripts/CATHODE/Traversals.cs b/CathodeLib/Scripts/CATHODE/Traversals.cs new file mode 100644 index 0000000..7000b7c --- /dev/null +++ b/CathodeLib/Scripts/CATHODE/Traversals.cs @@ -0,0 +1,97 @@ +using CATHODE.Scripting; +using CathodeLib; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +#if UNITY_EDITOR || UNITY_STANDALONE_WIN +using UnityEngine; +#else +using System.Numerics; +using System.Runtime.InteropServices; +#endif + +namespace CATHODE.EXPERIMENTAL +{ + /* DATA/ENV/PRODUCTION/x/WORLD/COLLISION.BIN */ + public class Traversals : CathodeFile + { + //NOTE: Not bothering finishing reversing this one as it's not actually used. + // The TRAVERSAL file is only populated in the AUTOGENERATION folder which isn't used by the game at runtime. + // Have included write support though to write the empty file. + + /*public*/ private List Entries = new List(); + public static new Implementation Implementation = Implementation.SAVE; + public Traversals(string path) : base(path) { } + + private char[] _magic = new char[4] { 't', 'r', 'a', 'v' }; + private int _version = 2; + + #region FILE_IO + override protected bool LoadInternal() + { + using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) + { + char[] magic = reader.ReadChars(4); + if (!magic.SequenceEqual(_magic)) throw new Exception(); + int version = reader.ReadInt32(); + if (version != _version) throw new Exception(); + + int entryCount = reader.ReadInt16(); + for (int i = 0; i < entryCount; i++) + { + Entries.Add(Utilities.Consume(reader)); + } + + //note: there is more data left behind here. + } + return true; + } + + override protected bool SaveInternal() + { + using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) + { + writer.BaseStream.SetLength(0); + writer.Write(_magic); + writer.Write(_version); + + /* + writer.Write((Int16)Entries.Count); + for (int i = 0; i < Entries.Count; i++) + { + + } + */ + + writer.Write((Int16)0); + writer.Write((Int16)1); + writer.Write((Int16)1); + writer.Write((Int16)0); + writer.Write((Int16)0); + writer.Write((Int16)0); + writer.Write((Int16)0); + writer.Write((Int16)0); + writer.Write(16256); + } + return true; + } + #endregion + + #region STRUCTURES + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public class Entry + { + public short EntryIndex; + public int UnknownID; // NOTE: It is the same value for all entries in 'sci_hub'. Only seen in this file. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] Unknowns_; //5 + public ShortGuid NodeID; // NOTE: This is found in 'commands.pak' and it is a "Traversal" node for the Alien indicates animation. + // Seen in 'resources.bin', 'nav_mesh', 'traversal' and 'commands.pak'. + public ShortGuid ResourcesBINID; // NOTE: Seen in 'resources.bin', 'nav_mesh', 'traversal'. MATT: is this instance id? + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public Vector3[] Ps; //20 + }; + #endregion + } +} \ No newline at end of file diff --git a/CathodeLib/Scripts/Level.cs b/CathodeLib/Scripts/Level.cs index 1a90305..7a5a88c 100644 --- a/CathodeLib/Scripts/Level.cs +++ b/CathodeLib/Scripts/Level.cs @@ -52,6 +52,7 @@ public class State { public int Index; public NavigationMesh NavMesh; + public Traversals Traversals; } public List StateResources = new List(); @@ -81,7 +82,7 @@ public Level(string path, Global global) RenderableElements = new RenderableElements(path + "/WORLD/REDS.BIN"); Movers = new Movers(path + "/WORLD/MODELS.MVR"); Commands = new Commands(path + "/WORLD/COMMANDS.PAK"); - //Resources = new Resources(path + "/WORLD/RESOURCES.BIN"); + Resources = new Resources(path + "/WORLD/RESOURCES.BIN"); //PhysicsMaps = new PhysicsMaps(path + "/WORLD/PHYSICS.MAP"); EnvironmentMaps = new EnvironmentMaps(path + "/WORLD/ENVIRONMENTMAP.BIN"); //CollisionMaps = new CollisionMaps(path + "/WORLD/COLLISION.MAP"); @@ -104,24 +105,31 @@ public Level(string path, Global global) // - SND NETWORK FILES /* WORLD STATE RESOURCES */ - int stateCount = 1; + int stateCount = 1; // we always implicitly have one state (the default state: state zero) using (BinaryReader reader = new BinaryReader(File.OpenRead(path + "/WORLD/EXCLUSIVE_MASTER_RESOURCE_INDICES"))) { - reader.BaseStream.Position = 4; - stateCount += reader.ReadInt32(); - //TODO: this file also contains indices for each state which seem to be of some relevence, although EXCLUSIVE_MASTER_RESOURCE doesn't point to indices? + reader.BaseStream.Position = 4; // version: 1 + int states = reader.ReadInt32(); // number of changeable states + stateCount += states; + for (int x = 0; x < states; x++) + { + int resourceIndex = reader.ReadInt32(); + Resources.Resource resource = Resources.Entries[resourceIndex]; //TODO: this gives you the instance of the ExclusiveMaster entity - use it + } } for (int i = 0; i < stateCount; i++) { + string statePath = path + "/WORLD/STATE_" + i + "/"; + State state = new State() { Index = i }; - state.NavMesh = new NavigationMesh(path + "/WORLD/STATE_" + i + "/NAV_MESH"); + state.NavMesh = new NavigationMesh(statePath + "NAV_MESH"); + state.Traversals = new Traversals(statePath + "TRAVERSAL"); // WORLD STATE RESOURCES TODO: // - ASSAULT_POSITIONS // - COVER // - CRAWL_SPACE_SPOTTING_POSITIONS // - SPOTTING_POSITIONS - // - TRAVERSAL } /* TEXT */ @@ -312,7 +320,7 @@ public static List GetLevels(string gameDirectory, bool swapNostromoForP string mapName = file.Substring(0, length); if (swapNostromoForPatch && (mapName == "DLC/BSPNOSTROMO_RIPLEY" || mapName == "DLC/BSPNOSTROMO_TWOTEAMS")) mapName += "_PATCH"; - mapList.Add(mapName); + mapList.Add(mapName.ToUpper()); } return mapList; } From d8efacfaf351a8bc28b609f923a1dfd1facf85f2 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Fri, 23 Aug 2024 16:30:04 +0100 Subject: [PATCH 42/72] remove obsolete flags on shortguid to reduce warnings --- .../Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs index f7c7606..8b45e62 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/ShortGuid.cs @@ -37,13 +37,11 @@ public ShortGuid(uint num) val = num; } - [Obsolete("For performance reasons, it is recommended to initialse ShortGuid as an unsigned integer.")] public ShortGuid(byte[] id) { val = BitConverter.ToUInt32(id, 0); } - [Obsolete("For performance reasons, it is recommended to initialse ShortGuid as an unsigned integer.")] public ShortGuid(string id) { System.String[] arr = id.Split('-'); @@ -68,13 +66,11 @@ public override bool Equals(object obj) return !(x.val == y.val); } - [Obsolete("For performance reasons, it is recommended to compare as ShortGuid or integer.")] public static bool operator ==(ShortGuid x, string y) { return x.ToByteString() == y; } - [Obsolete("For performance reasons, it is recommended to compare as ShortGuid or integer.")] public static bool operator !=(ShortGuid x, string y) { return x.ToByteString() != y; @@ -115,13 +111,11 @@ public uint ToUInt32() return val; } - [Obsolete("For performance reasons, it is recommended to use ToUInt32.")] public string ToByteString() { return BitConverter.ToString(BitConverter.GetBytes(val)); } - [Obsolete("For performance reasons, it is recommended to use ToUInt32.")] public byte[] ToBytes() { return BitConverter.GetBytes(val); From d32ab2f583673faaf35473ae68d00747d60b442e Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Thu, 12 Sep 2024 19:17:01 +0100 Subject: [PATCH 43/72] HasLinks --- .../CATHODE/CommandsPAK/Components/Entity.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index afc0dae..c96b9d2 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -230,6 +230,24 @@ public List GetParentLinks(Composite containedComposite) return connections; } + /* Utility: Returns true if this entity has any links IN or OUT (pass in the composite this entity is within) */ + public bool HasLinks(Composite containedComposite) + { + if (childLinks.Count != 0) + return true; + + List entities = containedComposite.GetEntities(); + for (int i = 0; i < entities.Count; i++) + { + for (int x = 0; x < entities[i].childLinks.Count; x++) + { + if (entities[i].childLinks[x].linkedEntityID == shortGUID) + return true; + } + } + return false; + } + /* Utility: Remove all child links out from the given parameter */ public void RemoveAllParameterLinksOut(string parameter) { From 8165c9216729d6b40bb9c19493510a318a00c248 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 21 Sep 2024 13:04:57 +0100 Subject: [PATCH 44/72] add new tables --- .../CommandsPAK/Components/TypeEnums.cs | 2 + .../CommandsPAK/Helpers/CustomTable.cs | 192 +++++++++++++++++- 2 files changed, 193 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index de21a55..34c7d47 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -1106,6 +1106,8 @@ public enum CustomEndTables ENTITY_NAMES, SHORT_GUIDS, COMPOSITE_PURGE_STATES, + COMPOSITE_MODIFICATION_INFO, + COMPOSITE_FLOWGRAPHS, //Add new entries here diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index 064323a..fc333ba 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -2,8 +2,8 @@ using CATHODE.Scripting.Internal; using System; using System.Collections.Generic; +using System.Drawing; using System.IO; -using System.Text; namespace CathodeLib { @@ -63,6 +63,12 @@ public static void WriteTable(string filepath, CustomEndTables table, Table cont case CustomEndTables.COMPOSITE_PURGE_STATES: ((CompositePurgeTable)toWrite[tableType]).Write(writer); break; + case CustomEndTables.COMPOSITE_MODIFICATION_INFO: + ((CompositeModificationInfoTable)toWrite[tableType]).Write(writer); + break; + case CustomEndTables.COMPOSITE_FLOWGRAPHS: + ((CompositeFlowgraphsTable)toWrite[tableType]).Write(writer); + break; } } } @@ -109,6 +115,12 @@ public static Table ReadTable(string filepath, CustomEndTables table) case CustomEndTables.COMPOSITE_PURGE_STATES: data = new CompositePurgeTable(reader); break; + case CustomEndTables.COMPOSITE_MODIFICATION_INFO: + data = new CompositeModificationInfoTable(reader); + break; + case CustomEndTables.COMPOSITE_FLOWGRAPHS: + data = new CompositeFlowgraphsTable(reader); + break; } } return data; @@ -269,4 +281,182 @@ public override void Write(BinaryWriter writer) } } } + public class CompositeModificationInfoTable : CustomTable.Table + { + public CompositeModificationInfoTable(BinaryReader reader = null) : base(reader) + { + type = CustomEndTables.COMPOSITE_MODIFICATION_INFO; + } + + public List modification_info; + + protected override void Read(BinaryReader reader) + { + if (reader == null) + { + modification_info = new List(); + return; + } + + int count = reader.ReadInt32(); + modification_info = new List(count); + for (int i = 0; i < count; i++) + { + ModificationInfo info = new ModificationInfo(); + info.composite_id = Utilities.Consume(reader); + info.script_editor_version = reader.ReadInt32(); + info.modification_date = reader.ReadInt32(); + modification_info.Add(info); + } + } + + public override void Write(BinaryWriter writer) + { + writer.Write(modification_info.Count); + for (int i = 0; i < modification_info.Count; i++) + { + Utilities.Write(writer, modification_info[i].composite_id); + writer.Write(modification_info[i].script_editor_version); + writer.Write(modification_info[i].modification_date); + } + } + + public class ModificationInfo + { + public ShortGuid composite_id; + public int script_editor_version; + public int modification_date; //unix timecode + } + } + public class CompositeFlowgraphsTable : CustomTable.Table //NOTE TO SELF: use this same class for reading/writing the default data stored in the script editor + { + public CompositeFlowgraphsTable(BinaryReader reader = null) : base(reader) + { + type = CustomEndTables.COMPOSITE_FLOWGRAPHS; + } + + public List flowgraphs; + + protected override void Read(BinaryReader reader) + { + if (reader == null) + { + flowgraphs = new List(); + return; + } + + int count = reader.ReadInt32(); + for (int i = 0; i < count; i++) + { + FlowgraphMeta flowgraph = new FlowgraphMeta(); + + flowgraph.CompositeGUID = Utilities.Consume(reader); + flowgraph.Name = reader.ReadString(); + + flowgraph.CanvasPosition = new PointF(reader.ReadSingle(), reader.ReadSingle()); + flowgraph.CanvasScale = reader.ReadSingle(); + + reader.BaseStream.Position += 10; //reserved + + int nodeMetaCount = reader.ReadInt32(); + for (int x = 0; x < nodeMetaCount; x++) + { + FlowgraphMeta.NodeMeta node = new FlowgraphMeta.NodeMeta(); + node.EntityGUID = Utilities.Consume(reader); + + node.Position = new Point(reader.ReadInt32(), reader.ReadInt32()); + + int inCount = reader.ReadInt32(); + for (int z = 0; z < inCount; z++) + { + FlowgraphMeta.NodeMeta.ConnectionMeta connection = new FlowgraphMeta.NodeMeta.ConnectionMeta(); + connection.ParameterGUID = Utilities.Consume(reader); + connection.ConnectedEntityGUID = Utilities.Consume(reader); + connection.ConnectedParameterGUID = Utilities.Consume(reader); + node.ConnectionsIn.Add(connection); + } + int outCount = reader.ReadInt32(); + for (int z = 0; z < outCount; z++) + { + FlowgraphMeta.NodeMeta.ConnectionMeta connection = new FlowgraphMeta.NodeMeta.ConnectionMeta(); + connection.ParameterGUID = Utilities.Consume(reader); + connection.ConnectedEntityGUID = Utilities.Consume(reader); + connection.ConnectedParameterGUID = Utilities.Consume(reader); + node.ConnectionsOut.Add(connection); + } + + flowgraph.Nodes.Add(node); + } + flowgraphs.Add(flowgraph); + } + } + + public override void Write(BinaryWriter writer) + { + writer.Write(flowgraphs.Count); + for (int i = 0; i < flowgraphs.Count; i++) + { + Utilities.Write(writer, flowgraphs[i].CompositeGUID); + writer.Write(flowgraphs[i].Name); + + writer.Write(flowgraphs[i].CanvasPosition.X); + writer.Write(flowgraphs[i].CanvasPosition.Y); + writer.Write(flowgraphs[i].CanvasScale); + + writer.Write(new byte[10]); //reserved + + writer.Write(flowgraphs[i].Nodes.Count); + for (int x = 0; x < flowgraphs[i].Nodes.Count; x++) + { + Utilities.Write(writer, flowgraphs[i].Nodes[x].EntityGUID); + + writer.Write(flowgraphs[i].Nodes[x].Position.X); + writer.Write(flowgraphs[i].Nodes[x].Position.Y); + + writer.Write(flowgraphs[i].Nodes[x].ConnectionsIn.Count); + for (int z = 0; z < flowgraphs[i].Nodes[x].ConnectionsIn.Count; z++) + { + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ParameterGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ConnectedEntityGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ConnectedParameterGUID); + } + writer.Write(flowgraphs[i].Nodes[x].ConnectionsOut.Count); + for (int z = 0; z < flowgraphs[i].Nodes[x].ConnectionsOut.Count; z++) + { + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ParameterGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ConnectedEntityGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ConnectedParameterGUID); + } + } + } + } + + public class FlowgraphMeta + { + public ShortGuid CompositeGUID; + public string Name; + + public List Nodes = new List(); + + public PointF CanvasPosition; + public float CanvasScale; + + public class NodeMeta + { + public ShortGuid EntityGUID; + + public Point Position; + + public List ConnectionsIn = new List(); + public List ConnectionsOut = new List(); + + public class ConnectionMeta + { + public ShortGuid ParameterGUID; + public ShortGuid ConnectedEntityGUID; + public ShortGuid ConnectedParameterGUID; + } + } + } + } } From 79d3cbc714aeba042fc26c6f9fb211cae46664a6 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 21 Sep 2024 18:27:37 +0100 Subject: [PATCH 45/72] expose read --- .../CATHODE/CommandsPAK/Helpers/CustomTable.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index fc333ba..f9298e7 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -143,7 +143,7 @@ public Table(BinaryReader reader) public CustomEndTables type = CustomEndTables.NUMBER_OF_END_TABLES; - protected virtual void Read(BinaryReader reader) + public virtual void Read(BinaryReader reader) { } @@ -164,7 +164,7 @@ public EntityNameTable(BinaryReader reader = null) : base(reader) public Dictionary> names; - protected override void Read(BinaryReader reader) + public override void Read(BinaryReader reader) { if (reader == null) { @@ -212,7 +212,7 @@ public GuidNameTable(BinaryReader reader = null) : base(reader) public Dictionary cache; public Dictionary cacheReversed; - protected override void Read(BinaryReader reader) + public override void Read(BinaryReader reader) { if (reader == null) { @@ -255,7 +255,7 @@ public CompositePurgeTable(BinaryReader reader = null) : base(reader) public List purged; - protected override void Read(BinaryReader reader) + public override void Read(BinaryReader reader) { if (reader == null) { @@ -290,7 +290,7 @@ public CompositeModificationInfoTable(BinaryReader reader = null) : base(reader) public List modification_info; - protected override void Read(BinaryReader reader) + public override void Read(BinaryReader reader) { if (reader == null) { @@ -337,7 +337,7 @@ public CompositeFlowgraphsTable(BinaryReader reader = null) : base(reader) public List flowgraphs; - protected override void Read(BinaryReader reader) + public override void Read(BinaryReader reader) { if (reader == null) { @@ -436,11 +436,11 @@ public class FlowgraphMeta public ShortGuid CompositeGUID; public string Name; - public List Nodes = new List(); - public PointF CanvasPosition; public float CanvasScale; + public List Nodes = new List(); + public class NodeMeta { public ShortGuid EntityGUID; From b106b422afc6145a722082c3f25794094237ed79 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 22 Sep 2024 15:58:24 +0100 Subject: [PATCH 46/72] modification info --- .../CommandsPAK/Helpers/CompositeUtils.cs | 94 +++++++++++++++++-- .../CommandsPAK/Helpers/CustomTable.cs | 6 +- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs index af5d0c9..a6d21a3 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs @@ -1,7 +1,13 @@ -using CATHODE.Scripting; +using CATHODE; +using CATHODE.Scripting; +using CATHODE.Scripting.Internal; using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Json; +using System.Security.Cryptography; using System.Text; #if UNITY_EDITOR || UNITY_STANDALONE using UnityEngine; @@ -9,10 +15,16 @@ namespace CathodeLib { - //Has a store of all composite paths in the vanilla game: used for prettifying the all-caps Windows strings public static class CompositeUtils { - private static Dictionary pathLookup; + //Has a store of all composite paths in the vanilla game: can be used for prettifying the all-caps Windows strings + private static Dictionary _pathLookup; + + //Has a store of Composite modification info for the currently linked Commands + private static CompositeModificationInfoTable _modificationInfo; + + public static Commands LinkedCommands => _commands; + private static Commands _commands; static CompositeUtils() { @@ -22,16 +34,50 @@ static CompositeUtils() BinaryReader reader = new BinaryReader(new MemoryStream(CathodeLib.Properties.Resources.composite_paths)); #endif int compositeCount = reader.ReadInt32(); - pathLookup = new Dictionary(compositeCount); + _pathLookup = new Dictionary(compositeCount); for (int i = 0; i < compositeCount; i++) - pathLookup.Add(Utilities.Consume(reader), reader.ReadString()); + _pathLookup.Add(Utilities.Consume(reader), reader.ReadString()); + + _modificationInfo = new CompositeModificationInfoTable(); + } + + public static void LinkCommands(Commands commands) + { + if (_commands != null) + { + _commands.OnLoadSuccess -= LoadModificationInfo; + _commands.OnSaveSuccess -= SaveModificationInfo; + } + + _commands = commands; + if (_commands == null) return; + + _commands.OnLoadSuccess += LoadModificationInfo; + _commands.OnSaveSuccess += SaveModificationInfo; + + LoadModificationInfo(_commands.Filepath); + } + + private static void LoadModificationInfo(string filepath) + { + _modificationInfo = (CompositeModificationInfoTable)CustomTable.ReadTable(filepath, CustomEndTables.COMPOSITE_MODIFICATION_INFO); + if (_modificationInfo == null) _modificationInfo = new CompositeModificationInfoTable(); + Console.WriteLine("Loaded modification info for " + _modificationInfo.modification_info.Count + " composites!"); + } + + private static void SaveModificationInfo(string filepath) + { + CustomTable.WriteTable(filepath, CustomEndTables.COMPOSITE_MODIFICATION_INFO, _modificationInfo); + Console.WriteLine("Saved modification info for " + _modificationInfo.modification_info.Count + " composites!"); } + /* Gets a pretty Composite name */ public static string GetFullPath(ShortGuid guid) { - return pathLookup.ContainsKey(guid) ? pathLookup[guid] : ""; + return _pathLookup.ContainsKey(guid) ? _pathLookup[guid] : ""; } + /* Gets a pretty Composite name, including trimming direct paths */ public static string GetPrettyPath(ShortGuid guid) { string fullPath = GetFullPath(guid); @@ -46,5 +92,41 @@ public static string GetPrettyPath(ShortGuid guid) } return fullPath; } + + /* Set/update the modification metadata for a composite */ + public static void SetModificationInfo(CompositeModificationInfoTable.ModificationInfo info) + { + _modificationInfo.modification_info.RemoveAll(o => o.composite_id == info.composite_id); + _modificationInfo.modification_info.Add(info); + } + + /* Get the modification metadata for a composite (if it exists) */ + public static CompositeModificationInfoTable.ModificationInfo GetModificationInfo(Composite composite) + { + return _modificationInfo.modification_info.FirstOrDefault(o => o.composite_id == composite.shortGUID); + } + + /* Generate a checksum for a Composite object */ + public static byte[] GenerateChecksum(Composite composite) + { + int size = Marshal.SizeOf(composite); + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(composite, ptr, true); + Marshal.Copy(ptr, arr, 0, size); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + + using (SHA256 sha256 = SHA256.Create()) + { + byte[] hash = sha256.ComputeHash(arr); + return hash; + } + } } } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index f9298e7..8a68f6f 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -304,7 +304,7 @@ public override void Read(BinaryReader reader) { ModificationInfo info = new ModificationInfo(); info.composite_id = Utilities.Consume(reader); - info.script_editor_version = reader.ReadInt32(); + info.editor_version = reader.ReadInt32(); info.modification_date = reader.ReadInt32(); modification_info.Add(info); } @@ -316,7 +316,7 @@ public override void Write(BinaryWriter writer) for (int i = 0; i < modification_info.Count; i++) { Utilities.Write(writer, modification_info[i].composite_id); - writer.Write(modification_info[i].script_editor_version); + writer.Write(modification_info[i].editor_version); writer.Write(modification_info[i].modification_date); } } @@ -324,7 +324,7 @@ public override void Write(BinaryWriter writer) public class ModificationInfo { public ShortGuid composite_id; - public int script_editor_version; + public int editor_version; //use this to store a unique identifier for whatever tool version modified the composite public int modification_date; //unix timecode } } From 65c8506997e2e08c36fb589ab930f2a22d1af70c Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 28 Sep 2024 09:48:41 +0100 Subject: [PATCH 47/72] GetContainedComposite --- .../CATHODE/CommandsPAK/Components/Entity.cs | 17 ++++++ .../CommandsPAK/Helpers/CommandsUtils.cs | 55 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index c96b9d2..293c5fd 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -185,6 +185,11 @@ public Parameter AddParameter(ShortGuid id, ParameterData data, ParameterVariant } return param; } + public Parameter AddParameter(Parameter param) + { + parameters.Add(param); + return param; + } /* Remove a parameter from the entity */ public void RemoveParameter(string name) @@ -192,12 +197,20 @@ public void RemoveParameter(string name) ShortGuid name_id = ShortGuidUtils.Generate(name); parameters.RemoveAll(o => o.name == name_id); } + public void RemoveParameter(Parameter param) + { + parameters.RemoveAll(o => o == param); + } /* Add a link from a parameter on us out to a parameter on another entity */ public void AddParameterLink(string parameter, Entity childEntity, string childParameter) { childLinks.Add(new EntityConnector(childEntity.shortGUID, ShortGuidUtils.Generate(parameter), ShortGuidUtils.Generate(childParameter))); } + public void AddParameterLink(Parameter parameter, Entity childEntity, Parameter childParameter) + { + childLinks.Add(new EntityConnector(childEntity.shortGUID, parameter.name, childParameter.name)); + } /* Remove a link to another entity */ public void RemoveParameterLink(string parameter, Entity childEntity, string childParameter) @@ -207,6 +220,10 @@ public void RemoveParameterLink(string parameter, Entity childEntity, string chi //TODO: do we want to do RemoveAll? should probably just remove the first childLinks.RemoveAll(o => o.thisParamID == parameter_id && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameter_id); } + public void RemoveParameterLink(Parameter parameter, Entity childEntity, Parameter childParameter) + { + childLinks.RemoveAll(o => o.thisParamID == parameter.name && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameter.name); + } /* Utility: Find all links in to this entity (pass in the composite this entity is within) */ public List GetParentLinks(Composite containedComposite) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 38a2c2a..ebdf6e5 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -62,6 +62,61 @@ private static void SavePurgeStates(string filepath) Console.WriteLine("Stored " + _purged.purged.Count + " pre-purged composites!"); } + /* Gets the composite that contains the entity */ + public static Composite GetContainedComposite(this Entity entity) + { + if (_commands == null) + throw (new Exception("Please link your Commands object to CommandsUtils using CommandsUtils.LinkCommands before calling this function")); + + for (int i = 0; i < _commands.Entries.Count; i++) + { + switch (entity.variant) + { + case EntityVariant.FUNCTION: + for (int x = 0; x < _commands.Entries[i].functions.Count; x++) + { + if (_commands.Entries[i].functions[x].shortGUID == entity.shortGUID) + { + if (_commands.Entries[i].functions[x] == entity) + return _commands.Entries[i]; + } + } + break; + case EntityVariant.VARIABLE: + for (int x = 0; x < _commands.Entries[i].variables.Count; x++) + { + if (_commands.Entries[i].variables[x].shortGUID == entity.shortGUID) + { + if (_commands.Entries[i].variables[x] == entity) + return _commands.Entries[i]; + } + } + break; + case EntityVariant.PROXY: + for (int x = 0; x < _commands.Entries[i].proxies.Count; x++) + { + if (_commands.Entries[i].proxies[x].shortGUID == entity.shortGUID) + { + if (_commands.Entries[i].proxies[x] == entity) + return _commands.Entries[i]; + } + } + break; + case EntityVariant.ALIAS: + for (int x = 0; x < _commands.Entries[i].aliases.Count; x++) + { + if (_commands.Entries[i].aliases[x].shortGUID == entity.shortGUID) + { + if (_commands.Entries[i].aliases[x] == entity) + return _commands.Entries[i]; + } + } + break; + } + } + return null; + } + #region FUNCTION_TYPE_UTILS /* Function Types */ private static Dictionary _functionTypeLUT = new Dictionary(); From 6aa5c6c77bbb139214d054ee6d929ef01f128407 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 28 Sep 2024 10:54:57 +0100 Subject: [PATCH 48/72] updated flowgraph table structure --- .../CommandsPAK/Helpers/CustomTable.cs | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index 8a68f6f..ac4a490 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; namespace CathodeLib { @@ -345,6 +346,12 @@ public override void Read(BinaryReader reader) return; } + byte version = reader.ReadByte(); + if (version != FlowgraphMeta.VERSION) + { + //Add compatibility here when required + } + int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { @@ -367,22 +374,18 @@ public override void Read(BinaryReader reader) node.Position = new Point(reader.ReadInt32(), reader.ReadInt32()); int inCount = reader.ReadInt32(); - for (int z = 0; z < inCount; z++) - { - FlowgraphMeta.NodeMeta.ConnectionMeta connection = new FlowgraphMeta.NodeMeta.ConnectionMeta(); - connection.ParameterGUID = Utilities.Consume(reader); - connection.ConnectedEntityGUID = Utilities.Consume(reader); - connection.ConnectedParameterGUID = Utilities.Consume(reader); - node.ConnectionsIn.Add(connection); - } + node.PinsIn = Utilities.ConsumeArray(reader, inCount).ToList(); int outCount = reader.ReadInt32(); - for (int z = 0; z < outCount; z++) + node.PinsOut = Utilities.ConsumeArray(reader, outCount).ToList(); + + int connectionCount = reader.ReadInt32(); + for (int z = 0; z < connectionCount; z++) { FlowgraphMeta.NodeMeta.ConnectionMeta connection = new FlowgraphMeta.NodeMeta.ConnectionMeta(); connection.ParameterGUID = Utilities.Consume(reader); connection.ConnectedEntityGUID = Utilities.Consume(reader); connection.ConnectedParameterGUID = Utilities.Consume(reader); - node.ConnectionsOut.Add(connection); + node.Connections.Add(connection); } flowgraph.Nodes.Add(node); @@ -393,6 +396,7 @@ public override void Read(BinaryReader reader) public override void Write(BinaryWriter writer) { + writer.Write(FlowgraphMeta.VERSION); writer.Write(flowgraphs.Count); for (int i = 0; i < flowgraphs.Count; i++) { @@ -413,19 +417,17 @@ public override void Write(BinaryWriter writer) writer.Write(flowgraphs[i].Nodes[x].Position.X); writer.Write(flowgraphs[i].Nodes[x].Position.Y); - writer.Write(flowgraphs[i].Nodes[x].ConnectionsIn.Count); - for (int z = 0; z < flowgraphs[i].Nodes[x].ConnectionsIn.Count; z++) - { - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ParameterGUID); - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ConnectedEntityGUID); - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsIn[z].ConnectedParameterGUID); - } - writer.Write(flowgraphs[i].Nodes[x].ConnectionsOut.Count); - for (int z = 0; z < flowgraphs[i].Nodes[x].ConnectionsOut.Count; z++) + writer.Write(flowgraphs[i].Nodes[x].PinsIn.Count); + Utilities.Write(writer, flowgraphs[i].Nodes[x].PinsIn); + writer.Write(flowgraphs[i].Nodes[x].PinsOut.Count); + Utilities.Write(writer, flowgraphs[i].Nodes[x].PinsOut); + + writer.Write(flowgraphs[i].Nodes[x].Connections.Count); + for (int z = 0; z < flowgraphs[i].Nodes[x].Connections.Count; z++) { - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ParameterGUID); - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ConnectedEntityGUID); - Utilities.Write(writer, flowgraphs[i].Nodes[x].ConnectionsOut[z].ConnectedParameterGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ParameterGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ConnectedEntityGUID); + Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ConnectedParameterGUID); } } } @@ -433,6 +435,8 @@ public override void Write(BinaryWriter writer) public class FlowgraphMeta { + public const byte VERSION = 1; + public ShortGuid CompositeGUID; public string Name; @@ -444,17 +448,21 @@ public class FlowgraphMeta public class NodeMeta { public ShortGuid EntityGUID; + public int NodeID; public Point Position; - public List ConnectionsIn = new List(); - public List ConnectionsOut = new List(); + public List PinsIn = new List(); + public List PinsOut = new List(); + + public List Connections = new List(); //NOTE: This is connections OUT of this node public class ConnectionMeta { public ShortGuid ParameterGUID; public ShortGuid ConnectedEntityGUID; public ShortGuid ConnectedParameterGUID; + public int ConnectedNodeID; } } } From da16a1e777cb437bc1fec4e99b1ce7e1d791e477 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 28 Sep 2024 11:44:38 +0100 Subject: [PATCH 49/72] equals connector --- .../CATHODE/CommandsPAK/Components/Entity.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 293c5fd..d36f624 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -613,6 +613,38 @@ public Entity GetEntity(Composite comp) { return comp.GetEntityByID(linkedEntityID); } + + public override bool Equals(object obj) + { + return obj is EntityConnector connector && + EqualityComparer.Default.Equals(ID, connector.ID) && + EqualityComparer.Default.Equals(thisParamID, connector.thisParamID) && + EqualityComparer.Default.Equals(linkedParamID, connector.linkedParamID) && + EqualityComparer.Default.Equals(linkedEntityID, connector.linkedEntityID); + } + + public override int GetHashCode() + { + int hashCode = -1516234163; + hashCode = hashCode * -1521134295 + ID.GetHashCode(); + hashCode = hashCode * -1521134295 + thisParamID.GetHashCode(); + hashCode = hashCode * -1521134295 + linkedParamID.GetHashCode(); + hashCode = hashCode * -1521134295 + linkedEntityID.GetHashCode(); + return hashCode; + } + + public static bool operator ==(EntityConnector x, EntityConnector y) + { + if (x.ID != y.ID) return false; + if (x.thisParamID != y.thisParamID) return false; + if (x.linkedParamID != y.linkedParamID) return false; + if (x.linkedEntityID != y.linkedEntityID) return false; + return true; + } + public static bool operator !=(EntityConnector x, EntityConnector y) + { + return !(x == y); + } } /// From fb3570413f3dfd1c6b402d2a32f64a76c7157f69 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 28 Sep 2024 13:21:13 +0100 Subject: [PATCH 50/72] table fix --- .../CATHODE/CommandsPAK/Components/Entity.cs | 16 ++++++++++++++++ .../CATHODE/CommandsPAK/Helpers/CustomTable.cs | 12 ++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index d36f624..dce84e3 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -211,6 +211,14 @@ public void AddParameterLink(Parameter parameter, Entity childEntity, Parameter { childLinks.Add(new EntityConnector(childEntity.shortGUID, parameter.name, childParameter.name)); } + public void AddParameterLink(ShortGuid parameterGUID, Entity childEntity, ShortGuid childParameterGUID) + { + childLinks.Add(new EntityConnector(childEntity.shortGUID, parameterGUID, childParameterGUID)); + } + public void AddParameterLink(ShortGuid parameterGUID, ShortGuid childEntityGUID, ShortGuid childParameterGUID) + { + childLinks.Add(new EntityConnector(childEntityGUID, parameterGUID, childParameterGUID)); + } /* Remove a link to another entity */ public void RemoveParameterLink(string parameter, Entity childEntity, string childParameter) @@ -224,6 +232,14 @@ public void RemoveParameterLink(Parameter parameter, Entity childEntity, Paramet { childLinks.RemoveAll(o => o.thisParamID == parameter.name && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameter.name); } + public void RemoveParameterLink(ShortGuid parameterGUID, Entity childEntity, ShortGuid childParameterGUID) + { + childLinks.RemoveAll(o => o.thisParamID == parameterGUID && o.linkedEntityID == childEntity.shortGUID && o.linkedParamID == childParameterGUID); + } + public void RemoveParameterLink(ShortGuid parameterGUID, ShortGuid childEntityGUID, ShortGuid childParameterGUID) + { + childLinks.RemoveAll(o => o.thisParamID == parameterGUID && o.linkedEntityID == childEntityGUID && o.linkedParamID == childParameterGUID); + } /* Utility: Find all links in to this entity (pass in the composite this entity is within) */ public List GetParentLinks(Composite containedComposite) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index ac4a490..afbdc74 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -340,19 +340,19 @@ public CompositeFlowgraphsTable(BinaryReader reader = null) : base(reader) public override void Read(BinaryReader reader) { + flowgraphs = new List(); if (reader == null) - { - flowgraphs = new List(); return; - } + + int count = reader.ReadInt32(); + if (count == 0) + return; byte version = reader.ReadByte(); if (version != FlowgraphMeta.VERSION) { //Add compatibility here when required } - - int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { FlowgraphMeta flowgraph = new FlowgraphMeta(); @@ -396,8 +396,8 @@ public override void Read(BinaryReader reader) public override void Write(BinaryWriter writer) { - writer.Write(FlowgraphMeta.VERSION); writer.Write(flowgraphs.Count); + writer.Write(FlowgraphMeta.VERSION); for (int i = 0; i < flowgraphs.Count; i++) { Utilities.Write(writer, flowgraphs[i].CompositeGUID); From 756895f84bcca52b1d55fd33bab888533fb417bf Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 29 Sep 2024 11:53:53 +0100 Subject: [PATCH 51/72] add compatibility info table --- .../CommandsPAK/Components/TypeEnums.cs | 1 + .../CommandsPAK/Helpers/CustomTable.cs | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs index 34c7d47..ed6f369 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/TypeEnums.cs @@ -1108,6 +1108,7 @@ public enum CustomEndTables COMPOSITE_PURGE_STATES, COMPOSITE_MODIFICATION_INFO, COMPOSITE_FLOWGRAPHS, + COMPOSITE_FLOWGRAPH_COMPATIBILITY_INFO, //Add new entries here diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index afbdc74..5746aba 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -70,6 +70,9 @@ public static void WriteTable(string filepath, CustomEndTables table, Table cont case CustomEndTables.COMPOSITE_FLOWGRAPHS: ((CompositeFlowgraphsTable)toWrite[tableType]).Write(writer); break; + case CustomEndTables.COMPOSITE_FLOWGRAPH_COMPATIBILITY_INFO: + ((CompositeFlowgraphCompatibilityTable)toWrite[tableType]).Write(writer); + break; } } } @@ -122,6 +125,9 @@ public static Table ReadTable(string filepath, CustomEndTables table) case CustomEndTables.COMPOSITE_FLOWGRAPHS: data = new CompositeFlowgraphsTable(reader); break; + case CustomEndTables.COMPOSITE_FLOWGRAPH_COMPATIBILITY_INFO: + data = new CompositeFlowgraphCompatibilityTable(reader); + break; } } return data; @@ -467,4 +473,48 @@ public class ConnectionMeta } } } + public class CompositeFlowgraphCompatibilityTable : CustomTable.Table + { + public CompositeFlowgraphCompatibilityTable(BinaryReader reader = null) : base(reader) + { + type = CustomEndTables.COMPOSITE_FLOWGRAPH_COMPATIBILITY_INFO; + } + + public List compatibility_info; + + public override void Read(BinaryReader reader) + { + if (reader == null) + { + compatibility_info = new List(); + return; + } + + int count = reader.ReadInt32(); + compatibility_info = new List(count); + for (int i = 0; i < count; i++) + { + CompatibilityInfo info = new CompatibilityInfo(); + info.composite_id = Utilities.Consume(reader); + info.flowgraphs_supported = reader.ReadBoolean(); + compatibility_info.Add(info); + } + } + + public override void Write(BinaryWriter writer) + { + writer.Write(compatibility_info.Count); + for (int i = 0; i < compatibility_info.Count; i++) + { + Utilities.Write(writer, compatibility_info[i].composite_id); + writer.Write(compatibility_info[i].flowgraphs_supported); + } + } + + public class CompatibilityInfo + { + public ShortGuid composite_id; + public bool flowgraphs_supported; + } + } } From b68303e81a9e70c75a8b02be247a686bc48a9a30 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sun, 29 Sep 2024 13:02:12 +0100 Subject: [PATCH 52/72] ClearAllLinks --- .../Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 7 ++++--- .../Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index ebdf6e5..6a6c384 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -382,12 +382,12 @@ public static (Vector3, Quaternion) CalculateInstancedPosition(EntityPath hierar } /* CA's CAGE doesn't properly tidy up hierarchies pointing to deleted entities - so we can do that to save confusion */ - public static void PurgeDeadLinks(Commands commands, Composite composite, bool force = false) + public static bool PurgeDeadLinks(Commands commands, Composite composite, bool force = false) { if (!force && LinkedCommands == commands && _purged.purged.Contains(composite.shortGUID)) { Console.WriteLine("Skipping purge, as this composite is listed within the purged table."); - return; + return false; } int originalUnknownCount = 0; @@ -489,7 +489,7 @@ public static void PurgeDeadLinks(Commands commands, Composite composite, bool f (originalLinkCount - newLinkCount) == 0) { Console.WriteLine("Purge found nothing to clear up."); - return; + return true; } Console.WriteLine( @@ -501,6 +501,7 @@ public static void PurgeDeadLinks(Commands commands, Composite composite, bool f "\n - " + (originalTriggerCount - newTriggerCount) + " triggers (of " + originalTriggerCount + ")" + "\n - " + (originalAnimCount - newAnimCount) + " anim connections (of " + originalAnimCount + ")" + "\n - " + (originalLinkCount - newLinkCount) + " entity links (of " + originalLinkCount + ")"); + return true; } #endregion } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs index a6d21a3..d65c353 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs @@ -128,5 +128,11 @@ public static byte[] GenerateChecksum(Composite composite) return hash; } } + + /* Remove all links between Entities within the Composite */ + public static void ClearAllLinks(Composite composite) + { + composite.GetEntities().ForEach(o => o.childLinks.Clear()); + } } } From b98a0f7c385b4f73de5d696795fc605a2ad7fe1f Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 30 Sep 2024 16:34:14 +0100 Subject: [PATCH 53/72] fix table write --- CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index 5746aba..47f4a96 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -376,6 +376,7 @@ public override void Read(BinaryReader reader) { FlowgraphMeta.NodeMeta node = new FlowgraphMeta.NodeMeta(); node.EntityGUID = Utilities.Consume(reader); + node.NodeID = reader.ReadInt32(); node.Position = new Point(reader.ReadInt32(), reader.ReadInt32()); @@ -391,6 +392,7 @@ public override void Read(BinaryReader reader) connection.ParameterGUID = Utilities.Consume(reader); connection.ConnectedEntityGUID = Utilities.Consume(reader); connection.ConnectedParameterGUID = Utilities.Consume(reader); + connection.ConnectedNodeID = reader.ReadInt32(); node.Connections.Add(connection); } @@ -419,6 +421,7 @@ public override void Write(BinaryWriter writer) for (int x = 0; x < flowgraphs[i].Nodes.Count; x++) { Utilities.Write(writer, flowgraphs[i].Nodes[x].EntityGUID); + writer.Write(flowgraphs[i].Nodes[x].NodeID); writer.Write(flowgraphs[i].Nodes[x].Position.X); writer.Write(flowgraphs[i].Nodes[x].Position.Y); @@ -434,6 +437,7 @@ public override void Write(BinaryWriter writer) Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ParameterGUID); Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ConnectedEntityGUID); Utilities.Write(writer, flowgraphs[i].Nodes[x].Connections[z].ConnectedParameterGUID); + writer.Write(flowgraphs[i].Nodes[x].Connections[z].ConnectedNodeID); } } } From f41e57877453948cffa5bb86fa337437c69102fd Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 30 Sep 2024 18:09:34 +0100 Subject: [PATCH 54/72] add shortened name flag --- .../Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index 47f4a96..ace065d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -369,7 +369,8 @@ public override void Read(BinaryReader reader) flowgraph.CanvasPosition = new PointF(reader.ReadSingle(), reader.ReadSingle()); flowgraph.CanvasScale = reader.ReadSingle(); - reader.BaseStream.Position += 10; //reserved + flowgraph.UsesShortenedNames = reader.ReadBoolean(); + reader.BaseStream.Position += 9; //reserved int nodeMetaCount = reader.ReadInt32(); for (int x = 0; x < nodeMetaCount; x++) @@ -415,7 +416,8 @@ public override void Write(BinaryWriter writer) writer.Write(flowgraphs[i].CanvasPosition.Y); writer.Write(flowgraphs[i].CanvasScale); - writer.Write(new byte[10]); //reserved + writer.Write(flowgraphs[i].UsesShortenedNames); + writer.Write(new byte[9]); //reserved writer.Write(flowgraphs[i].Nodes.Count); for (int x = 0; x < flowgraphs[i].Nodes.Count; x++) @@ -446,6 +448,7 @@ public override void Write(BinaryWriter writer) public class FlowgraphMeta { public const byte VERSION = 1; + public bool UsesShortenedNames = false; public ShortGuid CompositeGUID; public string Name; From db6dfb1d58118fc3a2848c979e86e48d87b34c01 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Fri, 4 Oct 2024 18:42:30 +0100 Subject: [PATCH 55/72] also purge useless aliases --- .../CommandsPAK/Helpers/CommandsUtils.cs | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 6a6c384..c46d7da 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -392,25 +392,21 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f int originalUnknownCount = 0; int originalProxyCount = 0; - int newProxyCount = 0; int originalAliasCount = 0; - int newAliasCount = 0; - int originalTriggerCount = 0; int newTriggerCount = 0; - int originalAnimCount = 0; + int originalTriggerCount = 0; int newAnimCount = 0; - int originalLinkCount = 0; + int originalAnimCount = 0; int newLinkCount = 0; + int originalLinkCount = 0; int originalFuncCount = 0; - int newFuncCount = 0; //Clear functions List functionsPurged = new List(); for (int i = 0; i < composite.functions.Count; i++) if (CommandsUtils.FunctionTypeExists(composite.functions[i].function) || commands.GetComposite(composite.functions[i].function) != null) functionsPurged.Add(composite.functions[i]); - originalFuncCount += composite.functions.Count; - newFuncCount += functionsPurged.Count; + originalFuncCount = composite.functions.Count; composite.functions = functionsPurged; //Clear aliases @@ -418,8 +414,7 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f for (int i = 0; i < composite.aliases.Count; i++) if (ResolveHierarchy(commands, composite, composite.aliases[i].alias.path, out Composite flowTemp, out string hierarchy) != null) aliasesPurged.Add(composite.aliases[i]); - originalAliasCount += composite.aliases.Count; - newAliasCount += aliasesPurged.Count; + originalAliasCount = composite.aliases.Count; composite.aliases = aliasesPurged; //Clear proxies @@ -427,8 +422,7 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f for (int i = 0; i < composite.proxies.Count; i++) if (ResolveHierarchy(commands, composite, composite.proxies[i].proxy.path, out Composite flowTemp, out string hierarchy) != null) proxyPurged.Add(composite.proxies[i]); - originalProxyCount += composite.proxies.Count; - newProxyCount += proxyPurged.Count; + originalProxyCount = composite.proxies.Count; composite.proxies = proxyPurged; //Clear TriggerSequence and CAGEAnimation entities @@ -478,12 +472,22 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f entities[i].childLinks = childLinksPurged; } - //TODO: Clear aliases with no parameters/links in or out? + //Clear aliases with no parameters/links + List aliasPurged = new List(); + for (int i = 0; i < composite.aliases.Count; i++) + { + if (composite.aliases[i].childLinks.Count == 0 && + composite.aliases[i].parameters.Count == 0 && + composite.aliases[i].GetParentLinks(composite).Count == 0) + continue; + aliasPurged.Add(composite.aliases[i]); + } + composite.aliases = aliasPurged; if (originalUnknownCount + - (originalFuncCount - newFuncCount) + - (originalProxyCount - newProxyCount) + - (originalAliasCount - newAliasCount) + + (originalFuncCount - composite.functions.Count) + + (originalProxyCount - composite.proxies.Count) + + (originalAliasCount - composite.aliases.Count) + (originalTriggerCount - newTriggerCount) + (originalAnimCount - newAnimCount) + (originalLinkCount - newLinkCount) == 0) @@ -495,9 +499,9 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f Console.WriteLine( "Purged all dead hierarchies and entities in " + composite.name + "!" + "\n - " + originalUnknownCount + " unknown entities" + - "\n - " + (originalFuncCount - newFuncCount) + " functions (of " + originalFuncCount + ")" + - "\n - " + (originalProxyCount - newProxyCount) + " proxies (of " + originalProxyCount + ")" + - "\n - " + (originalAliasCount - newAliasCount) + " aliases (of " + originalAliasCount + ")" + + "\n - " + (originalFuncCount - composite.functions.Count) + " functions (of " + originalFuncCount + ")" + + "\n - " + (originalProxyCount - composite.proxies.Count) + " proxies (of " + originalProxyCount + ")" + + "\n - " + (originalAliasCount - composite.aliases.Count) + " aliases (of " + originalAliasCount + ")" + "\n - " + (originalTriggerCount - newTriggerCount) + " triggers (of " + originalTriggerCount + ")" + "\n - " + (originalAnimCount - newAnimCount) + " anim connections (of " + originalAnimCount + ")" + "\n - " + (originalLinkCount - newLinkCount) + " entity links (of " + originalLinkCount + ")"); From 05c588fe4dc67464bab3452f285edcfdd4653916 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Sat, 5 Oct 2024 10:47:14 +0100 Subject: [PATCH 56/72] IsUnfinished flag --- .../Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs index ace065d..780ed07 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CustomTable.cs @@ -370,7 +370,8 @@ public override void Read(BinaryReader reader) flowgraph.CanvasScale = reader.ReadSingle(); flowgraph.UsesShortenedNames = reader.ReadBoolean(); - reader.BaseStream.Position += 9; //reserved + flowgraph.IsUnfinished = reader.ReadBoolean(); + reader.BaseStream.Position += 8; //reserved int nodeMetaCount = reader.ReadInt32(); for (int x = 0; x < nodeMetaCount; x++) @@ -417,7 +418,8 @@ public override void Write(BinaryWriter writer) writer.Write(flowgraphs[i].CanvasScale); writer.Write(flowgraphs[i].UsesShortenedNames); - writer.Write(new byte[9]); //reserved + writer.Write(flowgraphs[i].IsUnfinished); + writer.Write(new byte[8]); //reserved writer.Write(flowgraphs[i].Nodes.Count); for (int x = 0; x < flowgraphs[i].Nodes.Count; x++) @@ -449,6 +451,7 @@ public class FlowgraphMeta { public const byte VERSION = 1; public bool UsesShortenedNames = false; + public bool IsUnfinished = false; public ShortGuid CompositeGUID; public string Name; From 37fa8297f7da351aa386a52981bc15c97fe333eb Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 7 Oct 2024 17:48:23 +0100 Subject: [PATCH 57/72] count links --- .../CATHODE/CommandsPAK/Helpers/CompositeUtils.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs index d65c353..b12bf57 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CompositeUtils.cs @@ -134,5 +134,15 @@ public static void ClearAllLinks(Composite composite) { composite.GetEntities().ForEach(o => o.childLinks.Clear()); } + + /* Count the number of links in the Composite */ + public static int CountLinks(Composite composite) + { + int count = 0; + List entities = composite.GetEntities(); + foreach (Entity ent in entities) + count += ent.childLinks.Count; + return count; + } } } From 714fd096e7ca635146cf1f1cf4283cf08505f641 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 8 Oct 2024 19:04:09 +0100 Subject: [PATCH 58/72] don't purge aliases in the link function --- .../CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index c46d7da..6d6e88a 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -472,18 +472,6 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f entities[i].childLinks = childLinksPurged; } - //Clear aliases with no parameters/links - List aliasPurged = new List(); - for (int i = 0; i < composite.aliases.Count; i++) - { - if (composite.aliases[i].childLinks.Count == 0 && - composite.aliases[i].parameters.Count == 0 && - composite.aliases[i].GetParentLinks(composite).Count == 0) - continue; - aliasPurged.Add(composite.aliases[i]); - } - composite.aliases = aliasPurged; - if (originalUnknownCount + (originalFuncCount - composite.functions.Count) + (originalProxyCount - composite.proxies.Count) + From 970b8445607f55bd71dd141caf7c97735452171c Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 9 Oct 2024 17:06:15 +0100 Subject: [PATCH 59/72] remove by guid --- .../Scripts/CATHODE/CommandsPAK/Components/Entity.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index dce84e3..66c7595 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -195,11 +195,15 @@ public Parameter AddParameter(Parameter param) public void RemoveParameter(string name) { ShortGuid name_id = ShortGuidUtils.Generate(name); - parameters.RemoveAll(o => o.name == name_id); + RemoveParameter(name_id); } public void RemoveParameter(Parameter param) { - parameters.RemoveAll(o => o == param); + RemoveParameter(param.name); + } + public void RemoveParameter(ShortGuid guid) + { + parameters.RemoveAll(o => o.name == guid); } /* Add a link from a parameter on us out to a parameter on another entity */ From bf119786159379afbef5272a9c629f6e72e4aa57 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 9 Oct 2024 18:40:23 +0100 Subject: [PATCH 60/72] reduce spam --- CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 6d6e88a..00e2239 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -480,7 +480,7 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f (originalAnimCount - newAnimCount) + (originalLinkCount - newLinkCount) == 0) { - Console.WriteLine("Purge found nothing to clear up."); + //Console.WriteLine("Purge found nothing to clear up."); return true; } From 198cb7ab7762685394147403e3d64c27a23acda3 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Fri, 18 Oct 2024 09:59:41 +0100 Subject: [PATCH 61/72] force upper --- CathodeLib/Scripts/Level.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/Level.cs b/CathodeLib/Scripts/Level.cs index 7a5a88c..bcb9e91 100644 --- a/CathodeLib/Scripts/Level.cs +++ b/CathodeLib/Scripts/Level.cs @@ -318,7 +318,7 @@ public static List GetLevels(string gameDirectory, bool swapNostromoForP int length = file.Length - extraLength; if (length <= 0) continue; - string mapName = file.Substring(0, length); + string mapName = file.Substring(0, length).ToUpper(); if (swapNostromoForPatch && (mapName == "DLC/BSPNOSTROMO_RIPLEY" || mapName == "DLC/BSPNOSTROMO_TWOTEAMS")) mapName += "_PATCH"; mapList.Add(mapName.ToUpper()); } From 7c7c085483a340105b46b47dd83fe3bda2e36e48 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Fri, 18 Oct 2024 15:24:00 +0100 Subject: [PATCH 62/72] comment out spammy log --- CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 00e2239..bd73352 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -386,7 +386,7 @@ public static bool PurgeDeadLinks(Commands commands, Composite composite, bool f { if (!force && LinkedCommands == commands && _purged.purged.Contains(composite.shortGUID)) { - Console.WriteLine("Skipping purge, as this composite is listed within the purged table."); + //Console.WriteLine("Skipping purge, as this composite is listed within the purged table."); return false; } From fda5cd485af3ca1b985c4b713f6a10d2dc0d1586 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 21 Oct 2024 18:39:24 +0100 Subject: [PATCH 63/72] some test resource stuff --- .../CATHODE/CommandsPAK/Helpers/EntityUtils.cs | 14 ++++++++++++++ CathodeLib/Scripts/CATHODE/Resources.cs | 18 +++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs index af15ebb..0a75d36 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/EntityUtils.cs @@ -36,6 +36,20 @@ static EntityUtils() reader.Close(); } + //For testing + public static List GetAllVanillaNames() + { + List names = new List(); + foreach (var entry in _vanilla.names) + { + foreach (var entry2 in entry.Value) + { + names.Add(entry2.Value); + } + } + return names; + } + /* Optionally, link a Commands file which can be used to save custom entity names to */ public static void LinkCommands(Commands commands) { diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index 5b7731d..ecd86ee 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -26,16 +26,15 @@ override protected bool LoadInternal() int entryCount = reader.ReadInt32(); reader.BaseStream.Position += 4; - Resource[] entries = new Resource[entryCount]; + //Resource[] entries = new Resource[entryCount]; for (int i = 0; i < entryCount; i++) { Resource resource = new Resource(); resource.composite_instance_id = Utilities.Consume(reader); resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM - int index = reader.ReadInt32(); - entries[index] = resource; + resource.index = reader.ReadInt32(); + Entries.Add(resource); } - Entries = entries.ToList(); } return true; } @@ -49,14 +48,14 @@ override protected bool SaveInternal() writer.BaseStream.SetLength(0); writer.Write(new byte[4] { 0xCC, 0xBA, 0xED, 0xFE }); writer.Write((Int32)1); - writer.Write(orderedEntries.Count); + writer.Write(Entries.Count); writer.Write((Int32)0); - for (int i = 0; i < orderedEntries.Count; i++) + for (int i = 0; i < Entries.Count; i++) { - Utilities.Write(writer, orderedEntries[i].composite_instance_id); - Utilities.Write(writer, orderedEntries[i].resource_id); - writer.Write(Entries.IndexOf(orderedEntries[i])); + Utilities.Write(writer, Entries[i].composite_instance_id); + Utilities.Write(writer, Entries[i].resource_id); + Utilities.Write(writer, Entries[i].index); } } return true; @@ -68,6 +67,7 @@ public class Resource { public ShortGuid composite_instance_id; public ShortGuid resource_id; + public int index; }; #endregion } From ee40d56384c3d69af00d55be6c5b86fe561c6da0 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 21 Oct 2024 20:07:57 +0100 Subject: [PATCH 64/72] some defaults --- CathodeLib/Scripts/CATHODE/Movers.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Movers.cs b/CathodeLib/Scripts/CATHODE/Movers.cs index 7dd0a94..8ff8e7d 100644 --- a/CathodeLib/Scripts/CATHODE/Movers.cs +++ b/CathodeLib/Scripts/CATHODE/Movers.cs @@ -32,7 +32,7 @@ public Movers(string path) : base(path) { } #region FILE_IO override protected bool LoadInternal() { - //note: first 12 always renderable but not linked to commands -> they are always the same models across every level + //note: first 12 always renderable but not linked to commands -> they are always the same models across every level. is it the content of GLOBAL? using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { @@ -271,23 +271,23 @@ public class GPU_CONSTANTS //As best I can tell, this is 80 bytes long //64 - public Vector4 LightColour; - public Vector4 MaterialTint; + public Vector4 LightColour = new Vector4(1,1,1,1); + public Vector4 MaterialTint = new Vector4(1,1,1,1); //96 - public float lightVolumeIntensity; //todo: idk if this is right, but editing this value seems to increase/decrease the brightness of the light volume meshes - public float particleIntensity; //0 = black particle - public float particleSystemOffset; //todo: not sure entirely, but increasing this value seems to apply an offset to particle systems + public float lightVolumeIntensity = 1; //todo: idk if this is right, but editing this value seems to increase/decrease the brightness of the light volume meshes + public float particleIntensity = 1; //0 = black particle + public float particleSystemOffset = 0; //todo: not sure entirely, but increasing this value seems to apply an offset to particle systems //108 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] blankSpace1; //116 - public float lightRadius; - public Vector2 textureTile; //x = horizontal tile, y = vertical tile + public float lightRadius = 0; + public Vector2 textureTile = new Vector2(1,1); //x = horizontal tile, y = vertical tile //128 - public float UnknownValue1_; - public float UnknownValue2_; - public float UnknownValue3_; - public float UnknownValue4_; + public float UnknownValue1_ = 1; + public float UnknownValue2_ = 1; + public float UnknownValue3_ = 0; + public float UnknownValue4_ = 0; //144 ~GPU_CONSTANTS() @@ -310,10 +310,10 @@ used in */ //160 - public Vector4 Unknown3_; + public Vector4 Unknown3_ = new Vector4(0,0,0,0); //176 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public UInt32[] Unknowns2_; + public UInt32[] Unknowns2_; //184 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public Vector3[] UnknownMinMax_; // NOTE: Sometimes I see 'nan's here too. From 26b8fe2d598e42929b74aa6e274c0ebbf1917a56 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Mon, 21 Oct 2024 20:57:06 +0100 Subject: [PATCH 65/72] revert to correct ordering --- CathodeLib/Scripts/CATHODE/Resources.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index ecd86ee..5b7731d 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -26,15 +26,16 @@ override protected bool LoadInternal() int entryCount = reader.ReadInt32(); reader.BaseStream.Position += 4; - //Resource[] entries = new Resource[entryCount]; + Resource[] entries = new Resource[entryCount]; for (int i = 0; i < entryCount; i++) { Resource resource = new Resource(); resource.composite_instance_id = Utilities.Consume(reader); resource.resource_id = Utilities.Consume(reader); //this is the id that's used in commands.pak, frequently translates to Door/AnimatedModel/Light/DYNAMIC_PHYSICS_SYSTEM - resource.index = reader.ReadInt32(); - Entries.Add(resource); + int index = reader.ReadInt32(); + entries[index] = resource; } + Entries = entries.ToList(); } return true; } @@ -48,14 +49,14 @@ override protected bool SaveInternal() writer.BaseStream.SetLength(0); writer.Write(new byte[4] { 0xCC, 0xBA, 0xED, 0xFE }); writer.Write((Int32)1); - writer.Write(Entries.Count); + writer.Write(orderedEntries.Count); writer.Write((Int32)0); - for (int i = 0; i < Entries.Count; i++) + for (int i = 0; i < orderedEntries.Count; i++) { - Utilities.Write(writer, Entries[i].composite_instance_id); - Utilities.Write(writer, Entries[i].resource_id); - Utilities.Write(writer, Entries[i].index); + Utilities.Write(writer, orderedEntries[i].composite_instance_id); + Utilities.Write(writer, orderedEntries[i].resource_id); + writer.Write(Entries.IndexOf(orderedEntries[i])); } } return true; @@ -67,7 +68,6 @@ public class Resource { public ShortGuid composite_instance_id; public ShortGuid resource_id; - public int index; }; #endregion } From f93d98a332927fdba351116af938669d78214907 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 22 Oct 2024 12:03:16 +0100 Subject: [PATCH 66/72] speeding up some bits with id generation --- .../CATHODE/CommandsPAK/Components/Entity.cs | 51 +++++++++++-------- CathodeLib/Scripts/Utilities.cs | 2 +- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 66c7595..dcb208d 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -682,6 +682,7 @@ public EntityPath(List _path) { path = _path; + //TODO: this whole system of modifying the path is dumb, should really come up with a better solution if (path.Count == 0 || path[path.Count - 1] != ShortGuid.Invalid) path.Add(ShortGuid.Invalid); } @@ -770,15 +771,13 @@ public Entity GetPointedEntity(Commands commands, Composite startComposite, out /* Get the ID of the entity that this path points to */ public ShortGuid GetPointedEntityID() { - path.Reverse(); ShortGuid id = ShortGuid.Invalid; - for (int i = 0; i < path.Count; i++) + for (int i = path.Count - 1; i >= 0; i--) { if (path[i] == ShortGuid.Invalid) continue; id = path[i]; break; } - path.Reverse(); return id; } @@ -807,31 +806,15 @@ public ShortGuid GeneratePathHash() } /* Generate the instance ID used to identify the instanced composite we're executed in */ - public ShortGuid GenerateInstance() + public ShortGuid GenerateCompositeInstanceID(bool hasInternalEntityID = true) //Set this to false the final value in the path is not an entity ID within the composite { - //TODO: This hijacks the usual use for this class, need to tidy it up - ShortGuid entityID = GetPointedEntityID(); - path.Insert(0, ShortGuid.InitialiserBase); - path.Remove(entityID); - path.Reverse(); - ShortGuid instanceGenerated = path[0]; - for (int i = 0; i < path.Count; i++) - { - if (i == path.Count - 1) break; - instanceGenerated = path[i + 1].Combine(instanceGenerated); - } - path.Reverse(); - path.RemoveAt(0); - path.RemoveAll(o => o == ShortGuid.Invalid); - path.Add(entityID); - path.Add(ShortGuid.Invalid); - return instanceGenerated; + return path.GenerateCompositeInstanceID(hasInternalEntityID); } /* Generate a zone ID (use this when the EntityHandle points to a Zone entity) */ public ShortGuid GenerateZoneID() { - return new ShortGuid(0 + GenerateInstance().ToUInt32() + GetPointedEntityID().ToUInt32() + 1); + return new ShortGuid(0 + GenerateCompositeInstanceID().ToUInt32() + GetPointedEntityID().ToUInt32() + 1); } /* Updates this path to have the path to another entity prepended to it */ @@ -843,6 +826,30 @@ public void PrependPath(EntityPath otherPath) } } + public static class PathUtils + { + /* Generate the instance ID used to identify the instanced composite we're executed in */ + public static ShortGuid GenerateCompositeInstanceID(this List path, bool hasInternalEntityID = true) //Set this to false the final value in the path is not an entity ID within the composite + { + bool hasTrailingInvalid = (path.Count > 0 && path[path.Count - 1] == ShortGuid.Invalid); + ShortGuid[] values = new ShortGuid[hasInternalEntityID ? (hasTrailingInvalid ? path.Count - 1 : path.Count) : (hasTrailingInvalid ? path.Count : path.Count + 1)]; + values[values.Length - 1] = ShortGuid.InitialiserBase; + int x = 0; + for (int i = values.Length - 2; i >= 0; i--) + { + values[i] = path[x]; + x++; + } + ShortGuid instanceGenerated = values[0]; + for (int i = 0; i < values.Length; i++) + { + if (i == values.Length - 1) break; + instanceGenerated = values[i + 1].Combine(instanceGenerated); + } + return instanceGenerated; + } + } + #if DEBUG public class EntityPathConverter : JsonConverter { diff --git a/CathodeLib/Scripts/Utilities.cs b/CathodeLib/Scripts/Utilities.cs index a3b8b9e..392000c 100644 --- a/CathodeLib/Scripts/Utilities.cs +++ b/CathodeLib/Scripts/Utilities.cs @@ -474,7 +474,7 @@ public EntityHandle() { } public EntityHandle(EntityPath hierarchy) { entity_id = hierarchy.GetPointedEntityID(); - composite_instance_id = hierarchy.GenerateInstance(); + composite_instance_id = hierarchy.GenerateCompositeInstanceID(); } public override bool Equals(object obj) From 49c873dce720a99dd5be2d2e867f4ab2d2a748b2 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 22 Oct 2024 13:53:51 +0100 Subject: [PATCH 67/72] correctly check custom cache when generating --- CathodeLib/Scripts/CATHODE/CollisionMaps.cs | 27 ++++++++----------- .../CATHODE/CommandsPAK/Components/Entity.cs | 1 - .../CommandsPAK/Helpers/CommandsUtils.cs | 10 +++---- .../CommandsPAK/Helpers/ShortGuidUtils.cs | 9 ++++++- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs index 152e2c8..dbe9df1 100644 --- a/CathodeLib/Scripts/CATHODE/CollisionMaps.cs +++ b/CathodeLib/Scripts/CATHODE/CollisionMaps.cs @@ -29,21 +29,15 @@ override protected bool LoadInternal() using (BinaryReader reader = new BinaryReader(File.OpenRead(_filepath))) { - //It seems typically in this file at the start there are a bunch of empty entries, and then there are a bunch of unresolvable ones, and then a bunch that can be resolved. + //The way this works: + // - First 18 entries are empty + // - Next set of entries are all the COLLISION_MAPPING resources referenced by COMMANDS.PAK (hence they have no composite_instance_id, as the composites aren't instanced - but they do have entity_ids) + // - There are then a few entries that have composite_instance_ids set but I can't resolve them - perhaps these are things from GLOBAL? + // - Then there's all the instanced entities with resolvable composite_instance_ids - //first 18 are always null - - //always first 247 are the same? 18 null and the rest in required assets? - - //note: some of the things we skip here actually contain useful info, but the game doesn't read it so there's no point us bothering with it - - - - //NOTE: skipping first 18 as they're always empty, at least, for what we parse reader.BaseStream.Position = 4; int entryCount = reader.ReadInt32(); - reader.BaseStream.Position += (48 * 18); - for (int i = 0; i < entryCount - 18; i++) + for (int i = 0; i < entryCount; i++) { Entry entry = new Entry(); @@ -106,15 +100,16 @@ override protected bool LoadInternal() override protected bool SaveInternal() { + //composite_instance_id defo has something to do with the ordering as all the zeros are first + + //Entries = Entries.OrderBy(o => o.entity.entity_id.ToUInt32() + o.id.ToUInt32()).ThenBy(o => o.entity.composite_instance_id.ToUInt32()).ThenBy(o => o.zone_id.ToUInt32()).ToList(); using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); - writer.Write((Entries.Count + 18) * 48); - writer.Write(Entries.Count + 18); - - writer.Write(new byte[18 * 48]); + writer.Write((Entries.Count) * 48); + writer.Write(Entries.Count); for (int i = 0; i < Entries.Count; i++) { diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index dcb208d..885b2a1 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -682,7 +682,6 @@ public EntityPath(List _path) { path = _path; - //TODO: this whole system of modifying the path is dumb, should really come up with a better solution if (path.Count == 0 || path[path.Count - 1] != ShortGuid.Invalid) path.Add(ShortGuid.Invalid); } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index bd73352..877c9f8 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -271,11 +271,11 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li asString = ""; return null; } - + List hierarchyCopy = new List(); for (int x = 0; x < hierarchy.Count; x++) hierarchyCopy.Add(new ShortGuid(hierarchy[x].ToUInt32())); - + Composite currentFlowgraphToSearch = composite; if (currentFlowgraphToSearch == null || currentFlowgraphToSearch.GetEntityByID(hierarchyCopy[0]) == null) { @@ -292,19 +292,19 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li hierarchyCopy.RemoveAt(0); } } - + Entity entity = null; string hierarchyString = ""; for (int i = 0; i < hierarchyCopy.Count; i++) { entity = currentFlowgraphToSearch.GetEntityByID(hierarchyCopy[i]); - + if (entity == null) break; if (includeShortGuids) hierarchyString += "[" + entity.shortGUID.ToByteString() + "] "; hierarchyString += EntityUtils.GetName(currentFlowgraphToSearch.shortGUID, entity.shortGUID); if (i >= hierarchyCopy.Count - 2) break; //Last is always 00-00-00-00 hierarchyString += " -> "; - + if (entity.variant == EntityVariant.FUNCTION) { Composite flowRef = commands.GetComposite(((FunctionEntity)entity).function); diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs index f446b2a..a58df89 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs @@ -53,6 +53,8 @@ public static ShortGuid Generate(string value, bool cache = true) { if (_vanilla.cache.ContainsKey(value)) return _vanilla.cache[value]; + if (_custom.cache.ContainsKey(value)) + return _custom.cache[value]; SHA1Managed sha1 = new SHA1Managed(); byte[] hash1 = sha1.ComputeHash(Encoding.UTF8.GetBytes(value)); @@ -133,9 +135,14 @@ private static void Cache(ShortGuid guid, string value, bool isVanilla = false) } else { + //TODO: need to fix this for BSPNOSTROMO_RIPLEY_PATCH if (_custom.cache.ContainsKey(value)) return; _custom.cache.Add(value, guid); - _custom.cacheReversed.Add(guid, value); + try + { + _custom.cacheReversed.Add(guid, value); + } + catch { } } } From dee39542133304360130fdacab421515aa65fab3 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Tue, 22 Oct 2024 14:26:40 +0100 Subject: [PATCH 68/72] add unique --- .../CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs | 2 +- CathodeLib/Scripts/CATHODE/Resources.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs index a58df89..ca0cbbb 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/ShortGuidUtils.cs @@ -135,7 +135,7 @@ private static void Cache(ShortGuid guid, string value, bool isVanilla = false) } else { - //TODO: need to fix this for BSPNOSTROMO_RIPLEY_PATCH + //TODO: need to fix this for BSPNOSTROMO_RIPLEY_PATCH (?) if (_custom.cache.ContainsKey(value)) return; _custom.cache.Add(value, guid); try diff --git a/CathodeLib/Scripts/CATHODE/Resources.cs b/CathodeLib/Scripts/CATHODE/Resources.cs index 5b7731d..dd415ca 100644 --- a/CathodeLib/Scripts/CATHODE/Resources.cs +++ b/CathodeLib/Scripts/CATHODE/Resources.cs @@ -63,6 +63,18 @@ override protected bool SaveInternal() } #endregion + public void AddUniqueResource(ShortGuid composite_instance_id, ShortGuid resource_id) + { + if (Entries.FirstOrDefault(o => o.composite_instance_id == composite_instance_id && o.resource_id == resource_id) != null) + return; + + Entries.Add(new Resource() + { + composite_instance_id = composite_instance_id, + resource_id = resource_id + }); + } + #region STRUCTURES public class Resource { From ffa29e629078813022dfdfb7c9494b5cb9882bd5 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 23 Oct 2024 13:01:12 +0100 Subject: [PATCH 69/72] handle paths as fixed size arrays --- CathodeLib/Scripts/CATHODE/Commands.cs | 16 +-- .../CommandsPAK/Components/Composite.cs | 6 +- .../CATHODE/CommandsPAK/Components/Entity.cs | 128 ++++++++++++++---- .../CommandsPAK/Helpers/CommandsUtils.cs | 47 +------ 4 files changed, 114 insertions(+), 83 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/Commands.cs b/CathodeLib/Scripts/CATHODE/Commands.cs index a716ce7..245c69d 100644 --- a/CathodeLib/Scripts/CATHODE/Commands.cs +++ b/CathodeLib/Scripts/CATHODE/Commands.cs @@ -189,7 +189,7 @@ override protected bool LoadInternal() reader_parallel.BaseStream.Position = (offsetPairs[x].GlobalOffset * 4) + (y * 12); AliasEntity overrider = new AliasEntity(new ShortGuid(reader_parallel)); int NumberOfParams = JumpToOffset(reader_parallel); - overrider.alias.path.AddRange(Utilities.ConsumeArray(reader_parallel, NumberOfParams)); + overrider.alias.path = Utilities.ConsumeArray(reader_parallel, NumberOfParams); composite.aliases.Add(overrider); break; } @@ -214,7 +214,7 @@ override protected bool LoadInternal() ProxyEntity thisProxy = new ProxyEntity(new ShortGuid(reader_parallel)); int resetPos = (int)reader_parallel.BaseStream.Position + 8; //TODO: This is a HACK - I need to rework JumpToOffset to make a temp stream int NumberOfParams = JumpToOffset(reader_parallel); - thisProxy.proxy.path.AddRange(Utilities.ConsumeArray(reader_parallel, NumberOfParams)); //Last is always 0x00, 0x00, 0x00, 0x00 + thisProxy.proxy.path = Utilities.ConsumeArray(reader_parallel, NumberOfParams); //Last is always 0x00, 0x00, 0x00, 0x00 reader_parallel.BaseStream.Position = resetPos; ShortGuid idCheck = new ShortGuid(reader_parallel); if (idCheck != thisProxy.shortGUID) throw new Exception("Proxy ID mismatch!"); @@ -315,7 +315,7 @@ override protected bool LoadInternal() header.parameterSubID = new ShortGuid(reader_parallel); int hierarchyCount = JumpToOffset(reader_parallel); - header.connectedEntity.path = Utilities.ConsumeArray(reader_parallel, hierarchyCount).ToList(); + header.connectedEntity.path = Utilities.ConsumeArray(reader_parallel, hierarchyCount); animEntity.connections.Add(header); } @@ -397,7 +397,7 @@ override protected bool LoadInternal() TriggerSequence.Entity thisTrigger = new TriggerSequence.Entity(); thisTrigger.timing = reader_parallel.ReadSingle(); reader_parallel.BaseStream.Position = hierarchyOffset; - thisTrigger.connectedEntity.path = Utilities.ConsumeArray(reader_parallel, hierarchyCount).ToList(); + thisTrigger.connectedEntity.path = Utilities.ConsumeArray(reader_parallel, hierarchyCount); trigEntity.entities.Add(thisTrigger); } @@ -849,7 +849,7 @@ override protected bool SaveInternal() List offsetPairs = new List(reshuffledAliases[i].Count); for (int p = 0; p < reshuffledAliases[i].Count; p++) { - offsetPairs.Add(new OffsetPair(writer.BaseStream.Position, reshuffledAliases[i][p].alias.path.Count)); + offsetPairs.Add(new OffsetPair(writer.BaseStream.Position, reshuffledAliases[i][p].alias.path.Length)); Utilities.Write(writer, reshuffledAliases[i][p].alias.path); } @@ -888,7 +888,7 @@ override protected bool SaveInternal() List offsetPairs = new List(); for (int p = 0; p < Entries[i].proxies.Count; p++) { - offsetPairs.Add(new OffsetPair(writer.BaseStream.Position, Entries[i].proxies[p].proxy.path.Count)); + offsetPairs.Add(new OffsetPair(writer.BaseStream.Position, Entries[i].proxies[p].proxy.path.Length)); Utilities.Write(writer, Entries[i].proxies[p].proxy.path); } @@ -983,7 +983,7 @@ override protected bool SaveInternal() Utilities.Write(writer, CommandsUtils.GetDataTypeGUID(header.parameterDataType)); Utilities.Write(writer, header.parameterSubID); writer.Write(hierarchyOffsets[pp] / 4); - writer.Write(header.connectedEntity.path.Count); + writer.Write(header.connectedEntity.path.Length); } List internalOffsets = new List(cageAnimationEntities[i][p].animations.Count); @@ -1094,7 +1094,7 @@ override protected bool SaveInternal() for (int pp = 0; pp < triggerSequenceEntities[i][p].entities.Count; pp++) { writer.Write(hierarchyOffsets[pp] / 4); - writer.Write(triggerSequenceEntities[i][p].entities[pp].connectedEntity.path.Count); + writer.Write(triggerSequenceEntities[i][p].entities[pp].connectedEntity.path.Length); writer.Write(triggerSequenceEntities[i][p].entities[pp].timing); } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs index e874718..14d7066 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Composite.cs @@ -105,10 +105,10 @@ public VariableEntity AddVariable(string parameter, DataType type, bool addDefau } /* Add a new proxy entity */ - public ProxyEntity AddProxy(Commands commands, List hierarchy, bool addDefaultParam = false) + public ProxyEntity AddProxy(Commands commands, ShortGuid[] hierarchy, bool addDefaultParam = false) { CommandsUtils.ResolveHierarchy(commands, this, hierarchy, out Composite targetComposite, out string str); - Entity ent = targetComposite.GetEntityByID(hierarchy[hierarchy.Count - 2]); + Entity ent = targetComposite.GetEntityByID(hierarchy[hierarchy.Length - 2]); if (ent.variant != EntityVariant.FUNCTION) return null; ProxyEntity proxy = new ProxyEntity(hierarchy, ((FunctionEntity)ent).function, addDefaultParam); @@ -117,7 +117,7 @@ public ProxyEntity AddProxy(Commands commands, List hierarchy, bool a } /* Add a new alias entity */ - public AliasEntity AddAlias(List hierarchy) + public AliasEntity AddAlias(ShortGuid[] hierarchy) { AliasEntity alias = new AliasEntity(hierarchy); aliases.Add(alias); diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs index 885b2a1..6c33589 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Components/Entity.cs @@ -466,13 +466,13 @@ public class ProxyEntity : Entity public ProxyEntity() : base(EntityVariant.PROXY) { } public ProxyEntity(ShortGuid shortGUID) : base(shortGUID, EntityVariant.PROXY) { } - public ProxyEntity(List hierarchy = null, ShortGuid targetType = new ShortGuid(), bool autoGenerateParameters = false) : base(EntityVariant.PROXY) + public ProxyEntity(ShortGuid[] hierarchy = null, ShortGuid targetType = new ShortGuid(), bool autoGenerateParameters = false) : base(EntityVariant.PROXY) { this.function = targetType; if (hierarchy != null) this.proxy.path = hierarchy; if (autoGenerateParameters) EntityUtils.ApplyDefaults(this); } - public ProxyEntity(ShortGuid shortGUID, List hierarchy = null, ShortGuid targetType = new ShortGuid(), bool autoGenerateParameters = false) : base(shortGUID, EntityVariant.PROXY) + public ProxyEntity(ShortGuid shortGUID, ShortGuid[] hierarchy = null, ShortGuid targetType = new ShortGuid(), bool autoGenerateParameters = false) : base(shortGUID, EntityVariant.PROXY) { this.shortGUID = shortGUID; this.function = targetType; @@ -489,11 +489,11 @@ public class AliasEntity : Entity public AliasEntity() : base(EntityVariant.ALIAS) { } public AliasEntity(ShortGuid shortGUID) : base(shortGUID, EntityVariant.ALIAS) { } - public AliasEntity(List hierarchy = null) : base(EntityVariant.ALIAS) + public AliasEntity(ShortGuid[] hierarchy = null) : base(EntityVariant.ALIAS) { if (hierarchy != null) this.alias.path = hierarchy; } - public AliasEntity(ShortGuid shortGUID, List hierarchy = null) : base(shortGUID, EntityVariant.ALIAS) + public AliasEntity(ShortGuid shortGUID, ShortGuid[] hierarchy = null) : base(shortGUID, EntityVariant.ALIAS) { this.shortGUID = shortGUID; if (hierarchy != null) this.alias.path = hierarchy; @@ -678,21 +678,19 @@ public override int GetHashCode() public class EntityPath { public EntityPath() { } - public EntityPath(List _path) + public EntityPath(ShortGuid[] _path) { - path = _path; - - if (path.Count == 0 || path[path.Count - 1] != ShortGuid.Invalid) - path.Add(ShortGuid.Invalid); + path = (ShortGuid[])_path.Clone(); + EnsureFinalIsEmpty(); } - public List path = new List(); + public ShortGuid[] path = new ShortGuid[0]; public static bool operator ==(EntityPath x, EntityPath y) { if (ReferenceEquals(x, null)) return ReferenceEquals(y, null); if (ReferenceEquals(y, null)) return ReferenceEquals(x, null); - if (x.path.Count != y.path.Count) return false; - for (int i = 0; i < x.path.Count; i++) + if (x.path.Length != y.path.Length) return false; + for (int i = 0; i < x.path.Length; i++) { if (x.path[i].ToByteString() != y.path[i].ToByteString()) return false; @@ -706,23 +704,32 @@ public EntityPath(List _path) public override bool Equals(object obj) { - return obj is EntityPath hierarchy && - EqualityComparer>.Default.Equals(this.path, hierarchy.path); + return obj is EntityPath path && + EqualityComparer.Default.Equals(this.path, path.path); } public override int GetHashCode() { - return 218564712 + EqualityComparer>.Default.GetHashCode(path); + return -1757656154 + EqualityComparer.Default.GetHashCode(path); + } + + private void EnsureFinalIsEmpty() + { + if (path.Length == 0 || path[path.Length - 1] != ShortGuid.Invalid) + { + Array.Resize(ref path, path.Length + 1); + path[path.Length - 1] = ShortGuid.Invalid; + } } /* Get this path as a string */ public string GetAsString() { string val = ""; - for (int i = 0; i < path.Count; i++) + for (int i = 0; i < path.Length; i++) { val += path[i].ToByteString(); - if (i != path.Count - 1) val += " -> "; + if (i != path.Length - 1) val += " -> "; } return val; } @@ -735,7 +742,7 @@ public string GetAsString(Commands commands, Composite composite, bool withIDs = public UInt32 ToUInt32() { UInt32 val = 0; - for (int i = 0; i < path.Count; i++) val += path[i].ToUInt32(); + for (int i = 0; i < path.Length; i++) val += path[i].ToUInt32(); return val; } @@ -771,7 +778,7 @@ public Entity GetPointedEntity(Commands commands, Composite startComposite, out public ShortGuid GetPointedEntityID() { ShortGuid id = ShortGuid.Invalid; - for (int i = path.Count - 1; i >= 0; i--) + for (int i = path.Length - 1; i >= 0; i--) { if (path[i] == ShortGuid.Invalid) continue; id = path[i]; @@ -789,15 +796,16 @@ public bool IsPathValid(Commands commands, Composite composite) /* Generate the checksum used identify the path */ public ShortGuid GeneratePathHash() { - if (path.Count == 0) return ShortGuid.Invalid; - if (path[path.Count - 1] != ShortGuid.Invalid) path.Add(ShortGuid.Invalid); + if (path.Length == 0) return ShortGuid.Invalid; + EnsureFinalIsEmpty(); + //TODO: invert loop rather than array path.Reverse(); ShortGuid checksumGenerated = path[0]; - for (int i = 0; i < path.Count; i++) + for (int i = 0; i < path.Length; i++) { checksumGenerated = checksumGenerated.Combine(path[i + 1]); - if (i == path.Count - 2) break; + if (i == path.Length - 2) break; } path.Reverse(); @@ -815,19 +823,78 @@ public ShortGuid GenerateZoneID() { return new ShortGuid(0 + GenerateCompositeInstanceID().ToUInt32() + GetPointedEntityID().ToUInt32() + 1); } - - /* Updates this path to have the path to another entity prepended to it */ - public void PrependPath(EntityPath otherPath) + + /* Add the next entity GUID along the path */ + public void AddNextStep(Entity entity) { - int length = otherPath.path[otherPath.path.Count - 1] == ShortGuid.Invalid ? otherPath.path.Count - 2 : otherPath.path.Count - 1; - for (int i = 0; i < length; i++) - path.Insert(i, otherPath.path[i]); + AddNextStep(entity.shortGUID); + } + public void AddNextStep(ShortGuid guid) + { + if (path.Length > 0 && path[path.Length - 1] == ShortGuid.Invalid) + { + path[path.Length - 1] = guid; + } + else + { + Array.Resize(ref path, path.Length + 1); + path[path.Length - 1] = guid; + } + EnsureFinalIsEmpty(); + } + + /* Remove the last entity GUID along the path */ + public void GoBackOneStep() + { + if (path.Length > 0 && path[path.Length - 1] == ShortGuid.Invalid) + { + if (path.Length > 1) + { + path[path.Length - 2] = ShortGuid.Invalid; + Array.Resize(ref path, path.Length - 1); + } + } + else if (path.Length > 0) + { + path[path.Length - 1] = ShortGuid.Invalid; + } + else + { + EnsureFinalIsEmpty(); + } } + + /* Updates this path to have the path to another entity prepended to it */ + //public void PrependPath(EntityPath otherPath) + //{ + // int length = otherPath.path[otherPath.path.Count - 1] == ShortGuid.Invalid ? otherPath.path.Count - 2 : otherPath.path.Count - 1; + // for (int i = 0; i < length; i++) + // path.Insert(i, otherPath.path[i]); + //} } public static class PathUtils { /* Generate the instance ID used to identify the instanced composite we're executed in */ + public static ShortGuid GenerateCompositeInstanceID(this ShortGuid[] path, bool hasInternalEntityID = true) //Set this to false the final value in the path is not an entity ID within the composite + { + bool hasTrailingInvalid = (path.Length > 0 && path[path.Length - 1] == ShortGuid.Invalid); + ShortGuid[] values = new ShortGuid[hasInternalEntityID ? (hasTrailingInvalid ? path.Length - 1 : path.Length) : (hasTrailingInvalid ? path.Length : path.Length + 1)]; + values[values.Length - 1] = ShortGuid.InitialiserBase; + int x = 0; + for (int i = values.Length - 2; i >= 0; i--) + { + values[i] = path[x]; + x++; + } + ShortGuid instanceGenerated = values[0]; + for (int i = 0; i < values.Length; i++) + { + if (i == values.Length - 1) break; + instanceGenerated = values[i + 1].Combine(instanceGenerated); + } + return instanceGenerated; + } public static ShortGuid GenerateCompositeInstanceID(this List path, bool hasInternalEntityID = true) //Set this to false the final value in the path is not an entity ID within the composite { bool hasTrailingInvalid = (path.Count > 0 && path[path.Count - 1] == ShortGuid.Invalid); @@ -861,7 +928,8 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { EntityPath e = new EntityPath(); List vals = reader.Value.ToString().Split(new[] { " -> " }, StringSplitOptions.None).ToList(); - for (int i = 0; i < vals.Count; i++) e.path.Add(new ShortGuid(vals[i])); + e.path = new ShortGuid[vals.Count]; + for (int i = 0; i < vals.Count; i++) e.path[i] = new ShortGuid(vals[i]); return e; } diff --git a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs index 877c9f8..a484fb7 100644 --- a/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs +++ b/CathodeLib/Scripts/CATHODE/CommandsPAK/Helpers/CommandsUtils.cs @@ -263,18 +263,16 @@ public static ShortGuid GetResourceEntryTypeGUID(ResourceType type) #region HELPER_FUNCS /* Resolve an entity hierarchy */ - public static Entity ResolveHierarchy(Commands commands, Composite composite, List hierarchy, out Composite containedComposite, out string asString, bool includeShortGuids = true) + public static Entity ResolveHierarchy(Commands commands, Composite composite, ShortGuid[] hierarchy, out Composite containedComposite, out string asString, bool includeShortGuids = true) { - if (hierarchy.Count == 0) + if (hierarchy.Length == 0) { containedComposite = null; asString = ""; return null; } - - List hierarchyCopy = new List(); - for (int x = 0; x < hierarchy.Count; x++) - hierarchyCopy.Add(new ShortGuid(hierarchy[x].ToUInt32())); + + List hierarchyCopy = hierarchy.ToList(); Composite currentFlowgraphToSearch = composite; if (currentFlowgraphToSearch == null || currentFlowgraphToSearch.GetEntityByID(hierarchyCopy[0]) == null) @@ -324,47 +322,12 @@ public static Entity ResolveHierarchy(Commands commands, Composite composite, Li return entity; } - /* Generate all possible hierarchies for an entity */ - private static List> _hierarchies = new List>(); - public static List GenerateHierarchies(Commands commands, Composite composite, Entity entity) - { - List hierarchies = new List(); - _hierarchies.Clear(); - - GenerateHierarchiesRecursive(commands, null, commands.EntryPoints[0], composite, new List()); - - for (int i = 0; i < _hierarchies.Count; i++) - { - _hierarchies[i].Add(entity.shortGUID); - hierarchies.Add(new EntityPath(_hierarchies[i])); - } - - return hierarchies; - } - private static void GenerateHierarchiesRecursive(Commands commands, Entity ent, Composite comp, Composite target, List hierarchy) - { - if (ent != null) - hierarchy.Add(ent.shortGUID); - - if (comp.shortGUID == target.shortGUID) - { - _hierarchies.Add(hierarchy); - return; - } - - Parallel.For(0, comp.functions.Count, i => - { - Composite next = commands.GetComposite(comp.functions[i].function); - if (next != null) GenerateHierarchiesRecursive(commands, comp.functions[i], next, target, new List(hierarchy.ConvertAll(x => x))); - }); - } - /* Calculate an instanced entity's worldspace position & rotation */ public static (Vector3, Quaternion) CalculateInstancedPosition(EntityPath hierarchy) { cTransform globalTransform = new cTransform(); Composite comp = _commands.EntryPoints[0]; - for (int x = 0; x < hierarchy.path.Count; x++) + for (int x = 0; x < hierarchy.path.Length; x++) { FunctionEntity compInst = comp.functions.FirstOrDefault(o => o.shortGUID == hierarchy.path[x]); if (compInst == null) From e3f4e35d7115d4598fa44ab616e9198c044933b9 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 23 Oct 2024 13:26:55 +0100 Subject: [PATCH 70/72] env maps need to be ordered --- CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs index 81bcd6e..fcfac52 100644 --- a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs +++ b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs @@ -1,6 +1,7 @@ -using CathodeLib; +using CathodeLib; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.InteropServices; namespace CATHODE @@ -36,16 +37,18 @@ override protected bool LoadInternal() override protected bool SaveInternal() { + List orderedEntries = Entries.OrderByDescending(o => o.MoverIndex).ToList(); + using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { writer.BaseStream.SetLength(0); Utilities.WriteString("envm", writer); writer.Write(1); writer.Write(Entries.Count); - for (int i = 0; i < Entries.Count; i++) + for (int i = 0; i < orderedEntries.Count; i++) { - writer.Write(Entries[i].MoverIndex); - writer.Write(Entries[i].EnvMapIndex); + writer.Write(orderedEntries[i].MoverIndex); + writer.Write(orderedEntries[i].EnvMapIndex); } writer.Write(EnvironmentMapCount); } From 95bb6b32a9b2ed3a4b69febbefc179ceed339ef5 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Wed, 23 Oct 2024 13:49:07 +0100 Subject: [PATCH 71/72] . --- CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs index fcfac52..fd75b73 100644 --- a/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs +++ b/CathodeLib/Scripts/CATHODE/EnvironmentMaps.cs @@ -37,7 +37,7 @@ override protected bool LoadInternal() override protected bool SaveInternal() { - List orderedEntries = Entries.OrderByDescending(o => o.MoverIndex).ToList(); + List orderedEntries = Entries.OrderBy(o => o.MoverIndex).ToList(); using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(_filepath))) { From 78cfcf37c5c659625ae68e1849889f68b3ca1382 Mon Sep 17 00:00:00 2001 From: Matt Filer Date: Thu, 24 Oct 2024 14:44:28 +0100 Subject: [PATCH 72/72] version number --- CathodeLib/CathodeLib.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CathodeLib/CathodeLib.csproj b/CathodeLib/CathodeLib.csproj index 36d7e70..9c5a0bf 100644 --- a/CathodeLib/CathodeLib.csproj +++ b/CathodeLib/CathodeLib.csproj @@ -9,10 +9,10 @@ CathodeLib Matt Filer Provides support for parsing and writing common Alien: Isolation formats from the Cathode engine. - Matt Filer 2023 - 0.6.0 + Matt Filer 2024 + 0.7.0 Library - 0.6.0.0 + 0.7.0.0 0.6.0.0 False