Core - Impprove AbstractGameRule classes

This commit is contained in:
miku-666
2025-11-19 21:47:39 +01:00
parent e3259a8f5c
commit d87817b6b5
14 changed files with 105 additions and 198 deletions

View File

@@ -18,16 +18,14 @@ namespace PckStudio.Core.DLC
private IDLCPackage _skinPackage;
private IDLCPackage _texturePackage;
private AbstractGameRule _gameRule;
private MapData _mapData;
private IDictionary<string, byte[]> _audioData;
private PckAudioFile _pckAudio;
private NamedData<byte[]> _savegameData;
internal DLCMashUpPackage(string name, string description, int identifier, IDLCPackageSerialization packageInfo, AbstractGameRule gameRule, IDLCPackage parentPackage, IDLCPackage skinPackage = null, IDLCPackage texturePackage = null)
: base(name, identifier, packageInfo, parentPackage)
{
Description = description;
_gameRule = gameRule;
_skinPackage = skinPackage;
_texturePackage = texturePackage;
}
@@ -37,18 +35,8 @@ namespace PckStudio.Core.DLC
{
_skinPackage = DLCSkinPackage.CreateEmpty(this);
_texturePackage = DLCTexturePackage.CreateDefaultPackage(this);
_savegameData = new NamedData<byte[]>("world.mcs", Array.Empty<byte>());
_audioData = new Dictionary<string, byte[]>();
_pckAudio = new PckAudioFile();
//! TODO(null): only create grf when adding savefile ?...
_gameRule.AddRule(new NamedRule("MapOptions",
new GameRuleFile.IntParameter("seed", 0),
new GameRuleFile.GameRuleParameter("baseSaveName", _savegameData.Name),
new GameRuleFile.BoolParameter("flatworld", false),
new GameRuleFile.IntParameter("texturePackId", Identifier))
);
_gameRule.AddRule(LevelRules.GetDefault(pos: Vector3.Zero, rot: Vector2.Zero));
}
public IDLCPackage GetSkinPackage() => _skinPackage;

View File

@@ -23,7 +23,7 @@ namespace PckStudio.Core.DLC
public void AddMap(string name, Image thumbnail, MapSize mapSize, NamedData<byte[]> world)
{
_maps.Add(new MapData(name, thumbnail, _miniGameId, mapSize, world));
_maps.Add(new MapData(name, thumbnail, world, _miniGameId, mapSize));
}
public override DLCPackageType GetDLCPackageType() => _packageType;

View File

@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
@@ -10,14 +9,45 @@ namespace PckStudio.Core.GameRule
public abstract class AbstractGameRule
{
private List<AbstractGameRule> _gameRules = new List<AbstractGameRule>();
private IDictionary<string, string> _parameters = new Dictionary<string, string>();
public abstract string Name { get; }
public void AddRule(AbstractGameRule gameRule) => _gameRules.Add(gameRule);
public void AddRules(IEnumerable<AbstractGameRule> gameRules) => _gameRules.AddRange(gameRules);
protected abstract GameRuleFile.GameRule GetGameRule();
public void AddParameter(string name, string value) => _parameters.Add(name, value);
public void AddParameter<T>(string name, T value) => AddParameter(name, value.ToString());
public void AddParameter(string name, bool value) => AddParameter(name, value.ToString().ToLower());
public void AddParameters(KeyValuePair<string, string>[] values)
{
foreach (KeyValuePair<string, string> value in values)
{
AddParameter(value.Key, value.Value);
}
}
private string GetString(char c, string prefix, string suffix) => $"{prefix}{(string.IsNullOrWhiteSpace(prefix) ? char.ToLower(c) : char.ToUpper(c))}{suffix}";
public void AddParameter(Vector2 vec2, string prefix = "", string suffix = "")
{
AddParameter(GetString('x', prefix, suffix), vec2.X);
AddParameter(GetString('y', prefix, suffix), vec2.Y);
}
public void AddParameter(Vector3 vec3, string prefix = "", string suffix = "")
{
AddParameter(new Vector2(vec3.X, vec3.Y), prefix, suffix);
AddParameter(GetString('z', prefix, suffix), vec3.Z);
}
private GameRuleFile.GameRule InternalGetGameRule()
{
_ = Name ?? throw new ArgumentNullException(nameof(Name));
IEnumerable<GameRuleFile.GameRule> a = _gameRules.Select(agr => agr.InternalGetGameRule());
GameRuleFile.GameRule gameRule = GetGameRule();
GameRuleFile.GameRule gameRule = new GameRuleFile.GameRule(Name);
gameRule.AddParameters(_parameters.Select(kv => new GameRuleFile.GameRuleParameter(kv.Key, kv.Value)).ToArray());
gameRule.AddRules(a);
return gameRule;
}

View File

@@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
public sealed class DistributeItems : AbstractGameRule
{
public override string Name => "DistributeItems";
public void AddPosition(int x, int y, int z) => AddRule(new WorldPosition(x, y, z));
private static string[] _idStrings =
{
"StartItems",
@@ -22,20 +21,10 @@ namespace PckStudio.Core.GameRule
OuterItems,
HighValueItems
}
private DistributeItemsId _id;
public void AddPosition(int x, int y, int z) => AddRule(new WorldPosition(x, y, z));
internal DistributeItems(DistributeItemsId id)
{
_id = id;
}
protected override GameRuleFile.GameRule GetGameRule()
{
var gameRule = new GameRuleFile.GameRule("DistributeItems");
gameRule.AddParameter(new GameRuleFile.GameRuleParameter("id", _idStrings[(int)_id]));
return gameRule;
AddParameter("id", _idStrings[(int)id]);
}
}
}

