Skip to content

Commit 1cb28a0

Browse files
authored
start of object validation (#37)
* start of object validation * add vehicle validation * finish object validation, and fix multiple industryobject bugs * disallow saving if object fails validation
1 parent e4884da commit 1cb28a0

Some content is hidden

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

62 files changed

+950
-161
lines changed

Core/DatFileParsing/SawyerStreamReader.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ namespace OpenLoco.ObjectEditor.DatFileParsing
1212
{
1313
public static class SawyerStreamReader
1414
{
15-
public static List<S5Header> LoadVariableCountS5Headers(ReadOnlySpan<byte> data, int count)
15+
public static List<S5Header> LoadVariableCountS5Headers(ReadOnlySpan<byte> data, int max)
1616
{
1717
List<S5Header> result = [];
18-
for (var i = 0; i < count; ++i)
18+
for (var i = 0; i < max; ++i)
1919
{
20-
var header = S5Header.Read(data[..S5Header.StructLength]);
21-
if (header.Checksum != 0 || header.Flags != 255)
20+
if (data[0] != 0xFF)
2221
{
23-
result.Add(header);
22+
var header = S5Header.Read(data[..S5Header.StructLength]);
23+
if (header.Checksum != 0 || header.Flags != 255)
24+
{
25+
result.Add(header);
26+
}
2427
}
2528

2629
data = data[S5Header.StructLength..];
@@ -148,12 +151,33 @@ public static (DatFileInfo DatFileInfo, ILocoObject? LocoObject) LoadFullObjectF
148151
locoStructPostLoad.PostLoad();
149152
}
150153

154+
ValidateLocoStruct(s5Header, locoStruct, logger);
155+
151156
// add to object manager
152157
SObjectManager.Add(newObj);
153158

154159
return new(new DatFileInfo(s5Header, objectHeader), newObj);
155160
}
156161

162+
static void ValidateLocoStruct(S5Header s5Header, ILocoStruct locoStruct, ILogger? logger)
163+
{
164+
try
165+
{
166+
if (!locoStruct.Validate())
167+
{
168+
logger?.Warning($"\"{s5Header.Name}\" failed validation");
169+
}
170+
else
171+
{
172+
logger?.Info($"\"{s5Header.Name}\" validated successfully");
173+
}
174+
}
175+
catch (NotImplementedException)
176+
{
177+
logger?.Debug2($"{s5Header.ObjectType} object type is missing validation function");
178+
}
179+
}
180+
157181
static string CStringToString(ReadOnlySpan<byte> data, Encoding enc)
158182
{
159183
var ptr = 0;

Core/Objects/Airport/AirportObject.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44

@@ -164,5 +164,20 @@ public ReadOnlySpan<byte> Save()
164164

165165
return ms.ToArray();
166166
}
167+
168+
public bool Validate()
169+
{
170+
if (CostIndex > 32)
171+
{
172+
return false;
173+
}
174+
175+
if (-SellCostFactor > BuildCostFactor)
176+
{
177+
return false;
178+
}
179+
180+
return BuildCostFactor > 0;
181+
}
167182
}
168183
}

Core/Objects/Airport/MovementEdge.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.DatFileParsing;
33

44
namespace Core.Objects
@@ -12,5 +12,8 @@ public record MovementEdge(
1212
[property: LocoStructOffset(0x03)] uint8_t var_03,
1313
[property: LocoStructOffset(0x04)] uint32_t MustBeClearEdges, // Which edges must be clear to use the transition edge. should probably be some kind of flags?
1414
[property: LocoStructOffset(0x08)] uint32_t AtLeastOneClearEdges // Which edges must have at least one clear to use transition edge. should probably be some kind of flags?
15-
) : ILocoStruct;
15+
) : ILocoStruct
16+
{
17+
public bool Validate() => true;
18+
}
1619
}

Core/Objects/Airport/MovementNode.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.DatFileParsing;
33

44
namespace Core.Objects
@@ -10,5 +10,8 @@ public record MovementNode(
1010
[property: LocoStructOffset(0x02)] int16_t Y,
1111
[property: LocoStructOffset(0x04)] int16_t Z,
1212
[property: LocoStructOffset(0x06)] AirportMovementNodeFlags Flags
13-
) : ILocoStruct;
13+
) : ILocoStruct
14+
{
15+
public bool Validate() => true;
16+
}
1417
}

Core/Objects/BridgeObject.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44
using OpenLoco.ObjectEditor.Headers;
@@ -61,5 +61,39 @@ public ReadOnlySpan<byte> Save()
6161

