Skip to content

Commit e877b5f

Browse files
authored
Objects v2 (#13)
* fully use attributes for struct size and type * split loco obj from file-specific headers * ui change for file info view * reverse on radical object changes, fix image saving, enable bridge saving * add a large number of objects to saving ability * add water and wall object to saving * add coloured text to log box * add dock saving, fix region saving * correctly save object length in obj header * add steam and road/track extra to saving * add town names to save * enable road and track station saving * save airport objs * save building objs * fix var_AE buildingobject parsing * complete loading of industry * working industry object saving * complete loading of vehicel object * add vehicle object saving (and fixed loading) * correctly load vehicle sounds * compute checksum for saving obejcts * misc cleanup * misc fixes
1 parent 94ccb46 commit e877b5f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2334
-1374
lines changed

OpenLocoTool/DatFileParsing/AttributeHelper.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using OpenLocoTool.Headers;
23

34
namespace OpenLocoTool.DatFileParsing
45
{
@@ -15,8 +16,25 @@ public static class AttributeHelper
1516

1617
public static bool Has<T>(PropertyInfo p) where T : Attribute
1718
=> p.GetCustomAttribute(typeof(T), inherit: false) is T;
19+
public static bool Has<T>(Type t) where T : Attribute
20+
=> t.GetCustomAttribute(typeof(T), inherit: false) is T;
1821

1922
public static IEnumerable<PropertyInfo> GetAllPropertiesWithAttribute<T>(Type t) where T : Attribute
2023
=> t.GetProperties().Where(Has<T>);
2124
}
25+
26+
public static class ObjectAttributes
27+
{
28+
public static int StructSize<T>() where T : ILocoStruct
29+
=> AttributeHelper.Get<LocoStructSizeAttribute>(typeof(T)).Size;
30+
31+
public static ObjectType ObjectType<T>() // where T : ILocoStruct
32+
=> AttributeHelper.Get<LocoStructTypeAttribute>(typeof(T)).ObjectType;
33+
34+
public static ObjectType ObjectType(ILocoStruct str) // where T : ILocoStruct
35+
=> AttributeHelper.Get<LocoStructTypeAttribute>(str.GetType()).ObjectType;
36+
37+
public static string[] StringTableNames<T>() // where T : ILocoStruct
38+
=> AttributeHelper.Get<LocoStringTableAttribute>(typeof(T)).Strings;
39+
}
2240
}

OpenLocoTool/DatFileParsing/ByteReader.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ public static object ReadT(ReadOnlySpan<byte> data, Type t, int offset, int arrL
9191
throw new NotImplementedException(t.ToString());
9292
}
9393

94-
public static ILocoStruct ReadLocoStruct<T>(ReadOnlySpan<byte> data) where T : class
95-
=> ReadLocoStruct(data, typeof(T));
94+
public static T ReadLocoStruct<T>(ReadOnlySpan<byte> data) where T : class
95+
=> (T)ReadLocoStruct(data, typeof(T));
9696