View File

@@ -1,39 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
using System.Collections.Generic;
namespace PckStudio.Core.GameRule
{
public sealed class LevelRules : AbstractGameRule
{
private readonly GameRuleFile.GameRuleParameter[] _parameters;
private readonly MiniGameId _miniGameId;
public override string Name => "LevelRules";
public MiniGameId MiniGame { get; }
public static LevelRules GetDefault(Vector3 pos, Vector2 rot) => new LevelRules([new UpdatePlayer(pos, rot)]);
public static LevelRules GetMiniGameLevelRules(MiniGameId miniGame) => new LevelRules(miniGame);
public LevelRules(IEnumerable<AbstractGameRule> gameRules, MiniGameId miniGameId, params GameRuleFile.GameRuleParameter[] parameters)
public LevelRules(IEnumerable<AbstractGameRule> gameRules, MiniGameId miniGameId, params KeyValuePair<string, string>[] parameters)
{
AddRules(gameRules);
_parameters = parameters;
_miniGameId = miniGameId;
MiniGame = miniGameId;
if (miniGameId != MiniGameId.None)
AddParameter("ruleType", (int)miniGameId);
AddParameters(parameters);
}
public LevelRules(IEnumerable<AbstractGameRule> gameRules, params GameRuleFile.GameRuleParameter[] parameters) : this(gameRules, MiniGameId.None, parameters) { }
public LevelRules(IEnumerable<AbstractGameRule> gameRules, params KeyValuePair<string, string>[] parameters) : this(gameRules, MiniGameId.None, parameters) { }
public LevelRules(MiniGameId miniGameId) : this(Enumerable.Empty<AbstractGameRule>(), miniGameId) { }
protected override GameRuleFile.GameRule GetGameRule()
{
var gameRule = new GameRuleFile.GameRule("LevelRules");
if (_miniGameId != MiniGameId.None)
gameRule.AddParameter(new GameRuleFile.IntParameter("ruleType", (int)_miniGameId));
gameRule.AddParameters(_parameters);
return gameRule;
}
}
}

View File

@@ -1,43 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
using PckStudio.Core.Extensions;
namespace PckStudio.Core.GameRule
{
internal sealed class NamedArea : AbstractGameRule
{
public string Name { get; }
public override string Name => "NamedArea";
public Vector3 Start { get; }
public Vector3 End { get; }
public NamedArea(string name, Vector3 start, Vector3 end)
{
Name = name;
AddParameter("name", name);
AddParameter(start, suffix: "0");
AddParameter(end, suffix: "1");
Start = start;
End = end;
}
public NamedArea(string name, BoundingBox boundingBox) : this(name, boundingBox.Start.ToNumericsVector(), boundingBox.End.ToNumericsVector()) { }
protected override GameRuleFile.GameRule GetGameRule()
{
GameRuleFile.GameRule gameRule = new GameRuleFile.GameRule("NamedArea");
gameRule.AddParameters(
new GameRuleFile.GameRuleParameter("name", Name),
new GameRuleFile.FloatParameter("x0", Start.X),
new GameRuleFile.FloatParameter("y0", Start.Y),
new GameRuleFile.FloatParameter("z0", Start.Z),
new GameRuleFile.FloatParameter("x1", End.X),
new GameRuleFile.FloatParameter("y1", End.Y),
new GameRuleFile.FloatParameter("z1", End.Z)
);
return gameRule;
}
}
}

