initialize repo

This commit is contained in:
2025-08-08 15:36:09 +02:00
parent d6a2c37a5f
commit cabf13d164
92 changed files with 2160 additions and 2 deletions

133
Lib/Civilization.Shared/.gitignore vendored Normal file
View File

@@ -0,0 +1,133 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.svclog
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
*.azurePubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
packages/
## TODO: If the tool you use requires repositories.config, also uncomment the next line
!packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
![Ss]tyle[Cc]op.targets
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac desktop service store files
.DS_Store
_NCrunch*

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Civilization.Core\Civilization.Core.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Commands;
public abstract record BaseCommand;

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Commands;
public record EndTurnCommand() : BaseCommand;

View File

@@ -0,0 +1,5 @@
using Civilization.Core;
namespace Civilization.Shared.Commands;
public record MoveUnitCommand(Guid UnitId, Vec2I TargetPosition) : BaseCommand;

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Commands;
public record SettleCityCommand(Guid UnitId) : BaseCommand;

View File

@@ -0,0 +1,46 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Civilization.Shared;
public class JsonPolymorphicConverter<TBase> : JsonConverter<TBase>
{
private readonly Dictionary<string, Type> _typeMap;
public JsonPolymorphicConverter()
{
_typeMap = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => typeof(TBase).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface)
.ToDictionary(t => t.Name, t => t);
}
public override TBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
if (!doc.RootElement.TryGetProperty("type", out var typeProp))
throw new JsonException("Missing 'type' field for polymorphic deserialization");
var typeName = typeProp.GetString();
if (typeName is null || !_typeMap.TryGetValue(typeName, out var derivedType))
throw new JsonException($"Unknown type discriminator: '{typeName}'");
var json = doc.RootElement.GetRawText();
return (TBase?)JsonSerializer.Deserialize(json, derivedType, options);
}
public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options)
{
using var jsonDoc = JsonDocument.Parse(JsonSerializer.Serialize(value, value.GetType(), options));
writer.WriteStartObject();
writer.WriteString("type", value.GetType().Name);
foreach (var prop in jsonDoc.RootElement.EnumerateObject())
{
prop.WriteTo(writer);
}
writer.WriteEndObject();
}
}

View File

@@ -0,0 +1,5 @@
using Civilization.Shared.Commands;
namespace Civilization.Shared.Packets;
public record ClientMessage(int PlayerId, BaseCommand Command);

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Packets;
public record PlayerInfo(int Id, string Name, string ColorHex);

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Packets.ServerMessages;
public abstract record BaseServerMessage;

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Packets.ServerMessages;
public record ErrorMessage(string Reason) : BaseServerMessage;

View File

@@ -0,0 +1,3 @@
namespace Civilization.Shared.Packets.ServerMessages;
public record LogMessage(string Message) : BaseServerMessage;

View File

@@ -0,0 +1,5 @@
using Civilization.Core.Game;
namespace Civilization.Shared.Packets.ServerMessages;
public record StateUpdateMessage(GameState GameState, PlayerInfo CurrentPlayer) : BaseServerMessage;

View File

@@ -0,0 +1,21 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Civilization.Shared.Commands;
using Civilization.Shared.Packets.ServerMessages;
namespace Civilization.Shared;
public static class SharedJson
{
public static readonly JsonSerializerOptions Options = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase),
new JsonPolymorphicConverter<BaseCommand>(),
new JsonPolymorphicConverter<BaseServerMessage>(),
},
WriteIndented = false
};
}