Skip to content

Commit

Permalink
Refactor data transport (#666)
Browse files Browse the repository at this point in the history
Part of #653.
  • Loading branch information
lahm86 authored May 6, 2024
1 parent d4d481a commit e8955af
Show file tree
Hide file tree
Showing 76 changed files with 3,292 additions and 2,904 deletions.
38 changes: 11 additions & 27 deletions ModelExport/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using TRModelTransporter.Utilities;
using TRDataControl.Utils;

namespace ModelExport;

Expand All @@ -12,52 +12,42 @@ static void Main(string[] args)
return;
}

bool exportSegments = args.Length > 1 && args[1].ToLower().Contains("segments");
switch (args[0].ToLower())
{
case "tr1":
TR1Export(exportSegments);
TR1Export();
break;
case "tr2":
TR2Export(exportSegments);
TR2Export();
break;
case "tr3":
TR3Export(exportSegments);
TR3Export();
break;
}
}

static void TR1Export(bool exportSegments)
static void TR1Export()
{
TR1MassExporter exporter = new();
string exportFolder = @"TR1\Models";
string segmentFolder = exportSegments ? @"TR1\ModelSegments" : null;

exporter.Export(Directory.GetCurrentDirectory(), exportFolder, segmentFolder);
exporter.Export(Directory.GetCurrentDirectory(), @"TR1\Objects");
}

static void TR2Export(bool exportSegments)
static void TR2Export()
{
TR2MassExporter exporter = new();
string exportFolder = @"TR2\Models";
string segmentFolder = exportSegments ? @"TR2\ModelSegments" : null;

exporter.Export(Directory.GetCurrentDirectory(), exportFolder, segmentFolder);
exporter.Export(Directory.GetCurrentDirectory(), @"TR2\Objects");
}

static void TR3Export(bool exportSegments)
static void TR3Export()
{
TR3MassExporter exporter = new();
string exportFolder = @"TR3\Models";
string segmentFolder = exportSegments ? @"TR3\ModelSegments" : null;

exporter.Export(Directory.GetCurrentDirectory(), exportFolder, segmentFolder);
exporter.Export(Directory.GetCurrentDirectory(), @"TR3\Objects");
}

private static void Usage()
{
Console.WriteLine();
Console.WriteLine("Usage: ModelExport [tr1 | tr2 | tr3] [segments]");
Console.WriteLine("Usage: ModelExport [tr1 | tr2 | tr3]");
Console.WriteLine();

Console.WriteLine("Example");
Expand All @@ -66,11 +56,5 @@ private static void Usage()
Console.ResetColor();
Console.WriteLine("\t\tExport defined models for TR1.");
Console.WriteLine();

Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\tModelExport tr2 segments");
Console.ResetColor();
Console.WriteLine("\t\tExport defined models for TR2 and include all individual segments for each model.");
Console.WriteLine();
}
}
48 changes: 48 additions & 0 deletions TRDataControl/Blob/Control/TRBlobControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using Newtonsoft.Json;
using System.Text;

namespace TRDataControl;

public class TRBlobControl
{
private static readonly uint _blobMagic = 'T' | ('R' << 8) | ('B' << 16) | ('M' << 24);

private static readonly TRBlobConverter _converter = new();
private static readonly JsonSerializerSettings _serializer = new()
{
ContractResolver = new TRBlobResolver()
};

public static T Read<T>(string file)
{
using BinaryReader reader = new(File.OpenRead(file));

uint magic = reader.ReadUInt32();
if (magic != _blobMagic)
{
throw new Exception("Unrecognised blob data file.");
}

using MemoryStream inflatedStream = new();
using InflaterInputStream inflater = new(reader.BaseStream);
inflater.CopyTo(inflatedStream);

string data = Encoding.Default.GetString(inflatedStream.ToArray());
return JsonConvert.DeserializeObject<T>(data, _converter);
}

public static void Write<T>(T blob, string file)
{
using BinaryWriter writer = new(File.Create(file));

writer.Write(_blobMagic);

string data = JsonConvert.SerializeObject(blob, _serializer);
using MemoryStream inStream = new(Encoding.Default.GetBytes(data));
using DeflaterOutputStream deflater = new(writer.BaseStream);

inStream.CopyTo(deflater);
deflater.Finish();
}
}
57 changes: 57 additions & 0 deletions TRDataControl/Blob/Control/TRBlobConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TRLevelControl.Model;

