mirror of
https://github.com/kwsch/NHSE.git
synced 2026-08-06 09:43:58 -05:00
Misc tweaks, sealed classes
This commit is contained in:
parent
666912a93b
commit
7ea5c03aa3
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class ItemMutator : BatchMutator<Item>
|
||||
public sealed class ItemMutator : BatchMutator<Item>
|
||||
{
|
||||
public readonly ItemReflection Reflect = ItemReflection.Default;
|
||||
private const char CONST_POINTER = '*';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class ItemProcessor(BatchMutator<Item> mut) : BatchProcessor<Item>(mut)
|
||||
public sealed class ItemProcessor(BatchMutator<Item> mut) : BatchProcessor<Item>(mut)
|
||||
{
|
||||
protected override bool CanModify(Item item) => true;
|
||||
protected override bool Finalize(Item item) => true;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class ItemReflection
|
||||
public sealed class ItemReflection
|
||||
{
|
||||
public static ItemReflection Default { get; } = new();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@ namespace NHSE.Core;
|
|||
/// Creates a HorizonSave from a file provider.
|
||||
/// </remarks>
|
||||
/// <param name="provider">Provider for reading/writing save files.</param>
|
||||
public class HorizonSave(ISaveFileProvider provider)
|
||||
public sealed class HorizonSave(ISaveFileProvider provider)
|
||||
{
|
||||
public readonly MainSave Main = new(provider);
|
||||
public readonly Player[] Players = Player.ReadMany(provider);
|
||||
private readonly ISaveFileProvider Provider = provider;
|
||||
public readonly IReadOnlyList<Player> Players = Player.ReadMany(provider);
|
||||
|
||||
public override string ToString() => $"{Players[0].Personal.TownName} - {Players[0]}";
|
||||
|
||||
|
|
@ -57,7 +56,7 @@ public void Save(uint seed)
|
|||
pair.Save(seed);
|
||||
}
|
||||
}
|
||||
Provider.Flush();
|
||||
provider.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets10 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets10 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x108;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets11 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets11 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets110 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets110 : MainSaveOffsets
|
||||
{
|
||||
public override int PatternCount => PatternCount2;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
/// <remarks>Same as <see cref="MainSaveOffsets110"/></remarks>
|
||||
public class MainSaveOffsets111 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets111 : MainSaveOffsets
|
||||
{
|
||||
public override int PatternCount => PatternCount2;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets12 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets12 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets13 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets13 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets14 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets14 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets15 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets15 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets16 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets16 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets17 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets17 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
/// <remarks>Same as <see cref="MainSaveOffsets17"/></remarks>.
|
||||
public class MainSaveOffsets18 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets18 : MainSaveOffsets
|
||||
{
|
||||
#region GSaveLand
|
||||
public const int GSaveLandStart = 0x110;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets19 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets19 : MainSaveOffsets
|
||||
{
|
||||
public override int PatternCount => PatternCount2;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
/// <remarks>Same as <see cref="MainSaveOffsets110"/></remarks>
|
||||
public class MainSaveOffsets20 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets20 : MainSaveOffsets
|
||||
{
|
||||
public override int PatternCount => PatternCount2;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// <inheritdoc cref="MainSaveOffsets"/>
|
||||
/// </summary>
|
||||
public class MainSaveOffsets30 : MainSaveOffsets
|
||||
public sealed class MainSaveOffsets30 : MainSaveOffsets
|
||||
{
|
||||
public override int PatternCount => PatternCount2;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace NHSE.Core;
|
|||
/// Interact-able structure that can be entered by the player.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)]
|
||||
public class Building
|
||||
public sealed class Building
|
||||
{
|
||||
public const int SIZE = 0x14;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,4 +35,6 @@ public enum BuildingType : ushort
|
|||
Incline = 27,
|
||||
ReddsTreasureTrawler = 28,
|
||||
Studio = 29,
|
||||
|
||||
Hotel = 42,
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Simple design pattern
|
||||
/// </summary>
|
||||
public class DesignPattern(Memory<byte> Raw) : IVillagerOrigin
|
||||
public sealed class DesignPattern(Memory<byte> Raw) : IVillagerOrigin
|
||||
{
|
||||
public const int Width = 32;
|
||||
public const int Height = 32;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Advanced design pattern with 4 sheets arranged in a square.
|
||||
/// </summary>
|
||||
public class DesignPatternPRO(Memory<byte> Raw) : IVillagerOrigin
|
||||
public sealed class DesignPatternPRO(Memory<byte> Raw) : IVillagerOrigin
|
||||
{
|
||||
public const int Width = 32;
|
||||
public const int Height = 32;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public static void DumpPlayerHouses(this IReadOnlyList<IPlayerHouse> houses, IRe
|
|||
/// <param name="path">Path to dump to</param>
|
||||
public static void DumpPlayerHouses(this HorizonSave sav, string path)
|
||||
{
|
||||
var count = Math.Min(sav.Players.Length, MainSaveOffsets.PlayerCount);
|
||||
var count = Math.Min(sav.Players.Count, MainSaveOffsets.PlayerCount);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var p = sav.Players[i];
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class ItemArrayEditor<T> where T : Item, ICopyableItem<T>
|
||||
public sealed record ItemArrayEditor<T>(IReadOnlyList<T> Items)
|
||||
where T : Item, ICopyableItem<T>
|
||||
{
|
||||
public readonly IReadOnlyList<T> Items;
|
||||
public ItemArrayEditor(IReadOnlyList<T> items) => Items = items;
|
||||
public int ItemSize => Items[0].Size;
|
||||
public int TotalSize => Items.Count * ItemSize;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,38 +5,19 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Metadata for an item's customization permissions
|
||||
/// </summary>
|
||||
public class ItemRemakeInfo
|
||||
public sealed record ItemRemakeInfo(
|
||||
short Index,
|
||||
ushort ItemUniqueID,
|
||||
sbyte ReBodyPatternNum,
|
||||
byte[] ReBodyPatternColors0,
|
||||
byte[] ReBodyPatternColors1,
|
||||
byte[] ReFabricPatternColors0,
|
||||
byte[] ReFabricPatternColors1,
|
||||
bool ReFabricPattern0VisibleOff)
|
||||
{
|
||||
public const int BodyColorCountMax = 8;
|
||||
public const int NoColor = (int)ItemCustomColor.None; // 14
|
||||
|
||||
public readonly short Index;
|
||||
public readonly ushort ItemUniqueID;
|
||||
public readonly sbyte ReBodyPatternNum; // count of body colors
|
||||
|
||||
public readonly byte[] ReBodyPatternColors0;
|
||||
public readonly byte[] ReBodyPatternColors1;
|
||||
|
||||
public readonly byte[] ReFabricPatternColors0;
|
||||
public readonly byte[] ReFabricPatternColors1;
|
||||
|
||||
public readonly bool ReFabricPattern0VisibleOff;
|
||||
|
||||
public ItemRemakeInfo(short index, ushort id, sbyte count, byte[] bc0, byte[] bc1, byte[] fc0, byte[] fc1, bool fp0)
|
||||
{
|
||||
Index = index;
|
||||
ItemUniqueID = id;
|
||||
ReBodyPatternNum = count;
|
||||
|
||||
ReBodyPatternColors0 = bc0;
|
||||
ReBodyPatternColors1 = bc1;
|
||||
|
||||
ReFabricPatternColors0 = fc0;
|
||||
ReFabricPatternColors1 = fc1;
|
||||
|
||||
ReFabricPattern0VisibleOff = fp0;
|
||||
}
|
||||
|
||||
private const string Invalid = nameof(Invalid);
|
||||
|
||||
public bool HasBodyColor(int variant) => ReBodyPatternColors0[variant] != NoColor || ReBodyPatternColors1[variant] != NoColor;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Manages the <see cref="Item"/> data for the player's outside overworld.
|
||||
/// </summary>
|
||||
public class FieldItemManager
|
||||
public sealed class FieldItemManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Base layer of items
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class RoomItemManager
|
||||
public sealed class RoomItemManager
|
||||
{
|
||||
public readonly RoomItemLayer[] Layers;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace NHSE.Core;
|
|||
/// Represents a Terraform-able terrain tile.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class TerrainTile
|
||||
public sealed class TerrainTile
|
||||
{
|
||||
// tile[2] (u16 model, u16 variation, u16 angle)
|
||||
// u16 elevation
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
namespace NHSE.Core;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public class GSaveFg
|
||||
public sealed class GSaveFg
|
||||
{
|
||||
public const int SIZE = 0x928;
|
||||
private const int _7b9816fbCount = 0x900;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
namespace NHSE.Core;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public class GSaveVisitorNpc
|
||||
public sealed class GSaveVisitorNpc
|
||||
{
|
||||
public const int SIZE = 0x78;
|
||||
private const int Days = 7;
|
||||
|
|
@ -46,7 +46,7 @@ public struct V3f
|
|||
public float Y { get; set; }
|
||||
public float Z { get; set; }
|
||||
|
||||
public override string ToString() => $"({X},{Y},{Z})";
|
||||
public readonly override string ToString() => $"({X},{Y},{Z})";
|
||||
}
|
||||
|
||||
public enum VisitorNPC
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class MapManager(MainSave sav) : MapTerrainStructure(sav)
|
||||
public sealed class MapManager(MainSave sav) : MapTerrainStructure(sav)
|
||||
{
|
||||
public readonly FieldItemManager Items = new(sav);
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ public class MapManager(MainSave sav) : MapTerrainStructure(sav)
|
|||
public FieldItemLayer CurrentLayer => MapLayer == 0 ? Items.Layer1 : Items.Layer2;
|
||||
}
|
||||
|
||||
public class MapTerrainStructure(MainSave sav)
|
||||
public abstract class MapTerrainStructure(MainSave sav)
|
||||
{
|
||||
public readonly TerrainLayer Terrain = new(sav.GetTerrainTiles(), sav.GetAcreBytes());
|
||||
public readonly IReadOnlyList<Building> Buildings = sav.Buildings;
|
||||
|
|
|
|||
|
|
@ -2,25 +2,19 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class MapView
|
||||
public abstract class MapView(MapManager m, int scale = 16)
|
||||
{
|
||||
private const int ViewInterval = 2;
|
||||
public readonly MapManager Map;
|
||||
public readonly MapManager Map = m;
|
||||
|
||||
public int MapScale { get; } = 1;
|
||||
public int AcreScale { get; }
|
||||
public int AcreScale { get; } = scale;
|
||||
public int TerrainScale => AcreScale * 2;
|
||||
|
||||
// Top Left Anchor Coordinates
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
protected MapView(MapManager m, int scale = 16)
|
||||
{
|
||||
AcreScale = scale;
|
||||
Map = m;
|
||||
}
|
||||
|
||||
public bool CanUp => Y != 0;
|
||||
public bool CanDown => Y < Map.CurrentLayer.TileInfo.TotalHeight - Map.CurrentLayer.TileInfo.ViewHeight;
|
||||
public bool CanLeft => X != 0;
|
||||
|
|
|
|||
|
|
@ -4,15 +4,12 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class Museum
|
||||
public sealed class Museum(Memory<byte> raw)
|
||||
{
|
||||
public const int SIZE = 0x3404;
|
||||
public const int EntryCount = 1024;
|
||||
|
||||
public readonly Memory<byte> Raw;
|
||||
public Span<byte> Data => Raw.Span;
|
||||
|
||||
public Museum(Memory<byte> data) => Raw = data;
|
||||
public Span<byte> Data => raw.Span;
|
||||
|
||||
public int MuseumLevel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,27 +5,17 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class MuseumEditor
|
||||
public sealed record MuseumEditor(Museum Museum)
|
||||
{
|
||||
public readonly Museum Museum;
|
||||
public readonly GSaveDate[] Dates;
|
||||
public readonly Item[] Items;
|
||||
public readonly byte[] Players;
|
||||
|
||||
public MuseumEditor(Museum museum)
|
||||
{
|
||||
Museum = museum;
|
||||
Dates = museum.GetDates();
|
||||
Items = museum.GetItems();
|
||||
Players = museum.GetPlayers();
|
||||
}
|
||||
public readonly GSaveDate[] Dates = Museum.GetDates();
|
||||
public readonly Item[] Items = Museum.GetItems();
|
||||
public readonly byte[] Players = Museum.GetPlayers();
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var museum = Museum;
|
||||
museum.SetDates(Dates);
|
||||
museum.SetItems(Items);
|
||||
museum.SetPlayers(Players);
|
||||
Museum.SetDates(Dates);
|
||||
Museum.SetItems(Items);
|
||||
Museum.SetPlayers(Players);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetDonationSummary(GameStrings str)
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class RecipeBook
|
||||
public sealed class RecipeBook(Memory<byte> raw)
|
||||
{
|
||||
private const int BitFlagArraySize = 0x100;
|
||||
private const int BitFlagArrayCount = 4;
|
||||
public const int SIZE = BitFlagArraySize * BitFlagArrayCount;
|
||||
public const ushort RecipeCount = BitFlagArraySize * 8;
|
||||
|
||||
private readonly Memory<byte> Raw;
|
||||
private Span<byte> Data => Raw.Span;
|
||||
public RecipeBook(Memory<byte> raw) => Raw = raw;
|
||||
private Span<byte> Data => raw.Span;
|
||||
|
||||
public void Save(Span<byte> data) => Data.CopyTo(data);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Used for allowing a struct to be mutated in a PropertyGrid.
|
||||
/// </summary>
|
||||
public class ValueTypeTypeConverter : ExpandableObjectConverter
|
||||
public sealed class ValueTypeTypeConverter : ExpandableObjectConverter
|
||||
{
|
||||
public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,51 +6,24 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Multi-milestone definition for tracking game-play achievements.
|
||||
/// </summary>
|
||||
public class LifeSupportAchievement : INamedValue
|
||||
public sealed record LifeSupportAchievement(
|
||||
ushort Index,
|
||||
byte AchievementCount,
|
||||
uint Threshold1,
|
||||
uint Threshold2,
|
||||
uint Threshold3,
|
||||
uint Threshold4,
|
||||
uint Threshold5,
|
||||
short FlagLand,
|
||||
short FlagPlayer,
|
||||
string Name)
|
||||
: INamedValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Amount of milestones an achievement can have.
|
||||
/// </summary>
|
||||
public const int MilestoneMax = 6;
|
||||
|
||||
public readonly short FlagLand;
|
||||
public readonly short FlagPlayer;
|
||||
|
||||
public ushort Index { get; }
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary> Total number of milestones for this achievement type. </summary>
|
||||
public readonly int AchievementCount;
|
||||
|
||||
/// <summary> First Milestone's Satisfaction Threshold </summary>
|
||||
public readonly uint Threshold1;
|
||||
|
||||
/// <summary> Second Milestone's Satisfaction Threshold </summary>
|
||||
public readonly uint Threshold2;
|
||||
|
||||
/// <summary> Third Milestone's Satisfaction Threshold </summary>
|
||||
public readonly uint Threshold3;
|
||||
|
||||
/// <summary> Fourth Milestone's Satisfaction Threshold </summary>
|
||||
public readonly uint Threshold4;
|
||||
|
||||
/// <summary> Fifth Milestone's Satisfaction Threshold </summary>
|
||||
public readonly uint Threshold5;
|
||||
|
||||
public LifeSupportAchievement(ushort index, byte max, uint t1, uint t2, uint t3, uint t4, uint t5, short land, short player, string name)
|
||||
{
|
||||
Index = index;
|
||||
AchievementCount = max;
|
||||
Threshold1 = t1;
|
||||
Threshold2 = t2;
|
||||
Threshold3 = t3;
|
||||
Threshold4 = t4;
|
||||
Threshold5 = t5;
|
||||
FlagLand = land;
|
||||
FlagPlayer = player;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public uint MaxThreshold => Math.Max(Threshold1, Math.Max(Threshold2, Math.Max(Threshold3, Math.Max(Threshold4, Threshold5))));
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
namespace NHSE.Core;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = SIZE)]
|
||||
public class TurnipStonk // GSaveShopKabu
|
||||
public sealed class TurnipStonk // GSaveShopKabu
|
||||
{
|
||||
public const int SIZE = 0x44;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,11 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class GSaveMemory : IVillagerOrigin
|
||||
public sealed class GSaveMemory(Memory<byte> raw) : IVillagerOrigin
|
||||
{
|
||||
public const int SIZE = 0x5F0;
|
||||
|
||||
public readonly Memory<byte> Raw;
|
||||
public Span<byte> Data => Raw.Span;
|
||||
|
||||
public GSaveMemory(Memory<byte> data) => Raw = data;
|
||||
public Span<byte> Data => raw.Span;
|
||||
|
||||
public GSavePlayerId PlayerId
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,15 +4,12 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class PlayerHouse1 : IPlayerHouse
|
||||
public class PlayerHouse1(Memory<byte> raw) : IPlayerHouse
|
||||
{
|
||||
public const int SIZE = 0x26400;
|
||||
public virtual string Extension => "nhph";
|
||||
|
||||
public readonly Memory<byte> Raw;
|
||||
public Span<byte> Data => Raw.Span;
|
||||
|
||||
public PlayerHouse1(Memory<byte> data) => Raw = data;
|
||||
public Span<byte> Data => raw.Span;
|
||||
|
||||
public byte[] Write() => Data.ToArray();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class PlayerHouse2 : PlayerHouse1
|
||||
public sealed class PlayerHouse2(Memory<byte> raw) : PlayerHouse1(raw)
|
||||
{
|
||||
public new const int SIZE = 0x28A28;
|
||||
public override string Extension => "nhph2";
|
||||
|
||||
public PlayerHouse2(Memory<byte> data) : base(data) { }
|
||||
|
||||
public override IPlayerRoom GetRoom(int roomIndex)
|
||||
{
|
||||
if ((uint)roomIndex >= MaxRoom)
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class PlayerRoom2(Memory<byte> raw) : PlayerRoom1(raw)
|
||||
public sealed class PlayerRoom2(Memory<byte> raw) : PlayerRoom1(raw)
|
||||
{
|
||||
public new const int SIZE = 0x6C24;
|
||||
public new virtual string Extension => "nhpr2";
|
||||
public override string Extension => "nhpr2";
|
||||
|
||||
/*
|
||||
s_665e9093 ExtraEffectLayerList[2]; // @0x65c8 size 0x320, align 2
|
||||
|
|
@ -47,7 +47,7 @@ public GSaveMusicBoxInfo MusicBoxInfo
|
|||
|
||||
// 3 bytes padding
|
||||
|
||||
public s_e13a81f4 _cfb139b9
|
||||
public s_e13a81f4 Unk_cfb139b9
|
||||
{
|
||||
get => Data.Slice(0x6C10, s_e13a81f4.SIZE).ToStructure<s_e13a81f4>();
|
||||
set => value.ToBytes().CopyTo(Data[0x6C10..]);
|
||||
|
|
|
|||
|
|
@ -8,14 +8,12 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Villager object format from 1.0 to update 1.4
|
||||
/// </summary>
|
||||
public sealed class Villager1 : IVillager
|
||||
public sealed class Villager1(Memory<byte> raw) : IVillager
|
||||
{
|
||||
public const int SIZE = 0x12AB0;
|
||||
public string Extension => "nhv";
|
||||
|
||||
public readonly Memory<byte> Raw;
|
||||
public Span<byte> Data => Raw.Span;
|
||||
public Villager1(Memory<byte> data) => Raw = data;
|
||||
public Span<byte> Data => raw.Span;
|
||||
public byte[] Write() => Data.ToArray();
|
||||
|
||||
public byte Species { get => Data[0]; set => Data[0] = value; }
|
||||
|
|
@ -34,7 +32,7 @@ public GSaveMemory GetMemory(int index)
|
|||
if ((uint) index >= PlayerMemoryCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
var bytes = Raw.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE);
|
||||
var bytes = raw.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE);
|
||||
return new GSaveMemory(bytes);
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +113,7 @@ public GSaveRoomFloorWall Room
|
|||
|
||||
public DesignPatternPRO Design
|
||||
{
|
||||
get => new(Raw.Slice(0x12128, DesignPatternPRO.SIZE));
|
||||
get => new(raw.Slice(0x12128, DesignPatternPRO.SIZE));
|
||||
set => value.Data.CopyTo(Data[0x12128..]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class VillagerHouse1 : IVillagerHouse
|
||||
public class VillagerHouse1(Memory<byte> raw) : IVillagerHouse
|
||||
{
|
||||
public const int SIZE = 0x1D4;
|
||||
public const int ItemCount = 36;
|
||||
public virtual string Extension => "nhvh";
|
||||
|
||||
public readonly Memory<byte> Raw;
|
||||
public VillagerHouse1(Memory<byte> raw) => Raw = raw;
|
||||
public Span<byte> Data => Raw.Span;
|
||||
public Span<byte> Data => raw.Span;
|
||||
|
||||
public byte[] Write() => Data.ToArray();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,11 @@
|
|||
|
||||
namespace NHSE.Core;
|
||||
|
||||
public class VillagerHouse2 : VillagerHouse1
|
||||
public sealed class VillagerHouse2(Memory<byte> raw) : VillagerHouse1(raw)
|
||||
{
|
||||
public new const int SIZE = 0x12E8;
|
||||
public override string Extension => "nhvh2";
|
||||
|
||||
public VillagerHouse2(Memory<byte> data) : base(data) { }
|
||||
|
||||
// 0x1D4-0x12DB -- 0x1108 sized structure
|
||||
// 0x12DC -- 8 byte item
|
||||
// 0x12E4 -- 1 byte
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace NHSE.Core;
|
|||
/// <summary>
|
||||
/// Key Value pair for a displayed <see cref="T:System.String" /> and underlying <see cref="T:System.Int32" /> value.
|
||||
/// </summary>
|
||||
public record ComboItem(string Text, int Value);
|
||||
public sealed record ComboItem(string Text, int Value);
|
||||
|
||||
public static class ComboItemUtil
|
||||
{
|
||||
|
|
@ -25,10 +25,10 @@ public static List<ComboItem> GetArray(ReadOnlySpan<string> items)
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<ComboItem> GetArray<T>(Type t) where T : struct, IFormattable
|
||||
public static List<ComboItem> GetArray<T>() where T : struct, Enum, IFormattable
|
||||
{
|
||||
var names = Enum.GetNames(t);
|
||||
var values = (T[])Enum.GetValues(t);
|
||||
var names = Enum.GetNames<T>();
|
||||
var values = Enum.GetValues<T>();
|
||||
|
||||
var acres = new List<ComboItem>(names.Length);
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
|
|
|
|||
|
|
@ -3,12 +3,8 @@
|
|||
|
||||
namespace NHSE.Injection;
|
||||
|
||||
public class AutoInjector
|
||||
public sealed record AutoInjector(IDataInjector Injector, Action<InjectionResult> DoRead, Action<InjectionResult> DoWrite)
|
||||
{
|
||||
public readonly IDataInjector Injector;
|
||||
private readonly Action<InjectionResult> AfterRead;
|
||||
private readonly Action<InjectionResult> AfterWrite;
|
||||
|
||||
public bool AutoInjectEnabled { private get; set; }
|
||||
|
||||
public bool ValidateEnabled
|
||||
|
|
@ -17,13 +13,6 @@ public bool ValidateEnabled
|
|||
set => Injector.ValidateEnabled = value;
|
||||
}
|
||||
|
||||
public AutoInjector(IDataInjector inj, Action<InjectionResult> read, Action<InjectionResult> write)
|
||||
{
|
||||
Injector = inj;
|
||||
AfterRead = read;
|
||||
AfterWrite = write;
|
||||
}
|
||||
|
||||
public void Validate() => Injector.Validate();
|
||||
|
||||
public InjectionResult Read(bool force = false)
|
||||
|
|
@ -34,7 +23,7 @@ public InjectionResult Read(bool force = false)
|
|||
try
|
||||
{
|
||||
var result = Injector.Read();
|
||||
AfterRead(result);
|
||||
DoRead(result);
|
||||
return result;
|
||||
}
|
||||
catch (IndexOutOfRangeException ex)
|
||||
|
|
@ -51,7 +40,7 @@ public InjectionResult Write(bool force = false)
|
|||
try
|
||||
{
|
||||
var result = Injector.Write();
|
||||
AfterWrite(result);
|
||||
DoWrite(result);
|
||||
return result;
|
||||
}
|
||||
catch (IndexOutOfRangeException ex)
|
||||
|
|
|
|||
|
|
@ -1,35 +1,27 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NHSE.Core;
|
||||
|
||||
namespace NHSE.Injection;
|
||||
|
||||
public class PocketInjector : IDataInjector
|
||||
public sealed class PocketInjector(IReadOnlyList<Item> items, IRAMReadWriter bot) : IDataInjector
|
||||
{
|
||||
private readonly IReadOnlyList<Item> Items;
|
||||
private readonly IRAMReadWriter Bot;
|
||||
public bool Connected => Bot.Connected;
|
||||
public bool Connected => bot.Connected;
|
||||
|
||||
private byte[]? LastData { get; set; }
|
||||
public uint WriteOffset { private get; set; }
|
||||
public bool ValidateEnabled { get; set; } = true;
|
||||
public bool SpoofInventoryWrite { get; set; }
|
||||
private static readonly Item DroppableOnlyItem = new(0x9C9); // Gold nugget
|
||||
|
||||
public PocketInjector(IReadOnlyList<Item> items, IRAMReadWriter bot)
|
||||
{
|
||||
Items = items;
|
||||
Bot = bot;
|
||||
}
|
||||
private static readonly Item DroppableOnlyItem = new(0x9C9); // Gold nugget
|
||||
|
||||
public bool ReadValidate(out byte[] data)
|
||||
{
|
||||
PlayerItemSet.GetOffsetLength(WriteOffset, out var offset, out var size);
|
||||
data = Bot.ReadBytes(offset, size);
|
||||
data = bot.ReadBytes(offset, size);
|
||||
return Validate(data);
|
||||
}
|
||||
|
||||
private byte[]? LastData;
|
||||
|
||||
public InjectionResult Read()
|
||||
{
|
||||
if (!ReadValidate(out var data))
|
||||
|
|
@ -38,7 +30,7 @@ public InjectionResult Read()
|
|||
if (LastData?.SequenceEqual(data) == true)
|
||||
return InjectionResult.Same;
|
||||
|
||||
PlayerItemSet.ReadPlayerInventory(data, Items);
|
||||
PlayerItemSet.ReadPlayerInventory(data, items);
|
||||
|
||||
LastData = data;
|
||||
|
||||
|
|
@ -52,9 +44,9 @@ public InjectionResult Write()
|
|||
|
||||
var orig = (byte[])data.Clone();
|
||||
|
||||
var items = !SpoofInventoryWrite ? Items : Enumerable.Repeat(DroppableOnlyItem, Items.Count).ToArray();
|
||||
var items1 = !SpoofInventoryWrite ? items : Enumerable.Repeat(DroppableOnlyItem, items.Count).ToArray();
|
||||
|
||||
PlayerItemSet.WritePlayerInventory(data, items);
|
||||
PlayerItemSet.WritePlayerInventory(data, items1);
|
||||
|
||||
if (data.SequenceEqual(orig))
|
||||
return InjectionResult.Same;
|
||||
|
|
@ -63,7 +55,7 @@ public InjectionResult Write()
|
|||
if (size != data.Length)
|
||||
return InjectionResult.FailBadSize;
|
||||
|
||||
Bot.WriteBytes(data, offset);
|
||||
bot.WriteBytes(data, offset);
|
||||
|
||||
LastData = data;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace NHSE.Injection;
|
||||
|
||||
public class SysBot : IRAMReadWriter
|
||||
public sealed class SysBot : IRAMReadWriter
|
||||
{
|
||||
public string IP = "192.168.1.65";
|
||||
public int Port = 6000;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace NHSE.Injection;
|
||||
|
||||
public class USBBot : IRAMReadWriter
|
||||
public sealed class USBBot : IRAMReadWriter
|
||||
{
|
||||
private UsbDevice? SwDevice;
|
||||
private UsbEndpointReader? reader;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class BCSV
|
||||
public sealed class BCSV
|
||||
{
|
||||
public static readonly BCSVEnumDictionary EnumLookup = new(Resources.specs_130.Split('\n'));
|
||||
public static bool DecodeColumnNames { private get; set; } = true;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class BCSVEnumDictionary
|
||||
public sealed class BCSVEnumDictionary
|
||||
{
|
||||
private readonly Dictionary<uint, string> Lookup = [];
|
||||
private readonly Dictionary<uint, string> _lookup = [];
|
||||
|
||||
public BCSVEnumDictionary(IEnumerable<string> lines)
|
||||
{
|
||||
|
|
@ -35,7 +35,7 @@ private void AddColumnName(string trim)
|
|||
var slice = value.AsSpan(2, value.Length - 3);
|
||||
var hex = StringUtil.GetHexValue(slice);
|
||||
|
||||
if (Lookup.TryGetValue(hex, out var exist))
|
||||
if (_lookup.TryGetValue(hex, out var exist))
|
||||
{
|
||||
if (exist == name)
|
||||
return;
|
||||
|
|
@ -43,7 +43,7 @@ private void AddColumnName(string trim)
|
|||
return;
|
||||
}
|
||||
|
||||
Lookup.Add(hex, name);
|
||||
_lookup.Add(hex, name);
|
||||
}
|
||||
|
||||
private void AddEnumName(string trim)
|
||||
|
|
@ -56,7 +56,7 @@ private void AddEnumName(string trim)
|
|||
return;
|
||||
|
||||
var hash = CRC32.Compute(text);
|
||||
if (Lookup.TryGetValue(hash, out var exist))
|
||||
if (_lookup.TryGetValue(hash, out var exist))
|
||||
{
|
||||
if (exist == text)
|
||||
return;
|
||||
|
|
@ -64,10 +64,10 @@ private void AddEnumName(string trim)
|
|||
return;
|
||||
}
|
||||
|
||||
Lookup.Add(hash, text);
|
||||
_lookup.Add(hash, text);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Dump() => Lookup.Select(z => $"{z.Key:X8}\t{z.Value}");
|
||||
public IEnumerable<string> Dump() => _lookup.Select(z => $"{z.Key:X8}\t{z.Value}");
|
||||
|
||||
public string this[uint key] => Lookup.TryGetValue(key, out var val) ? val : $"0x{key:X8}";
|
||||
public string this[uint key] => _lookup.TryGetValue(key, out var val) ? val : $"0x{key:X8}";
|
||||
}
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
namespace NHSE.Parsing;
|
||||
|
||||
public class BCSVFieldParam
|
||||
public sealed record BCSVFieldParam(uint ColumnKey, int Offset, int Index)
|
||||
{
|
||||
public const int SIZE = 8;
|
||||
public readonly uint ColumnKey;
|
||||
public readonly int Offset;
|
||||
public readonly int Index;
|
||||
|
||||
public BCSVFieldParam(uint key, int offset, int index)
|
||||
{
|
||||
ColumnKey = key;
|
||||
Offset = offset;
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ public static class GameMSBTDumper
|
|||
/// <param name="dest">Destination folder where the dumps will be saved.</param>
|
||||
/// <param name="csv">Convert all <see cref="MSBT"/> files to CSV for easy viewing.</param>
|
||||
/// <param name="delim">Delimiter when exporting the <see cref="csv"/> files</param>
|
||||
public static void UpdateDumps(string root, string dest, bool csv = true, char delim = '\t')
|
||||
public static void UpdateDumps(string root, string dest, bool csv = false, char delim = '\t')
|
||||
{
|
||||
if (csv)
|
||||
UpdateCSV(root, Path.Combine(dest, "csv"), delim);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class LBL1() : MSBTSection(string.Empty, [])
|
||||
public sealed class LBL1() : MSBTSection(string.Empty, [])
|
||||
{
|
||||
public uint NumberOfGroups;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBT
|
||||
public sealed class MSBT
|
||||
{
|
||||
public readonly MSBTHeader Header;
|
||||
public readonly LBL1 LBL1 = new();
|
||||
|
|
@ -78,7 +78,7 @@ private void ReadLBL1(BinaryReaderX br)
|
|||
var length = Convert.ToUInt32(br.ReadByte());
|
||||
var name = br.ReadString((int)length);
|
||||
var index = br.ReadUInt32();
|
||||
var lbl = new MSBTLabel(name) {Index = index, Length = length};
|
||||
var lbl = new MSBTLabel {Name = name, Index = index, Length = length};
|
||||
LBL1.Labels.Add(lbl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBTGroup
|
||||
public sealed record MSBTGroup
|
||||
{
|
||||
public uint NumberOfLabels;
|
||||
public uint Offset;
|
||||
public required uint NumberOfLabels { get; init; }
|
||||
public required uint Offset { get; init; }
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBTHeader
|
||||
public sealed class MSBTHeader
|
||||
{
|
||||
public readonly string Identifier; // MsgStdBn
|
||||
public readonly byte[] ByteOrderMark;
|
||||
|
|
|
|||
|
|
@ -2,19 +2,14 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBTLabel
|
||||
public sealed record MSBTLabel
|
||||
{
|
||||
public uint Length;
|
||||
public readonly string Name;
|
||||
public MSBTTextString String;
|
||||
public required uint Length { get; init; }
|
||||
public required uint Index { get; init; }
|
||||
public required string Name { get; init; }
|
||||
|
||||
public MSBTLabel(string name)
|
||||
{
|
||||
Name = name;
|
||||
String = MSBTTextString.Empty;
|
||||
}
|
||||
public MSBTTextString String { get; set; } = MSBTTextString.Empty;
|
||||
|
||||
public uint Index { get; set; }
|
||||
public override string ToString() => Length > 0 ? Name : (Index + 1).ToString();
|
||||
public string ToString(Encoding encoding) => encoding.GetString(String.Value.Span);
|
||||
}
|
||||
|
|
@ -1,14 +1,8 @@
|
|||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBTSection
|
||||
public abstract class MSBTSection(string identifier, byte[] padding)
|
||||
{
|
||||
public string Identifier;
|
||||
public uint SectionSize; // Begins after Unknown1
|
||||
public byte[] Padding1; // Always 0x0000 0000
|
||||
|
||||
public MSBTSection(string identifier, byte[] padding)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Padding1 = padding;
|
||||
}
|
||||
public string Identifier { get; set; } = identifier;
|
||||
public uint SectionSize { get; set; } // Begins after Unknown1
|
||||
public byte[] Padding1 { get; set; } = padding; // Always 0x0000 0000
|
||||
}
|
||||
|
|
@ -4,19 +4,10 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class MSBTTextString
|
||||
public sealed record MSBTTextString(Memory<byte> Value, uint Index)
|
||||
{
|
||||
public readonly Memory<byte> Value;
|
||||
public readonly uint Index;
|
||||
|
||||
public static readonly MSBTTextString Empty = new(default, 0);
|
||||
|
||||
public MSBTTextString(Memory<byte> v, uint i)
|
||||
{
|
||||
Value = v;
|
||||
Index = i;
|
||||
}
|
||||
|
||||
public override string ToString() => (Index + 1).ToString();
|
||||
|
||||
public string ToString(Encoding encoding) => encoding.GetString(Value.Span);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class TXT2() : MSBTSection(string.Empty, [])
|
||||
public sealed class TXT2() : MSBTSection(string.Empty, [])
|
||||
{
|
||||
public uint NumberOfStrings;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace NHSE.Parsing;
|
||||
|
||||
public class PBC
|
||||
public sealed class PBC
|
||||
{
|
||||
private const uint MAGIC = 0x00636270; // pbc\0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace NHSE.Parsing;
|
||||
|
|
@ -22,7 +23,7 @@ public static void ConvertItemStrings(string input, string output)
|
|||
private static string[] ConvertItemList(string path)
|
||||
{
|
||||
var lines = File.ReadAllLines(path);
|
||||
var items = lines.Select(z => new ParseItem(z)).ToArray();
|
||||
var items = lines.Select(ParseItem.FromString).ToArray();
|
||||
|
||||
var max = items.Max(z => z.Index);
|
||||
var result = new string[max + 1];
|
||||
|
|
@ -32,14 +33,18 @@ private static string[] ConvertItemList(string path)
|
|||
}
|
||||
}
|
||||
|
||||
public class ParseItem
|
||||
public readonly record struct ParseItem
|
||||
{
|
||||
public readonly int Index;
|
||||
public readonly string Name;
|
||||
public required int Index {get; init; }
|
||||
public required string Name { get; init; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public ParseItem(string line)
|
||||
{
|
||||
var split = line.Split(", ");
|
||||
Index = int.Parse(split[0], System.Globalization.NumberStyles.HexNumber);
|
||||
Name = split[1];
|
||||
}
|
||||
|
||||
public static ParseItem FromString(string s) => new(s);
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class ArrayUtilTests
|
||||
public static class ArrayUtilTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenPatternNotFound_ReturnsZero()
|
||||
public static void ReplaceOccurrences_WhenPatternNotFound_ReturnsZero()
|
||||
{
|
||||
byte[] array = [0x01, 0x02, 0x03, 0x04, 0x05];
|
||||
byte[] pattern = [0xAA, 0xBB];
|
||||
|
|
@ -22,7 +22,7 @@ public void ReplaceOccurrences_WhenPatternNotFound_ReturnsZero()
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenSingleOccurrence_ReplacesAndReturnsOne()
|
||||
public static void ReplaceOccurrences_WhenSingleOccurrence_ReplacesAndReturnsOne()
|
||||
{
|
||||
byte[] array = [0x01, 0xAA, 0xBB, 0x04, 0x05];
|
||||
byte[] pattern = [0xAA, 0xBB];
|
||||
|
|
@ -35,7 +35,7 @@ public void ReplaceOccurrences_WhenSingleOccurrence_ReplacesAndReturnsOne()
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenMultipleOccurrences_ReplacesAllAndReturnsCount()
|
||||
public static void ReplaceOccurrences_WhenMultipleOccurrences_ReplacesAllAndReturnsCount()
|
||||
{
|
||||
byte[] array = [0xAA, 0xBB, 0x03, 0xAA, 0xBB, 0x06, 0xAA, 0xBB];
|
||||
byte[] pattern = [0xAA, 0xBB];
|
||||
|
|
@ -48,7 +48,7 @@ public void ReplaceOccurrences_WhenMultipleOccurrences_ReplacesAllAndReturnsCoun
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenConsecutiveOccurrences_ReplacesAll()
|
||||
public static void ReplaceOccurrences_WhenConsecutiveOccurrences_ReplacesAll()
|
||||
{
|
||||
byte[] array = [0xAA, 0xBB, 0xAA, 0xBB, 0xAA, 0xBB];
|
||||
byte[] pattern = [0xAA, 0xBB];
|
||||
|
|
@ -61,7 +61,7 @@ public void ReplaceOccurrences_WhenConsecutiveOccurrences_ReplacesAll()
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenSwapContainsPattern_DoesNotCauseInfiniteLoop()
|
||||
public static void ReplaceOccurrences_WhenSwapContainsPattern_DoesNotCauseInfiniteLoop()
|
||||
{
|
||||
// Swap contains the original pattern - must skip past swapped data
|
||||
byte[] array = [0x01, 0xAA, 0xBB, 0x04];
|
||||
|
|
@ -75,7 +75,7 @@ public void ReplaceOccurrences_WhenSwapContainsPattern_DoesNotCauseInfiniteLoop(
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceOccurrences_WhenLargeFileWithRandomPlacements_ReplacesAllOccurrences()
|
||||
public static void ReplaceOccurrences_WhenLargeFileWithRandomPlacements_ReplacesAllOccurrences()
|
||||
{
|
||||
const int fileSize = 1024 * 1024; // 1 MB
|
||||
const int sequenceLength = 0x13; // 19 bytes
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
using System.Linq;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NHSE.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class BuildingTests
|
||||
public static class BuildingTests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildingMarshal()
|
||||
public static void BuildingMarshal()
|
||||
{
|
||||
var building = new Building();
|
||||
var bytes = building.ToBytesClass();
|
||||
|
|
@ -16,7 +16,7 @@ public void BuildingMarshal()
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildingClear()
|
||||
public static void BuildingClear()
|
||||
{
|
||||
var item = new Building {BuildingType = BuildingType.PlayerHouse1, X=5, Y=7};
|
||||
var bytes = item.ToBytesClass();
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class EncryptedIntTests
|
||||
public static class EncryptedIntTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestParse()
|
||||
public static void TestParse()
|
||||
{
|
||||
const int expect = 31_280;
|
||||
ReadOnlySpan<byte> data = [0x8A, 0xC4, 0xE3, 0xCF, 0x37, 0xD5, 0x1A, 0xD3];
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class EnumHashTests
|
||||
public static class EnumHashTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Base", 0x6086515F)]
|
||||
[InlineData("River", 0x3422482F)]
|
||||
[InlineData("RoadStone", 0x13011867)]
|
||||
public void ChecksumMatches(string str, uint val)
|
||||
public static void ChecksumMatches(string str, uint val)
|
||||
{
|
||||
var computed = CRC32.Compute(str);
|
||||
computed.Should().Be(val);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
using FluentAssertions;
|
||||
using FluentAssertions;
|
||||
using NHSE.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class FancyMarshalTests
|
||||
public sealed class FancyMarshalTests
|
||||
{
|
||||
[Fact] public void MarshalGSaveBulletinBoard() => MarshalBytesTestS<GSaveBulletinBoard>(GSaveBulletinBoard.SIZE);
|
||||
[Fact] public void MarshalBulletinBoard() => MarshalBytesTestS<BulletinBoardStock>(BulletinBoardStock.SIZE);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
using FluentAssertions;
|
||||
using FluentAssertions;
|
||||
using NHSE.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace NHSE.Tests;
|
||||
|
||||
public class MarshalTests
|
||||
public sealed class MarshalTests
|
||||
{
|
||||
[Fact] public void MarshalItem() => MarshalTest<Item>(Item.SIZE);
|
||||
[Fact] public void MarshalVillagerItem() => MarshalTest<VillagerItem>(VillagerItem.SIZE);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,7 @@
|
|||
|
||||
namespace NHSE.Villagers;
|
||||
|
||||
public class VillagerData
|
||||
{
|
||||
public readonly Memory<byte> Villager;
|
||||
public readonly Memory<byte> House;
|
||||
|
||||
public VillagerData(Memory<byte> villager, Memory<byte> house)
|
||||
{
|
||||
Villager = villager;
|
||||
House = house;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tuple-like record struct to hold villager and house memory segments.
|
||||
/// </summary>
|
||||
public readonly record struct VillagerData(Memory<byte> Villager, Memory<byte> House);
|
||||
|
|
@ -2,14 +2,4 @@
|
|||
|
||||
namespace NHSE.Villagers;
|
||||
|
||||
public class VillagerInfo
|
||||
{
|
||||
public readonly Villager2 Villager;
|
||||
public readonly IVillagerHouse House;
|
||||
|
||||
public VillagerInfo(Villager2 villager, IVillagerHouse house)
|
||||
{
|
||||
Villager = villager;
|
||||
House = house;
|
||||
}
|
||||
}
|
||||
public readonly record struct VillagerInfo(Villager2 Villager, IVillagerHouse House);
|
||||
|
|
@ -11,7 +11,11 @@ namespace NHSE.WinForms;
|
|||
|
||||
public partial class ItemGridEditor : UserControl
|
||||
{
|
||||
private static readonly GridSize Sprites = new();
|
||||
private static readonly GridSize Sprites = new()
|
||||
{
|
||||
Width = 64,
|
||||
Height = 64,
|
||||
};
|
||||
private readonly ItemEditor Editor;
|
||||
private readonly IReadOnlyList<Item> Items;
|
||||
|
||||
|
|
@ -304,9 +308,9 @@ private void SetEditorItems(List<Item> items)
|
|||
private void B_ClearFish_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Fish.Contains(z.ItemId));
|
||||
private void B_ClearDive_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Dive.Contains(z.ItemId));
|
||||
|
||||
private class GridSize : IGridItem
|
||||
private sealed record GridSize : IGridItem
|
||||
{
|
||||
public int Width { get; set; } = 64;
|
||||
public int Height { get; set; } = 64;
|
||||
public required int Width { get; set; }
|
||||
public required int Height { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ private void SaveMain()
|
|||
#region Player Editing
|
||||
private void LoadPlayers()
|
||||
{
|
||||
if (SAV.Players.Length == 0)
|
||||
if (SAV.Players.Count == 0)
|
||||
throw new Exception("No players found in the loaded directory.");
|
||||
|
||||
CB_Players.Items.Clear();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ private void LoadComboBoxes()
|
|||
|
||||
CB_MapAcreSelect.DisplayMember = nameof(ComboItem.Text);
|
||||
CB_MapAcreSelect.ValueMember = nameof(ComboItem.Value);
|
||||
CB_MapAcreSelect.DataSource = ComboItemUtil.GetArray<ushort>(typeof(OutsideAcre));
|
||||
CB_MapAcreSelect.DataSource = ComboItemUtil.GetArray<OutsideAcre>();
|
||||
|
||||
NUD_MapAcreTemplateOutside.Value = SAV.OutsideFieldTemplateUniqueId;
|
||||
NUD_MapAcreTemplateField.Value = SAV.MainFieldParamUniqueID;
|
||||
|
|
|
|||
|
|
@ -5,11 +5,8 @@
|
|||
|
||||
namespace NHSE.WinForms;
|
||||
|
||||
public class SysBotController
|
||||
public sealed class SysBotController(InjectionType type)
|
||||
{
|
||||
public SysBotController(InjectionType type) => Type = type;
|
||||
|
||||
private readonly InjectionType Type;
|
||||
public readonly SysBot Bot = new();
|
||||
private readonly Settings Settings = Settings.Default;
|
||||
|
||||
|
|
@ -42,7 +39,7 @@ public bool Connect(string ip, string port)
|
|||
public uint GetDefaultOffset()
|
||||
{
|
||||
var settings = Settings;
|
||||
return Type switch
|
||||
return type switch
|
||||
{
|
||||
InjectionType.Generic => settings.SysBotGenericOffset,
|
||||
InjectionType.Pouch => settings.SysBotPouchOffset,
|
||||
|
|
@ -53,7 +50,7 @@ public uint GetDefaultOffset()
|
|||
public void SetOffset(uint value)
|
||||
{
|
||||
var settings = Settings;
|
||||
switch (Type)
|
||||
switch (type)
|
||||
{
|
||||
case InjectionType.Generic: settings.SysBotGenericOffset = value; break;
|
||||
case InjectionType.Pouch: settings.SysBotPouchOffset = value; break;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace NHSE.WinForms;
|
||||
|
||||
public class USBBotController
|
||||
public sealed class USBBotController
|
||||
{
|
||||
public readonly USBBot Bot = new();
|
||||
|
||||
|
|
@ -20,10 +20,7 @@ public bool Connect()
|
|||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
Bot.Disconnect();
|
||||
}
|
||||
public void Disconnect() => Bot.Disconnect();
|
||||
|
||||
//todo: this
|
||||
//public uint GetDefaultOffset()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace NHSE.WinForms;
|
||||
|
||||
public class InterpolatingPictureBox : PictureBox
|
||||
public sealed class InterpolatingPictureBox : PictureBox
|
||||
{
|
||||
private readonly InterpolationMode InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user