View File

@@ -1,28 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
internal sealed class NamedRule : AbstractGameRule
internal sealed class NamedRule(string name) : AbstractGameRule
{
private readonly string _name;
private readonly GameRuleFile.GameRuleParameter[] _parameters;
public NamedRule(string name, params GameRuleFile.GameRuleParameter[] parameters)
{
_name = name;
_parameters = parameters;
}
protected override GameRuleFile.GameRule GetGameRule()
{
var rule = new GameRuleFile.GameRule(_name);
rule.AddParameters(_parameters);
return rule;
}
public override string Name => name;
}
}

View File

@@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
public sealed class OnGameStartSpawnPositions : AbstractGameRule
{
public override string Name => "OnGameStartSpawnPositions";
public SpawnPositionSet OnStart { get; } = new SpawnPositionSet(SpawnPositionSet.SpanPositionMethod.OnStart);
public SpawnPositionSet OnRespawn { get; } = new SpawnPositionSet(SpawnPositionSet.SpanPositionMethod.OnRespawn);
protected override GameRuleFile.GameRule GetGameRule()
public OnGameStartSpawnPositions()
{
AddRule(OnStart);
AddRule(OnRespawn);
return new GameRuleFile.GameRule("OnGameStartSpawnPositions");
}
}
}

View File

@@ -1,24 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
public sealed class OnInitialiseWorld : AbstractGameRule
{
public override string Name => "OnInitialiseWorld";
public DistributeItems StartItems { get; } = new DistributeItems(DistributeItems.DistributeItemsId.StartItems);
public DistributeItems OuterItems { get; } = new DistributeItems(DistributeItems.DistributeItemsId.OuterItems);
public DistributeItems HighValueItems { get; } = new DistributeItems(DistributeItems.DistributeItemsId.HighValueItems);
protected override GameRuleFile.GameRule GetGameRule()
public OnInitialiseWorld()
{
AddRule(StartItems);
AddRule(OuterItems);
AddRule(HighValueItems);
return new GameRuleFile.GameRule("OnInitialiseWorld");
}
}
}

View File

@@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
public sealed class RootGameRule : AbstractGameRule
{
protected override GameRuleFile.GameRule GetGameRule() => new GameRuleFile.GameRule("__ROOT__"); //! name is irrelevant
public override string Name => "__ROOT__"; //! name is irrelevant
}
}

View File

@@ -1,32 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
public sealed class SpawnPositionSet : AbstractGameRule
{
public override string Name => "SpawnPositionSet";
public void AddSpawnPosition(int x, int y, int z, int xRot, int yRot) => AddRule(new UpdatePlayer(new Vector3(x, y, z), new Vector2(xRot, yRot)));
public void AddSpawnPosition(int x, int y, int z) => AddSpawnPosition(x, y, z, 0, 0);
internal enum SpanPositionMethod
{
OnStart,
OnRespawn
}
private SpanPositionMethod _method;
internal SpawnPositionSet(SpanPositionMethod method) => _method = method;
public void AddSpawnPosition(int x, int y, int z, int xRot, int yRot) => AddRule(new UpdatePlayer(new Vector3(x, y, z), new Vector2(xRot, yRot)));
public void AddSpawnPosition(int x, int y, int z) => AddSpawnPosition(x, y, z, 0, 0);
protected override GameRuleFile.GameRule GetGameRule()
{
var gameRule = new GameRuleFile.GameRule("SpawnPositionSet");
gameRule.AddParameter(new GameRuleFile.IntParameter("method", (int)_method));
return gameRule;
}
internal SpawnPositionSet(SpanPositionMethod method) => AddParameter("method", (int)method);
}
}

View File

@@ -1,35 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
internal sealed class UpdatePlayer : AbstractGameRule
public sealed class UpdatePlayer : AbstractGameRule
{
private Vector3 _spawn;
private Vector2 _rot;
public override string Name => "UpdatePlayer";
public UpdatePlayer(Vector3 spawn, Vector2 rot)
{
_spawn = spawn;
_rot = rot;
}
protected override GameRuleFile.GameRule GetGameRule()
{
var gameRule = new GameRuleFile.GameRule("UpdatePlayer");
gameRule.AddParameters(
new GameRuleFile.FloatParameter("x", _spawn.X),
new GameRuleFile.FloatParameter("y", _spawn.Y),
new GameRuleFile.FloatParameter("z", _spawn.Z),
new GameRuleFile.FloatParameter("xRot", _rot.X),
new GameRuleFile.FloatParameter("yRot", _rot.Y)
);
return gameRule;
AddParameter(spawn);
AddParameter(rot, suffix: "Rot");
}
}
}