namespace TRDataControl;

public class TRBlobConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TRAnimCommand) || objectType == typeof(TRTexture);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
if (objectType == typeof(TRAnimCommand))
{
return ReadAnimCommand(jo);
}
if (objectType == typeof(TRTexture))
{
return ReadTexture(jo);
}
return existingValue;
}

private static object ReadAnimCommand(JObject jo)
{
TRAnimCommandType type = (TRAnimCommandType)jo[nameof(TRAnimCommand.Type)].Value<int>();
return type switch
{
TRAnimCommandType.EmptyHands => JsonConvert.DeserializeObject<TREmptyHandsCommand>(jo.ToString()),
TRAnimCommandType.Null => JsonConvert.DeserializeObject<TRNullCommand>(jo.ToString()),
TRAnimCommandType.SetPosition => JsonConvert.DeserializeObject<TRSetPositionCommand>(jo.ToString()),
TRAnimCommandType.JumpDistance => JsonConvert.DeserializeObject<TRJumpDistanceCommand>(jo.ToString()),
TRAnimCommandType.Kill => JsonConvert.DeserializeObject<TRKillCommand>(jo.ToString()),
TRAnimCommandType.PlaySound => JsonConvert.DeserializeObject<TRSFXCommand>(jo.ToString()),
TRAnimCommandType.FlipEffect =>
jo[nameof(TRFootprintCommand.Foot)] == null
? JsonConvert.DeserializeObject<TRFXCommand>(jo.ToString())
: JsonConvert.DeserializeObject<TRFootprintCommand>(jo.ToString()),
_ => throw new InvalidDataException(),
};
}

private static TRTexture ReadTexture(JObject jo)
{
return jo[nameof(TRObjectTexture.Vertices)] == null
? JsonConvert.DeserializeObject<TRSpriteTexture>(jo.ToString())
: JsonConvert.DeserializeObject<TRObjectTexture>(jo.ToString());
}

public override bool CanWrite => false;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { }
}
20 changes: 20 additions & 0 deletions TRDataControl/Blob/Control/TRBlobResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using System.Reflection;
using TRLevelControl.Model;

namespace TRDataControl;

public class TRBlobResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
// Don't output dynamic getters
IEnumerable<PropertyInfo> props = type.GetProperties()
.Where(p => p.CanWrite || type.BaseType == typeof(TRAnimCommand));

return base.CreateProperties(type, memberSerialization)
?.Where(p => !p.Ignored && props.Any(pi => pi.Name == p.PropertyName))
.ToList();
}
}
33 changes: 13 additions & 20 deletions TRDataControl/Blob/TRBlobBase.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
using Newtonsoft.Json;
using System.Drawing;
using TRImageControl;
using TRImageControl.Packing;
using TRLevelControl.Model;

namespace TRModelTransporter.Model;
namespace TRDataControl;

public abstract class TRBlobBase<E> where E : Enum
public abstract class TRBlobBase<T>
where T : Enum
{
[JsonIgnore]
public E Entity { get; set; }
[JsonIgnore]
public E Alias { get; set; }
[JsonIgnore]
public TRImage Image { get; set; }
[JsonIgnore]
public bool HasGraphics => false;// ObjectTextures.Count > 0;
[JsonIgnore]
public TRBlobType Type { get; set; }
public T ID { get; set; }
public T Alias { get; set; }
public bool IsDependencyOnly { get; set; }

public E[] Dependencies { get; set; }
//public Dictionary<int, List<IndexedTRObjectTexture>> ObjectTextures { get; set; }
//public Dictionary<E, Dictionary<int, List<IndexedTRSpriteTexture>>> SpriteTextures { get; set; }
public Dictionary<E, TRSpriteSequence> SpriteSequences { get; set; }
public Rectangle[] TextureSegments { get; set; }
public List<T> Dependencies { get; set; }
public TRModel Model { get; set; }
public TRStaticMesh StaticMesh { get; set; }
public List<int> SpriteOffsets { get; set; }
public List<TRTextileRegion> Textures { get; set; }
public List<TRCinematicFrame> CinematicFrames { get; set; }
}
8 changes: 8 additions & 0 deletions TRDataControl/Blob/TRBlobType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TRDataControl;