9797
public static ILocoStruct ReadLocoStruct(ReadOnlySpan<byte> data, Type t)
9898
{
@@ -110,7 +110,7 @@ public static ILocoStruct ReadLocoStruct(ReadOnlySpan<byte> data, Type t)
110110

111111
// ignore skipped properties (usually image ids and string ids which are only used in loco itself, not this tool
112112
var skip = AttributeHelper.Get<LocoStructSkipReadAttribute>(p);
113-
if (offsetAttr == null)
113+
if (skip != null)
114114
{
115115
continue;
116116
}

OpenLocoTool/DatFileParsing/ByteReaderT.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ public static class ByteReaderT
55
public static uint8_t Read_uint8t(ReadOnlySpan<byte> data, int offset)
66
=> data[offset];
77

8+
public static MicroZ Read_MicroZ(ReadOnlySpan<byte> data, int offset)
9+
=> data[offset];
10+
811
public static int8_t Read_int8t(ReadOnlySpan<byte> data, int offset)
912
=> (sbyte)data[offset];
1013

@@ -14,6 +17,9 @@ public static uint16_t Read_uint16t(ReadOnlySpan<byte> data, int offset)
1417
public static int16_t Read_int16t(ReadOnlySpan<byte> data, int offset)
1518
=> BitConverter.ToInt16(data[offset..(offset + 2)]);
1619

20+
public static Speed16 Read_Speed16(ReadOnlySpan<byte> data, int offset)
21+
=> BitConverter.ToInt16(data[offset..(offset + 2)]);
22+
1723
public static uint32_t Read_uint32t(ReadOnlySpan<byte> data, int offset)
1824
=> BitConverter.ToUInt32(data[offset..(offset + 4)]);
1925

@@ -22,39 +28,44 @@ public static int32_t Read_int32t(ReadOnlySpan<byte> data, int offset)
2228

2329
public static T Read<T>(ReadOnlySpan<byte> data, int offset) where T : struct
2430
{
25-
if (typeof(T) == typeof(uint8_t))
31+
var type = typeof(T);
32+
33+
if (type == typeof(uint8_t) || type == typeof(MicroZ) || type == typeof(SoundObjectId))
2634
{
2735
return (T)(dynamic)Read_uint8t(data, offset);
2836
}
2937

30-
if (typeof(T) == typeof(int8_t))
38+
if (type == typeof(int8_t))
3139
{
3240
return (T)(dynamic)Read_int8t(data, offset);
3341
}
3442

35-
if (typeof(T) == typeof(uint16_t))
43+
if (type == typeof(uint16_t) || type == typeof(string_id))
3644
{
3745
return (T)(dynamic)Read_uint16t(data, offset);
3846
}
3947

40-
if (typeof(T) == typeof(int16_t))
48+
if (type == typeof(int16_t) || type == typeof(Speed16))
4149
{
4250
return (T)(dynamic)Read_int16t(data, offset);
4351
}
4452

45-
if (typeof(T) == typeof(uint32_t))
53+
if (type == typeof(uint32_t))
4654
{
4755
return (T)(dynamic)Read_uint32t(data, offset);
4856
}
4957

50-
if (typeof(T) == typeof(int32_t))
58+
if (type == typeof(int32_t) || type == typeof(Speed32))
5159
{
5260
return (T)(dynamic)Read_int32t(data, offset);
5361
}
5462

5563
throw new NotImplementedException("");
5664
}
5765

66+
// todo:
67+
// static Dictionary cachedTypes
68+
5869
public static T[] Read_Array<T>(ReadOnlySpan<byte> data, int count, int offset = 0) where T : struct
5970
{
6071
var arr = new T[count];

OpenLocoTool/DatFileParsing/ByteWriter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ public static ReadOnlySpan<byte> WriteLocoStruct(ILocoStruct obj)
9898
continue;
9999
}
100100

101+
// skip variable struct loading as they'll be set in special save
102+
var variable = AttributeHelper.Get<LocoStructVariableLoadAttribute>(p);
103+
if (variable != null)
104+
{
105+
continue;
106+
}
107+
101108
// special array handling
102109
var arrLength = 0;
103110
if (p.PropertyType.IsArray)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.ComponentModel;
2+
using OpenLocoTool.Headers;
3+
4+
namespace OpenLocoTool.DatFileParsing
5+
{
6+
[TypeConverter(typeof(ExpandableObjectConverter))]
7+
public class DatFileInfo(S5Header s5Header, ObjectHeader objectHeader)
8+
{
9+
public S5Header S5Header { get; set; } = s5Header;
10+
public ObjectHeader ObjectHeader { get; set; } = objectHeader;
11+
}
12+
}

OpenLocoTool/DatFileParsing/ILocoObject.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@ namespace OpenLocoTool.DatFileParsing
66
[TypeConverter(typeof(ExpandableObjectConverter))]
77
public interface ILocoObject
88
{
9-
S5Header S5Header { get; set; }
10-
ObjectHeader ObjectHeader { get; set; }
119
ILocoStruct Object { get; set; }
1210
StringTable StringTable { get; set; }
13-
G1Header? G1Header { get; set; }
1411
List<G1Element32>? G1Elements { get; set; }
1512
}
1613
}

OpenLocoTool/DatFileParsing/ILocoStruct.cs

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,7 @@
22

