1
0
mirror of https://github.com/Raymonf/whack.git synced 2025-02-13 08:52:32 +01:00
whack/WTT/UAssetAPI/AssetBinaryWriter.cs
2022-09-28 18:39:41 -04:00

177 lines
5.1 KiB
C#

using System;
using System.IO;
using System.Text;
using UAssetAPI.Kismet.Bytecode;
using UAssetAPI.UnrealTypes;
namespace UAssetAPI
{
public class AssetBinaryWriter : BinaryWriter
{
public UAsset Asset;
public AssetBinaryWriter(UAsset asset) : base()
{
Asset = asset;
}
public AssetBinaryWriter(Stream stream, UAsset asset) : base(stream)
{
Asset = asset;
}
public AssetBinaryWriter(Stream stream, Encoding encoding, UAsset asset) : base(stream, encoding)
{
Asset = asset;
}
public AssetBinaryWriter(Stream stream, Encoding encoding, bool leaveOpen, UAsset asset) : base(stream, encoding, leaveOpen)
{
Asset = asset;
}
private byte[] ReverseIfBigEndian(byte[] data)
{
if (!BitConverter.IsLittleEndian) Array.Reverse(data);
return data;
}
public override void Write(short value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(ushort value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(int value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(uint value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(long value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(ulong value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(float value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(double value)
{
this.Write(ReverseIfBigEndian(BitConverter.GetBytes(value)));
}
public override void Write(string value)
{
Write(new FString(value));
}
public virtual int Write(FString value)
{
switch (value?.Value)
{
case null:
this.Write((int)0);
return sizeof(int);
default:
string nullTerminatedStr = value.Value + "\0";
this.Write(value.Encoding is UnicodeEncoding ? -nullTerminatedStr.Length : nullTerminatedStr.Length);
byte[] actualStrData = value.Encoding.GetBytes(nullTerminatedStr);
this.Write(actualStrData);
return actualStrData.Length + 4;
}
}
public virtual void Write(FName name)
{
this.Write(name.Index);
this.Write(name.Number);
}
public virtual void WritePropertyGuid(Guid? guid)
{
if (Asset.EngineVersion >= UE4Version.VER_UE4_PROPERTY_GUID_IN_PROPERTY_TAG)
{
Write(guid != null);
if (guid != null) Write(((Guid)guid).ToByteArray());
}
}
public int XFERSTRING(string val)
{
long startMetric = this.BaseStream.Position;
this.Write(Encoding.ASCII.GetBytes(val + "\0"));
return (int)(this.BaseStream.Position - startMetric);
}
public int XFERUNICODESTRING(string val)
{
long startMetric = this.BaseStream.Position;
this.Write(Encoding.Unicode.GetBytes(val + "\0"));
return (int)(this.BaseStream.Position - startMetric);
}
public int XFERNAME(FName val)
{
this.Write(val);
return 12; // FScriptName's iCode offset is 12 bytes, not 8
}
public int XFER_FUNC_NAME(FName val)
{
return this.XFERNAME(val);
}
private static readonly int PointerSize = sizeof(ulong);
public int XFERPTR(FPackageIndex val)
{
this.Write(val.Index);
return PointerSize; // For the iCode offset, we return the size of a pointer in memory rather than the size of an FPackageIndex on disk
}
public int XFER_FUNC_POINTER(FPackageIndex val)
{
return this.XFERPTR(val);
}
public int XFER_PROP_POINTER(KismetPropertyPointer val)
{
if (Asset.EngineVersion >= KismetPropertyPointer.XFER_PROP_POINTER_SWITCH_TO_SERIALIZING_AS_FIELD_PATH_VERSION)
{
this.Write(val.New.Path.Length);
for (int i = 0; i < val.New.Path.Length; i++)
{
this.XFERNAME(val.New.Path[i]);
}
this.XFER_OBJECT_POINTER(val.New.ResolvedOwner);
}
else
{
this.XFERPTR(val.Old);
}
return PointerSize;
}
public int XFER_OBJECT_POINTER(FPackageIndex val)
{
return this.XFERPTR(val);
}
}
}