public enum TRBlobType
{
Model,
Sprite,
StaticMesh
}
11 changes: 4 additions & 7 deletions TRDataControl/Blob/Types/TR1Blob.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using TRLevelControl.Model;

namespace TRModelTransporter.Model.Definitions;
namespace TRDataControl;

public class TR1Blob : TRBlobBase<TR1Type>
{
public TRCinematicFrame[] CinematicFrames { get; set; }
public Dictionary<int, TRColour> Colours { get; set; }
public List<TRMesh> Meshes { get; set; }
public TRModel Model { get; set; }
public Dictionary<ushort, TRColour> Palette8 { get; set; }
public SortedDictionary<TR1SFX, TR1SoundEffect> SoundEffects { get; set; }

public override bool Equals(object obj)
{
return obj is TR1Blob definition && Entity == definition.Entity;
return obj is TR1Blob blob && ID == blob.ID;
}

public override int GetHashCode()
{
return 1674515507 + Entity.GetHashCode();
return ID.GetHashCode();
}
}
11 changes: 4 additions & 7 deletions TRDataControl/Blob/Types/TR2Blob.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using TRLevelControl.Model;

namespace TRModelTransporter.Model.Definitions;
namespace TRDataControl;

public class TR2Blob : TRBlobBase<TR2Type>
{
public TRCinematicFrame[] CinematicFrames { get; set; }
public Dictionary<int, TRColour4> Colours { get; set; }
public List<TRMesh> Meshes { get; set; }
public TRModel Model { get; set; }
public Dictionary<ushort, TRColour4> Palette16 { get; set; }
public SortedDictionary<TR2SFX, TR2SoundEffect> SoundEffects { get; set; }

public override bool Equals(object obj)
{
return obj is TR2Blob definition && Entity == definition.Entity;
return obj is TR2Blob blob && ID == blob.ID;
}

public override int GetHashCode()
{
return 1875520522 + Entity.GetHashCode();
return ID.GetHashCode();
}
}
11 changes: 4 additions & 7 deletions TRDataControl/Blob/Types/TR3Blob.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using TRLevelControl.Model;

namespace TRModelTransporter.Model.Definitions;
namespace TRDataControl;

public class TR3Blob : TRBlobBase<TR3Type>
{
public TRCinematicFrame[] CinematicFrames { get; set; }
public Dictionary<int, TRColour4> Colours { get; set; }
public List<TRMesh> Meshes { get; set; }
public TRModel Model { get; set; }
public Dictionary<ushort, TRColour4> Palette16 { get; set; }
public SortedDictionary<TR3SFX, TR3SoundEffect> SoundEffects { get; set; }

public override bool Equals(object obj)
{
return obj is TR3Blob definition && Entity == definition.Entity;
return obj is TR3Blob blob && ID == blob.ID;
}

public override int GetHashCode()
{
return 1075520522 + Entity.GetHashCode();
return ID.GetHashCode();
}
}
18 changes: 18 additions & 0 deletions TRDataControl/Blob/Types/TR4Blob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using TRLevelControl.Model;

namespace TRDataControl;

public class TR4Blob : TRBlobBase<TR4Type>
{
public SortedDictionary<TR4SFX, TR4SoundEffect> SoundEffects { get; set; }

public override bool Equals(object obj)
{
return obj is TR4Blob blob && ID == blob.ID;
}

public override int GetHashCode()
{
return ID.GetHashCode();
}
}
18 changes: 18 additions & 0 deletions TRDataControl/Blob/Types/TR5Blob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using TRLevelControl.Model;

namespace TRDataControl;

public class TR5Blob : TRBlobBase<TR5Type>
{
public SortedDictionary<TR5SFX, TR4SoundEffect> SoundEffects { get; set; }

public override bool Equals(object obj)
{
return obj is TR5Blob blob && ID == blob.ID;
}

public override int GetHashCode()
{
return ID.GetHashCode();
}
}
Loading

0 comments on commit e8955af

Please sign in to comment.