View File

@@ -1,26 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.GameRule;
namespace PckStudio.Core.GameRule
{
internal sealed class WorldPosition(int x, int y, int z) : AbstractGameRule
internal sealed class WorldPosition : AbstractGameRule
{
private Vector3 _pos = new Vector3(x, y, z);
protected override GameRuleFile.GameRule GetGameRule()
public override string Name => "WorldPosition";
public WorldPosition(int x, int y, int z)
{
var gameRule = new GameRuleFile.GameRule("WorldPosition");
gameRule.AddParameters(
new GameRuleFile.IntParameter("x", (int)_pos.X),
new GameRuleFile.IntParameter("y", (int)_pos.Y),
new GameRuleFile.IntParameter("z", (int)_pos.Z)
);
return gameRule;
AddParameter(new Vector3(x, y, z));
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Drawing;
using System.IO;
using System.Numerics;
using Cyotek.Data.Nbt;
using OMI.Formats.GameRule;
using PckStudio.Core.Extensions;
using PckStudio.Core.GameRule;
namespace PckStudio.Core
@@ -24,41 +24,45 @@ namespace PckStudio.Core
Huge
}
#nullable enable
public sealed class MapData
{
public string Name { get; }
public Image Thumbnail { get; }
public Image? Thumbnail { get; }
public AbstractGameRule LevelRules { get; }
internal AbstractGameRule Grf { get; }
internal NamedData<byte[]> World { get; }
public MapData(string name, Image thumbnail, MiniGameId miniGame, MapSize mapSize, NamedData<byte[]> world)
public MapData(string name, Image? thumbnail, NamedData<byte[]> world, MiniGameId miniGame = MiniGameId.None, MapSize mapSize = default)
{
Name = name;
Thumbnail = thumbnail;
Grf = new RootGameRule();
World = world;
var levelData = MapReader.OpenSave(new MemoryStream(world.Value))["level.dat"];
TagCompound levelDat = NbtDocument.LoadDocument(new MemoryStream(levelData)).DocumentRoot["Data"] as TagCompound;
Vector3 spawn = Vector3.Zero;
if (levelDat is not null)
spawn = new Vector3((int)levelDat["SpawnX"].GetValue(), (int)levelDat["SpawnX"].GetValue(), (int)levelDat["SpawnY"].GetValue());
Grf.AddRule(new NamedRule("MapOptions",
new GameRuleFile.GameRuleParameter("seed", levelDat["RandomSeed"].GetValue().ToString()),
new GameRuleFile.FloatParameter("spawnX", spawn.X),
new GameRuleFile.FloatParameter("spawnY", spawn.Y),
new GameRuleFile.FloatParameter("spawnZ", spawn.Z),
new GameRuleFile.BoolParameter("flatworld", false),
new GameRuleFile.GameRuleParameter("baseSaveName", world.Name),
new GameRuleFile.IntParameter("mapSize", (int)mapSize),
new GameRuleFile.IntParameter("themeId", 0))
);
TagCompound? levelDat = NbtDocument.LoadDocument(new MemoryStream(levelData))!.DocumentRoot?["Data"] as TagCompound;
_ = levelDat ?? throw new NullReferenceException(nameof(levelDat));
Vector3 spawn = levelDat.GetVector3("Spawn");
LevelRules = GameRule.LevelRules.GetMiniGameLevelRules(miniGame);
var mapOptions = new NamedRule("MapOptions");
mapOptions.AddParameter("seed", levelDat["RandomSeed"].GetValue());
mapOptions.AddParameter(spawn, prefix: "spawn");
mapOptions.AddParameter("flatworld", false);
mapOptions.AddParameter("baseSaveName", world.Name);
if (miniGame > MiniGameId.None)
{
mapOptions.AddParameter("mapSize", (int)mapSize);
mapOptions.AddParameter("themeId", 0);
}
Grf = new RootGameRule();
Grf.AddRule(mapOptions);
LevelRules = miniGame > MiniGameId.None ? GameRule.LevelRules.GetMiniGameLevelRules(miniGame) : GameRule.LevelRules.GetDefault(spawn, Vector2.Zero);
Grf.AddRule(LevelRules);
World = world;
}
#nullable disable
}
}
}