ThiefLightmapper/KeepersCompound.LGS/Database/Chunks/Link.cs

172 lines
3.9 KiB
C#
Raw Permalink Normal View History

2025-01-11 13:16:31 +00:00
using Serilog;
2024-09-20 15:28:44 +00:00
namespace KeepersCompound.LGS.Database.Chunks;
public record LinkId
{
private readonly uint _data;
public LinkId(uint data)
{
_data = data;
}
public uint GetId()
{
return _data & 0xFFFF;
}
public bool IsConcrete()
{
return (_data & 0xF0000) != 0;
}
public uint GetRelation()
{
return (_data >> 20) & 0xFFF;
}
public uint GetRaw()
{
return _data;
}
public void Write(BinaryWriter writer)
{
writer.Write(_data);
}
2024-09-20 15:28:44 +00:00
}
public class LinkChunk : IChunk, IMergable
{
public record Link
{
public LinkId linkId;
public int source;
public int destination;
public ushort relation;
public Link(BinaryReader reader)
{
linkId = new LinkId(reader.ReadUInt32());
source = reader.ReadInt32();
destination = reader.ReadInt32();
relation = reader.ReadUInt16();
}
public void Write(BinaryWriter writer)
{
linkId.Write(writer);
writer.Write(source);
writer.Write(destination);
writer.Write(relation);
}
2024-09-20 15:28:44 +00:00
}
public ChunkHeader Header { get; set; }
public List<Link> links;
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
{
links = new List<Link>();
while (reader.BaseStream.Position < entry.Offset + entry.Size + 24)
{
links.Add(new Link(reader));
}
}
public void WriteData(BinaryWriter writer)
{
foreach (var link in links)
{
link.Write(writer);
}
2024-09-20 15:28:44 +00:00
}
public void Merge(IMergable other)
{
// !HACK: We always merge into gamesys so we can pre-trim garbage here
var count = links.Count;
for (var i = count - 1; i >= 0; i--)
{
var link = links[i];
if (link.linkId.IsConcrete())
{
links.RemoveAt(i);
}
}
if (links.Count != count)
{
2025-01-11 13:16:31 +00:00
Log.Information("Trimming excess Links in GAM: {StartCount} -> {EndCount}", count, links.Count);
}
2024-09-20 15:28:44 +00:00
links.AddRange(((LinkChunk)other).links);
}
}
// TODO: This should be generic like Property
public class LinkDataMetaProp : IChunk, IMergable
{
public record LinkData
{
public LinkId linkId;
public int priority;
public LinkData(BinaryReader reader)
{
linkId = new LinkId(reader.ReadUInt32());
priority = reader.ReadInt32();
}
public void Write(BinaryWriter writer)
{
linkId.Write(writer);
writer.Write(priority);
}
2024-09-20 15:28:44 +00:00
}
public ChunkHeader Header { get; set; }
public int DataSize;
public List<LinkData> linkData;
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
{
DataSize = reader.ReadInt32();
linkData = new List<LinkData>();
while (reader.BaseStream.Position < entry.Offset + entry.Size + 24)
{
linkData.Add(new LinkData(reader));
}
}
public void WriteData(BinaryWriter writer)
{
writer.Write(DataSize);
foreach (var data in linkData)
{
data.Write(writer);
}
2024-09-20 15:28:44 +00:00
}
public void Merge(IMergable other)
{
// !HACK: We always merge into gamesys so we can pre-trim garbage here
var count = linkData.Count;
for (var i = count - 1; i >= 0; i--)
{
var link = linkData[i];
if (link.linkId.IsConcrete())
{
linkData.RemoveAt(i);
}
}
if (linkData.Count != count)
{
2025-01-11 13:16:31 +00:00
Log.Information("Trimming excess LinkData in GAM: {StartCount} -> {EndCount}", count, linkData.Count);
}
2024-09-20 15:28:44 +00:00
linkData.AddRange(((LinkDataMetaProp)other).linkData);
}
}