Skip to content

Commit

Permalink
start of object validation (#37)
Browse files Browse the repository at this point in the history
* start of object validation

* add vehicle validation

* finish object validation, and fix multiple industryobject bugs

* disallow saving if object fails validation
  • Loading branch information
LeftofZen authored Feb 23, 2024
1 parent e4884da commit 1cb28a0
Show file tree
Hide file tree
Showing 62 changed files with 950 additions and 161 deletions.
34 changes: 29 additions & 5 deletions Core/DatFileParsing/SawyerStreamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ namespace OpenLoco.ObjectEditor.DatFileParsing
{
public static class SawyerStreamReader
{
public static List<S5Header> LoadVariableCountS5Headers(ReadOnlySpan<byte> data, int count)
public static List<S5Header> LoadVariableCountS5Headers(ReadOnlySpan<byte> data, int max)
{
List<S5Header> result = [];
for (var i = 0; i < count; ++i)
for (var i = 0; i < max; ++i)
{
var header = S5Header.Read(data[..S5Header.StructLength]);
if (header.Checksum != 0 || header.Flags != 255)
if (data[0] != 0xFF)
{
result.Add(header);
var header = S5Header.Read(data[..S5Header.StructLength]);
if (header.Checksum != 0 || header.Flags != 255)
{
result.Add(header);
}
}

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

ValidateLocoStruct(s5Header, locoStruct, logger);

// add to object manager
SObjectManager.Add(newObj);

return new(new DatFileInfo(s5Header, objectHeader), newObj);
}

static void ValidateLocoStruct(S5Header s5Header, ILocoStruct locoStruct, ILogger? logger)
{
try
{
if (!locoStruct.Validate())
{
logger?.Warning($"\"{s5Header.Name}\" failed validation");
}
else
{
logger?.Info($"\"{s5Header.Name}\" validated successfully");
}
}
catch (NotImplementedException)
{
logger?.Debug2($"{s5Header.ObjectType} object type is missing validation function");
}
}

static string CStringToString(ReadOnlySpan<byte> data, Encoding enc)
{
var ptr = 0;
Expand Down
17 changes: 16 additions & 1 deletion Core/Objects/Airport/AirportObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand Down Expand Up @@ -164,5 +164,20 @@ public ReadOnlySpan<byte> Save()

return ms.ToArray();
}

public bool Validate()
{
if (CostIndex > 32)
{
return false;
}

if (-SellCostFactor > BuildCostFactor)
{
return false;
}

return BuildCostFactor > 0;
}
}
}
7 changes: 5 additions & 2 deletions Core/Objects/Airport/MovementEdge.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.DatFileParsing;

namespace Core.Objects
Expand All @@ -12,5 +12,8 @@ public record MovementEdge(
[property: LocoStructOffset(0x03)] uint8_t var_03,
[property: LocoStructOffset(0x04)] uint32_t MustBeClearEdges, // Which edges must be clear to use the transition edge. should probably be some kind of flags?
[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?
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate() => true;
}
}
7 changes: 5 additions & 2 deletions Core/Objects/Airport/MovementNode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.DatFileParsing;

namespace Core.Objects
Expand All @@ -10,5 +10,8 @@ public record MovementNode(
[property: LocoStructOffset(0x02)] int16_t Y,
[property: LocoStructOffset(0x04)] int16_t Z,
[property: LocoStructOffset(0x06)] AirportMovementNodeFlags Flags
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate() => true;
}
}
38 changes: 36 additions & 2 deletions Core/Objects/BridgeObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;
using OpenLoco.ObjectEditor.Headers;
Expand Down Expand Up @@ -61,5 +61,39 @@ public ReadOnlySpan<byte> Save()

return headers.SelectMany(h => h.Write().ToArray()).ToArray();
}

public bool Validate()
{
if (CostIndex > 32)
{
return false;
}

if (-SellCostFactor > BaseCostFactor)
{
return false;
}
if (BaseCostFactor <= 0)
{
return false;
}
if (HeightCostFactor < 0)
{
return false;
}
if (var_06 != 16 && var_06 != 32)
{
return false;
}
if (SpanLength != 1 && SpanLength != 2 && SpanLength != 4)
{
return false;
}
if (NumCompatibleTrackMods > 7)
{
return false;
}
return NumCompatibleRoadMods <= 7;
}
}
}
}
4 changes: 4 additions & 0 deletions Core/Objects/BuildingObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,9 @@ public ReadOnlySpan<byte> Save()

return ms.ToArray();
}

