2024-05-07 20:41:21 +02:00
|
|
|
using System.Diagnostics;
|
2024-05-03 15:47:33 +02:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2024-04-14 18:50:20 +02:00
|
|
|
using System.IO;
|
2024-05-03 15:47:33 +02:00
|
|
|
using TanksServer.Graphics;
|
2024-04-14 18:50:20 +02:00
|
|
|
|
2024-04-10 19:25:45 +02:00
|
|
|
namespace TanksServer.GameLogic;
|
2024-04-06 13:46:34 +02:00
|
|
|
|
2024-04-07 13:02:49 +02:00
|
|
|
internal sealed class MapService
|
2024-04-06 13:46:34 +02:00
|
|
|
{
|
2024-11-12 18:27:04 +01:00
|
|
|
public const ulong TilesPerRow = 44;
|
|
|
|
public const ulong TilesPerColumn = 20;
|
|
|
|
public const ulong TileSize = 8;
|
|
|
|
public const ulong PixelsPerRow = TilesPerRow * TileSize;
|
|
|
|
public const ulong PixelsPerColumn = TilesPerColumn * TileSize;
|
2024-04-14 18:50:20 +02:00
|
|
|
|
2024-05-07 20:41:21 +02:00
|
|
|
private readonly ConcurrentDictionary<string, MapPrototype> _mapPrototypes = new();
|
2024-10-16 20:15:32 +02:00
|
|
|
private readonly ConcurrentDictionary<string, Bitmap> _mapPreviews = new();
|
2024-04-14 23:11:00 +02:00
|
|
|
|
2024-05-05 13:51:28 +02:00
|
|
|
public IEnumerable<string> MapNames => _mapPrototypes.Keys;
|
2024-04-16 18:55:34 +02:00
|
|
|
|
|
|
|
public Map Current { get; private set; }
|
2024-04-14 18:50:20 +02:00
|
|
|
|
2024-04-14 21:10:21 +02:00
|
|
|
public MapService()
|
2024-04-14 18:50:20 +02:00
|
|
|
{
|
2024-04-16 18:55:34 +02:00
|
|
|
foreach (var file in Directory.EnumerateFiles("./assets/maps/", "*.txt"))
|
|
|
|
LoadMapString(file);
|
|
|
|
foreach (var file in Directory.EnumerateFiles("./assets/maps/", "*.png"))
|
|
|
|
LoadMapPng(file);
|
2024-05-05 13:51:28 +02:00
|
|
|
Current = GetRandomMap();
|
2024-04-14 21:10:21 +02:00
|
|
|
}
|
|
|
|
|
2024-05-05 13:51:28 +02:00
|
|
|
public bool TryGetPrototype(string name, [MaybeNullWhen(false)] out MapPrototype map)
|
|
|
|
=> _mapPrototypes.TryGetValue(name, out map);
|
2024-04-14 21:10:21 +02:00
|
|
|
|
2024-05-03 15:47:33 +02:00
|
|
|
public void SwitchTo(MapPrototype prototype) => Current = prototype.CreateInstance();
|
2024-04-14 22:45:51 +02:00
|
|
|
|
2024-10-16 20:15:32 +02:00
|
|
|
public bool TryGetPreview(string name, [MaybeNullWhen(false)] out Bitmap pixelGrid)
|
2024-05-05 13:51:28 +02:00
|
|
|
{
|
|
|
|
if (_mapPreviews.TryGetValue(name, out pixelGrid))
|
|
|
|
return true; // already generated
|
|
|
|
if (!_mapPrototypes.TryGetValue(name, out var prototype))
|
|
|
|
return false; // name not found
|
|
|
|
|
2024-10-19 16:07:41 +02:00
|
|
|
pixelGrid = new Bitmap(PixelsPerRow, PixelsPerColumn);
|
2024-05-05 13:51:28 +02:00
|
|
|
DrawMapStep.Draw(pixelGrid, prototype.CreateInstance());
|
|
|
|
|
|
|
|
_mapPreviews.TryAdd(name, pixelGrid); // another thread may have added the map already
|
|
|
|
return true; // new preview
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:47:33 +02:00
|
|
|
private void LoadMapPng(string file)
|
|
|
|
{
|
2024-05-05 13:51:28 +02:00
|
|
|
var name = MapNameFromFilePath(file);
|
2024-05-03 15:47:33 +02:00
|
|
|
var prototype = new SpriteMapPrototype(name, Sprite.FromImageFile(file));
|
2024-05-07 20:41:21 +02:00
|
|
|
var added = _mapPrototypes.TryAdd(name, prototype);
|
|
|
|
Debug.Assert(added);
|
2024-04-14 18:50:20 +02:00
|
|
|
}
|
2024-04-06 13:46:34 +02:00
|
|
|
|
2024-04-16 18:55:34 +02:00
|
|
|
private void LoadMapString(string file)
|
2024-04-14 18:50:20 +02:00
|
|
|
{
|
2024-05-05 13:51:28 +02:00
|
|
|
var name = MapNameFromFilePath(file);
|
2024-04-14 21:10:21 +02:00
|
|
|
var map = File.ReadAllText(file).ReplaceLineEndings(string.Empty).Trim();
|
2024-05-03 15:47:33 +02:00
|
|
|
var prototype = new TextMapPrototype(name, map);
|
2024-05-07 20:41:21 +02:00
|
|
|
_mapPrototypes.TryAdd(name, prototype);
|
2024-05-05 13:51:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static string MapNameFromFilePath(string filePath) => Path.GetFileName(filePath).ToUpperInvariant();
|
|
|
|
|
|
|
|
private Map GetRandomMap()
|
|
|
|
{
|
|
|
|
var chosenMapIndex = Random.Shared.Next(_mapPrototypes.Count);
|
|
|
|
var chosenMapName = _mapPrototypes.Keys.Skip(chosenMapIndex).First();
|
|
|
|
return _mapPrototypes[chosenMapName].CreateInstance();
|
2024-04-21 19:34:22 +02:00
|
|
|
}
|
2024-04-06 13:46:34 +02:00
|
|
|
}
|