6262
return headers.SelectMany(h => h.Write().ToArray()).ToArray();
6363
}
64+
65+
public bool Validate()
66+
{
67+
if (CostIndex > 32)
68+
{
69+
return false;
70+
}
71+
72+
if (-SellCostFactor > BaseCostFactor)
73+
{
74+
return false;
75+
}
76+
if (BaseCostFactor <= 0)
77+
{
78+
return false;
79+
}
80+
if (HeightCostFactor < 0)
81+
{
82+
return false;
83+
}
84+
if (var_06 != 16 && var_06 != 32)
85+
{
86+
return false;
87+
}
88+
if (SpanLength != 1 && SpanLength != 2 && SpanLength != 4)
89+
{
90+
return false;
91+
}
92+
if (NumCompatibleTrackMods > 7)
93+
{
94+
return false;
95+
}
96+
return NumCompatibleRoadMods <= 7;
97+
}
6498
}
65-
}
99+
}

Core/Objects/BuildingObject.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,9 @@ public ReadOnlySpan<byte> Save()
161161

162162
return ms.ToArray();
163163
}
164+
165+
public bool Validate()
166+
=> NumAnimations is not 0 and not > 63
167+
&& NumVariations is not 0 and <= 31;
164168
}
165169
}

Core/Objects/CargoObject.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44

@@ -53,5 +53,10 @@ public record CargoObject(
5353
[property: LocoStructOffset(0x1B)] uint16_t PaymentFactor,
5454
[property: LocoStructOffset(0x1D)] uint8_t PaymentIndex,
5555
[property: LocoStructOffset(0x1E)] uint8_t UnitSize
56-
) : ILocoStruct;
57-
}
56+
) : ILocoStruct
57+
{
58+
public bool Validate()
59+
=> var_02 <= 3840
60+
&& CargoTransferTime != 0;
61+
}
62+
}

Core/Objects/CliffEdgeObject.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44

@@ -11,5 +11,8 @@ namespace OpenLoco.ObjectEditor.Objects
1111
public record CliffEdgeObject(
1212
[property: LocoStructOffset(0x00), LocoString, Browsable(false)] string_id Name,
1313
[property: LocoStructOffset(0x02), LocoString, Browsable(false)] image_id Image
14-
) : ILocoStruct;
14+
) : ILocoStruct
15+
{
16+
public bool Validate() => true;
17+
}
1518
}

Core/Objects/ClimateObject.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44

@@ -18,5 +18,9 @@ public record ClimateObject(
1818
) : ILocoStruct
1919
{
2020
public const int Seasons = 4;
21+
22+
public bool Validate()
23+
=> WinterSnowLine <= SummerSnowLine
24+
&& FirstSeason < 4;
2125
}
2226
}

Core/Objects/CompetitorObject.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.ComponentModel;
1+
using System.ComponentModel;
22
using OpenLoco.ObjectEditor.Data;
33
using OpenLoco.ObjectEditor.DatFileParsing;
44

@@ -13,7 +13,7 @@ public record CompetitorObject(
1313
[property: LocoStructOffset(0x00), LocoString, Browsable(false)] string_id LastName,
1414
[property: LocoStructOffset(0x04)] uint32_t var_04,
1515
[property: LocoStructOffset(0x08)] uint32_t var_08,
16-
[property: LocoStructOffset(0x0C)] uint8_t Emotions,
16+
[property: LocoStructOffset(0x0C)] uint32_t Emotions,
1717
[property: LocoStructOffset(0x10), Browsable(false), LocoArrayLength(CompetitorObject.ImagesLength)] image_id[] Images,
1818
[property: LocoStructOffset(0x34)] uint8_t Intelligence,
1919
[property: LocoStructOffset(0x35)] uint8_t Aggressiveness,
@@ -22,5 +22,22 @@ public record CompetitorObject(
2222
) : ILocoStruct
2323
{
2424
public const int ImagesLength = 9;
25+
26+
public bool Validate()
27+
{
28+
if ((Emotions & (1 << 0)) == 0)
29+
{
30+
return false;
31+
}
32+
if (Intelligence < 1 || Intelligence > 9)
33+
{
34+
return false;
35+
}
36+
if (Aggressiveness < 1 || Aggressiveness > 9)
37+
{
38+
return false;
39+
}
40+
return Competitiveness >= 1 && Competitiveness <= 9;
41+
}
2542
}
2643
}

0 commit comments

Comments
 (0)