public bool Validate()
=> NumAnimations is not 0 and not > 63
&& NumVariations is not 0 and <= 31;
}
}
11 changes: 8 additions & 3 deletions Core/Objects/CargoObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand Down Expand Up @@ -53,5 +53,10 @@ public record CargoObject(
[property: LocoStructOffset(0x1B)] uint16_t PaymentFactor,
[property: LocoStructOffset(0x1D)] uint8_t PaymentIndex,
[property: LocoStructOffset(0x1E)] uint8_t UnitSize
) : ILocoStruct;
}
) : ILocoStruct
{
public bool Validate()
=> var_02 <= 3840
&& CargoTransferTime != 0;
}
}
7 changes: 5 additions & 2 deletions Core/Objects/CliffEdgeObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand All @@ -11,5 +11,8 @@ namespace OpenLoco.ObjectEditor.Objects
public record CliffEdgeObject(
[property: LocoStructOffset(0x00), LocoString, Browsable(false)] string_id Name,
[property: LocoStructOffset(0x02), LocoString, Browsable(false)] image_id Image
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate() => true;
}
}
6 changes: 5 additions & 1 deletion Core/Objects/ClimateObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand All @@ -18,5 +18,9 @@ public record ClimateObject(
) : ILocoStruct
{
public const int Seasons = 4;

public bool Validate()
=> WinterSnowLine <= SummerSnowLine
&& FirstSeason < 4;
}
}
21 changes: 19 additions & 2 deletions Core/Objects/CompetitorObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand All @@ -13,7 +13,7 @@ public record CompetitorObject(
[property: LocoStructOffset(0x00), LocoString, Browsable(false)] string_id LastName,
[property: LocoStructOffset(0x04)] uint32_t var_04,
[property: LocoStructOffset(0x08)] uint32_t var_08,
[property: LocoStructOffset(0x0C)] uint8_t Emotions,
[property: LocoStructOffset(0x0C)] uint32_t Emotions,
[property: LocoStructOffset(0x10), Browsable(false), LocoArrayLength(CompetitorObject.ImagesLength)] image_id[] Images,
[property: LocoStructOffset(0x34)] uint8_t Intelligence,
[property: LocoStructOffset(0x35)] uint8_t Aggressiveness,
Expand All @@ -22,5 +22,22 @@ public record CompetitorObject(
) : ILocoStruct
{
public const int ImagesLength = 9;

public bool Validate()
{
if ((Emotions & (1 << 0)) == 0)
{
return false;
}
if (Intelligence < 1 || Intelligence > 9)
{
return false;
}
if (Aggressiveness < 1 || Aggressiveness > 9)
{
return false;
}
return Competitiveness >= 1 && Competitiveness <= 9;
}
}
}
18 changes: 16 additions & 2 deletions Core/Objects/CurrencyObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand All @@ -15,5 +15,19 @@ public record CurrencyObject(
[property: LocoStructOffset(0x06), Browsable(false)] image_id ObjectIcon,
[property: LocoStructOffset(0x0A)] uint8_t Separator,
[property: LocoStructOffset(0x0B)] uint8_t Factor
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate()
{
if (Separator > 4)
{
return false;
}
if (Factor > 3)
{
return false;
}
return true;
}
}
}
16 changes: 15 additions & 1 deletion Core/Objects/DockObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;
using OpenLoco.ObjectEditor.Types;
Expand Down Expand Up @@ -78,5 +78,19 @@ public ReadOnlySpan<byte> Save()
.Concat(var_1C)
.Concat(new byte[] { 0xFF })
.ToArray();
public bool Validate()
{
if (CostIndex > 32)
{
return false;
}

if (-SellCostFactor > BuildCostFactor)
{
return false;
}

return BuildCostFactor > 0;
}
}
}
7 changes: 5 additions & 2 deletions Core/Objects/HillShapesObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.Data;
using OpenLoco.ObjectEditor.DatFileParsing;

Expand All @@ -15,5 +15,8 @@ public record HillShapesObject(
[property: LocoStructOffset(0x04), Browsable(false)] image_id Image,
[property: LocoStructOffset(0x08), Browsable(false)] image_id ImageHill,
[property: LocoStructOffset(0x0C), LocoArrayLength(0x0E - 0x0C), Browsable(false)] uint8_t[] pad_0C
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate() => true;
}
}
11 changes: 9 additions & 2 deletions Core/Objects/Industry/BuildingPartAnimation.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using OpenLoco.ObjectEditor.DatFileParsing;

namespace Core.Objects
Expand All @@ -9,5 +9,12 @@ namespace Core.Objects
public record BuildingPartAnimation(
[property: LocoStructOffset(0x00)] uint8_t NumFrames, // Must be a power of 2 (0 = no part animation, could still have animation sequence)
[property: LocoStructOffset(0x01)] uint8_t AnimationSpeed // Also encodes in bit 7 if the animation is position modified
) : ILocoStruct;
) : ILocoStruct
{
public bool Validate()
=> IsPowerOfTwo(NumFrames);

static bool IsPowerOfTwo(uint8_t x)
=> (x & (x - 1)) == 0 && x > 0;
}
}
Loading

0 comments on commit 1cb28a0

Please sign in to comment.