33
namespace OpenLocoTool.DatFileParsing
44
{
5-
/*
6-
=== Dat File Format ===
7-
|-File-------------------------------|
8-
|-S5Header-|-DatHeader--|-ObjectData-|
9-
10-
==============================================================================================================
11-
12-
|-S5Header----------------|
13-
|-Flags-|-Name-|-Checksum-|
14-
15-
|-DatHeader-------------|
16-
|-Encoding-|-Datalength-|
17-
18-
|-ObjectData-----------------------------------------|
19-
|-Object-|-StringTable-|-VariableData-|-GraphicsData-|
20-
21-
==============================================================================================================
22-
23-
|-Object-|
24-
-- per-object
25-
26-
|-StringTable-|
27-
|-String{n}---|
28-
29-
|-VariableData-|
30-
-- per-object
31-
32-
|-GraphicsData------------------------------|
33-
|-G1Header-|-G1Element32{n}-|-ImageBytes{n}-|
34-
35-
==============================================================================================================
36-
37-
|-String-----------------|
38-
|-Language-|-StringBytes-|
39-
40-
|-G1Header---------------|
41-
|-NumEntries-|-TotalSize-|
42-
43-
|-G1Element32------------------------------------------------------|
44-
|-Offset-|-Width-|-Height-|-xOffset-|-yOffset-|-Flags-|-ZoomOffset-|
45-
46-
|-ImageBytes-|
47-
-- offset by G1Element32.Offset
48-
*/
49-
505
[TypeConverter(typeof(ExpandableObjectConverter))]
516
public interface ILocoStruct
52-
{
53-
static int StructSize { get; }
54-
}
7+
{ }
558
}

OpenLocoTool/DatFileParsing/ILocoStructStringTablePostLoad.cs

Lines changed: 0 additions & 10 deletions
This file was deleted.

OpenLocoTool/DatFileParsing/LocoAttributes.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace OpenLocoTool.DatFileParsing
1+
using OpenLocoTool.Headers;
2+
3+
namespace OpenLocoTool.DatFileParsing
24
{
35
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
46
public class LocoArrayLengthAttribute(int length) : Attribute
@@ -18,6 +20,12 @@ public class LocoStructSizeAttribute(int size) : Attribute
1820
public int Size => size;
1921
}
2022

23+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
24+
public class LocoStructTypeAttribute(ObjectType objectType) : Attribute
25+
{
26+
public ObjectType ObjectType => objectType;
27+
}
28+
2129
// basically a 'skip' attribute to allow deferred loading for variable data
2230
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
2331
public class LocoStructVariableLoadAttribute : Attribute
@@ -32,4 +40,16 @@ public class LocoStructSkipReadAttribute : Attribute
3240
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
3341
public class LocoStringAttribute : Attribute
3442
{ }
43+
44+
// to mark properties that seemingly have no purpose or use
45+
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
46+
public class LocoPropertyMaybeUnused : Attribute
47+
{ }
48+
49+
// basically a 'skip' attribute to allow deferred loading for variable data, and writing of this property will be 0
50+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
51+
public class LocoStringTableAttribute(params string[] strings) : Attribute
52+
{
53+
public string[] Strings => strings;
54+
}
3555
}

OpenLocoTool/DatFileParsing/LocoObject.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,25 @@
33

44
namespace OpenLocoTool.DatFileParsing
55
{
6+
67
[TypeConverter(typeof(ExpandableObjectConverter))]
78
public class LocoObject : ILocoObject
89
{
9-
public LocoObject(S5Header s5Hdr, ObjectHeader objHdr, ILocoStruct obj, StringTable stringTable, G1Header? g1Header, List<G1Element32>? g1Elements)
10+
public LocoObject(ILocoStruct obj, StringTable stringTable, List<G1Element32>? g1Elements)
1011
{
11-
S5Header = s5Hdr;
12-
ObjectHeader = objHdr;
1312
Object = obj;
1413
StringTable = stringTable;
15-
G1Header = g1Header;
1614
G1Elements = g1Elements;
1715
}
18-
public LocoObject(S5Header s5Hdr, ObjectHeader objHdr, ILocoStruct obj, StringTable stringTable)
16+
public LocoObject(ILocoStruct obj, StringTable stringTable)
1917
{
20-
S5Header = s5Hdr;
21-
ObjectHeader = objHdr;
2218
Object = obj;
2319
StringTable = stringTable;
24-
G1Header = null;
2520
G1Elements = null;
2621
}
2722

28-
public S5Header S5Header { get; set; }
29-
public ObjectHeader ObjectHeader { get; set; }
3023
public ILocoStruct Object { get; set; }
3124
public StringTable StringTable { get; set; }
32-
public G1Header? G1Header { get; set; }
3325
public List<G1Element32>? G1Elements { get; set; }
3426
}
3527
}

0 commit comments

Comments
 (0)