position is now center, socket improvements
This commit is contained in:
parent
40eba7a7c7
commit
d4d0abd013
|
@ -1,7 +1,9 @@
|
||||||
namespace TanksServer.GameLogic;
|
namespace TanksServer.GameLogic;
|
||||||
|
|
||||||
internal sealed class CollideBulletsWithTanks(
|
internal sealed class CollideBulletsWithTanks(
|
||||||
BulletManager bullets, TankManager tanks, SpawnQueue spawnQueue
|
BulletManager bullets,
|
||||||
|
TankManager tanks,
|
||||||
|
SpawnQueue spawnQueue
|
||||||
) : ITickStep
|
) : ITickStep
|
||||||
{
|
{
|
||||||
public Task TickAsync()
|
public Task TickAsync()
|
||||||
|
@ -14,7 +16,7 @@ internal sealed class CollideBulletsWithTanks(
|
||||||
{
|
{
|
||||||
foreach (var tank in tanks)
|
foreach (var tank in tanks)
|
||||||
{
|
{
|
||||||
var (topLeft, bottomRight) = TankManager.GetTankBounds(tank.Position.ToPixelPosition());
|
var (topLeft, bottomRight) = tank.Bounds;
|
||||||
if (bullet.Position.X < topLeft.X || bullet.Position.X > bottomRight.X ||
|
if (bullet.Position.X < topLeft.X || bullet.Position.X > bottomRight.X ||
|
||||||
bullet.Position.Y < topLeft.Y || bullet.Position.Y > bottomRight.Y)
|
bullet.Position.Y < topLeft.Y || bullet.Position.Y > bottomRight.Y)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -47,9 +47,7 @@ internal sealed class MoveTanks(
|
||||||
|
|
||||||
private bool TryMoveTankTo(Tank tank, FloatPosition newPosition)
|
private bool TryMoveTankTo(Tank tank, FloatPosition newPosition)
|
||||||
{
|
{
|
||||||
var (topLeft, bottomRight) = TankManager.GetTankBounds(newPosition.ToPixelPosition());
|
if (HitsWall(newPosition))
|
||||||
|
|
||||||
if (HitsWall(topLeft, bottomRight))
|
|
||||||
return false;
|
return false;
|
||||||
if (HitsTank(tank, newPosition))
|
if (HitsTank(tank, newPosition))
|
||||||
return false;
|
return false;
|
||||||
|
@ -63,15 +61,16 @@ internal sealed class MoveTanks(
|
||||||
.Where(otherTank => otherTank != tank)
|
.Where(otherTank => otherTank != tank)
|
||||||
.Any(otherTank => newPosition.Distance(otherTank.Position) < MapService.TileSize);
|
.Any(otherTank => newPosition.Distance(otherTank.Position) < MapService.TileSize);
|
||||||
|
|
||||||
private bool HitsWall(PixelPosition topLeft, PixelPosition bottomRight)
|
private bool HitsWall(FloatPosition newPosition)
|
||||||
{
|
{
|
||||||
|
var (topLeft, bottomRight) = Tank.GetBoundsForCenter(newPosition);
|
||||||
TilePosition[] positions =
|
TilePosition[] positions =
|
||||||
[
|
[
|
||||||
topLeft.ToTilePosition(),
|
topLeft.ToTilePosition(),
|
||||||
new PixelPosition(bottomRight.X, topLeft.Y).ToTilePosition(),
|
new PixelPosition(bottomRight.X, topLeft.Y).ToTilePosition(),
|
||||||
new PixelPosition(topLeft.X, bottomRight.Y).ToTilePosition(),
|
new PixelPosition(topLeft.X, bottomRight.Y).ToTilePosition(),
|
||||||
bottomRight.ToTilePosition(),
|
bottomRight.ToTilePosition()
|
||||||
];
|
];
|
||||||
return positions.Any(map.IsCurrentlyWall);
|
return positions.Any(map.IsCurrentlyWall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ internal sealed class ShootFromTanks(
|
||||||
|
|
||||||
var angle = tank.Rotation * 2 * Math.PI;
|
var angle = tank.Rotation * 2 * Math.PI;
|
||||||
var position = new FloatPosition(
|
var position = new FloatPosition(
|
||||||
x: tank.Position.X + MapService.TileSize / 2d + Math.Sin(angle) * _config.BulletSpeed,
|
tank.Position.X + Math.Sin(angle) * _config.BulletSpeed,
|
||||||
y: tank.Position.Y + MapService.TileSize / 2d - Math.Cos(angle) * _config.BulletSpeed
|
tank.Position.Y - Math.Cos(angle) * _config.BulletSpeed
|
||||||
);
|
);
|
||||||
|
|
||||||
bulletManager.Spawn(new Bullet(tank.Owner, position, tank.Rotation));
|
bulletManager.Spawn(new Bullet(tank.Owner, position, tank.Rotation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,6 @@ internal sealed class SpawnNewTanks(
|
||||||
}
|
}
|
||||||
|
|
||||||
var min = candidates.MaxBy(kvp => kvp.Value).Key;
|
var min = candidates.MaxBy(kvp => kvp.Value).Key;
|
||||||
return new FloatPosition(
|
return min.ToPixelPosition().GetPixelRelative(4, 4).ToFloatPosition();
|
||||||
min.X * MapService.TileSize,
|
|
||||||
min.Y * MapService.TileSize
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,4 @@ internal sealed class TankManager(ILogger<TankManager> logger) : IEnumerable<Tan
|
||||||
logger.LogInformation("Tank removed for player {}", tank.Owner.Id);
|
logger.LogInformation("Tank removed for player {}", tank.Owner.Id);
|
||||||
_tanks.Remove(tank, out _);
|
_tanks.Remove(tank, out _);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static (PixelPosition TopLeft, PixelPosition BottomRight) GetTankBounds(PixelPosition tankPosition)
|
|
||||||
{
|
|
||||||
return (tankPosition, new PixelPosition(
|
|
||||||
(ushort)(tankPosition.X + MapService.TileSize - 1),
|
|
||||||
(ushort)(tankPosition.Y + MapService.TileSize - 1)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
using DisplayCommands;
|
|
||||||
using TanksServer.GameLogic;
|
|
||||||
|
|
||||||
namespace TanksServer.Graphics;
|
|
||||||
|
|
||||||
internal sealed class BulletDrawer(BulletManager bullets) : IDrawStep
|
|
||||||
{
|
|
||||||
public void Draw(PixelGrid buffer)
|
|
||||||
{
|
|
||||||
foreach (var bullet in bullets.GetAll())
|
|
||||||
{
|
|
||||||
var pos = bullet.Position.ToPixelPosition();
|
|
||||||
buffer[pos.X, pos.Y] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
13
TanksServer/Graphics/DrawBulletsStep.cs
Normal file
13
TanksServer/Graphics/DrawBulletsStep.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using DisplayCommands;
|
||||||
|
using TanksServer.GameLogic;
|
||||||
|
|
||||||
|
namespace TanksServer.Graphics;
|
||||||
|
|
||||||
|
internal sealed class DrawBulletsStep(BulletManager bullets) : IDrawStep
|
||||||
|
{
|
||||||
|
public void Draw(PixelGrid buffer)
|
||||||
|
{
|
||||||
|
foreach (var position in bullets.GetAll().Select(b => b.Position.ToPixelPosition()))
|
||||||
|
buffer[position.X, position.Y] = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using TanksServer.GameLogic;
|
||||||
|
|
||||||
namespace TanksServer.Graphics;
|
namespace TanksServer.Graphics;
|
||||||
|
|
||||||
internal sealed class MapDrawer(MapService map) : IDrawStep
|
internal sealed class DrawMapStep(MapService map) : IDrawStep
|
||||||
{
|
{
|
||||||
public void Draw(PixelGrid buffer)
|
public void Draw(PixelGrid buffer)
|
||||||
{
|
{
|
||||||
|
@ -22,4 +22,4 @@ internal sealed class MapDrawer(MapService map) : IDrawStep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,13 +5,13 @@ using TanksServer.GameLogic;
|
||||||
|
|
||||||
namespace TanksServer.Graphics;
|
namespace TanksServer.Graphics;
|
||||||
|
|
||||||
internal sealed class TankDrawer : IDrawStep
|
internal sealed class DrawTanksStep : IDrawStep
|
||||||
{
|
{
|
||||||
private readonly TankManager _tanks;
|
private readonly TankManager _tanks;
|
||||||
private readonly bool[] _tankSprite;
|
private readonly bool[] _tankSprite;
|
||||||
private readonly int _tankSpriteWidth;
|
private readonly int _tankSpriteWidth;
|
||||||
|
|
||||||
public TankDrawer(TankManager tanks)
|
public DrawTanksStep(TankManager tanks)
|
||||||
{
|
{
|
||||||
_tanks = tanks;
|
_tanks = tanks;
|
||||||
|
|
||||||
|
@ -22,9 +22,7 @@ internal sealed class TankDrawer : IDrawStep
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (var y = 0; y < tankImage.Height; y++)
|
for (var y = 0; y < tankImage.Height; y++)
|
||||||
for (var x = 0; x < tankImage.Width; x++, i++)
|
for (var x = 0; x < tankImage.Width; x++, i++)
|
||||||
{
|
|
||||||
_tankSprite[i] = tankImage[x, y] == whitePixel;
|
_tankSprite[i] = tankImage[x, y] == whitePixel;
|
||||||
}
|
|
||||||
|
|
||||||
_tankSpriteWidth = tankImage.Width;
|
_tankSpriteWidth = tankImage.Width;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +31,7 @@ internal sealed class TankDrawer : IDrawStep
|
||||||
{
|
{
|
||||||
foreach (var tank in _tanks)
|
foreach (var tank in _tanks)
|
||||||
{
|
{
|
||||||
var tankPosition = tank.Position.ToPixelPosition();
|
var tankPosition = tank.Bounds.TopLeft;
|
||||||
var orientation = (int)Math.Round(tank.Rotation * 16d) % 16;
|
var orientation = (int)Math.Round(tank.Rotation * 16d) % 16;
|
||||||
|
|
||||||
for (byte dy = 0; dy < MapService.TileSize; dy++)
|
for (byte dy = 0; dy < MapService.TileSize; dy++)
|
||||||
|
@ -56,4 +54,4 @@ internal sealed class TankDrawer : IDrawStep
|
||||||
|
|
||||||
return _tankSprite[index];
|
return _tankSprite[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,8 +3,9 @@ using TanksServer.GameLogic;
|
||||||
|
|
||||||
namespace TanksServer.Graphics;
|
namespace TanksServer.Graphics;
|
||||||
|
|
||||||
internal sealed class DrawStateToFrame(
|
internal sealed class GeneratePixelsTickStep(
|
||||||
IEnumerable<IDrawStep> drawSteps, LastFinishedFrameProvider lastFrameProvider
|
IEnumerable<IDrawStep> drawSteps,
|
||||||
|
LastFinishedFrameProvider lastFrameProvider
|
||||||
) : ITickStep
|
) : ITickStep
|
||||||
{
|
{
|
||||||
private readonly List<IDrawStep> _drawSteps = drawSteps.ToList();
|
private readonly List<IDrawStep> _drawSteps = drawSteps.ToList();
|
|
@ -12,30 +12,10 @@ internal sealed class ByteChannelWebSocket(WebSocket socket, ILogger logger, int
|
||||||
|
|
||||||
public async IAsyncEnumerable<Memory<byte>> ReadAllAsync()
|
public async IAsyncEnumerable<Memory<byte>> ReadAllAsync()
|
||||||
{
|
{
|
||||||
while (true)
|
while (socket.State is WebSocketState.Open or WebSocketState.CloseSent)
|
||||||
{
|
{
|
||||||
if (socket.State is not (WebSocketState.Open or WebSocketState.CloseSent))
|
if (await TryReadAsync())
|
||||||
break;
|
yield return _buffer.ToArray();
|
||||||
|
|
||||||
var response = await socket.ReceiveAsync(_buffer, CancellationToken.None);
|
|
||||||
if (response.MessageType == WebSocketMessageType.Close)
|
|
||||||
{
|
|
||||||
if (socket.State == WebSocketState.CloseReceived)
|
|
||||||
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
|
|
||||||
CancellationToken.None);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.Count != _buffer.Length)
|
|
||||||
{
|
|
||||||
await socket.CloseOutputAsync(
|
|
||||||
WebSocketCloseStatus.InvalidPayloadData,
|
|
||||||
"response has unexpected size",
|
|
||||||
CancellationToken.None);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return _buffer.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socket.State != WebSocketState.Closed)
|
if (socket.State != WebSocketState.Closed)
|
||||||
|
@ -44,7 +24,45 @@ internal sealed class ByteChannelWebSocket(WebSocket socket, ILogger logger, int
|
||||||
|
|
||||||
public async Task CloseAsync()
|
public async Task CloseAsync()
|
||||||
{
|
{
|
||||||
logger.LogDebug("closing socket");
|
if (socket.State != WebSocketState.Open)
|
||||||
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
||||||
|
}
|
||||||
|
catch (WebSocketException socketException)
|
||||||
|
{
|
||||||
|
logger.LogDebug(socketException, "could not close socket properly");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private async Task<bool> TryReadAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await socket.ReceiveAsync(_buffer, CancellationToken.None);
|
||||||
|
if (response.MessageType == WebSocketMessageType.Close)
|
||||||
|
{
|
||||||
|
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
|
||||||
|
CancellationToken.None);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Count != _buffer.Length)
|
||||||
|
{
|
||||||
|
await socket.CloseOutputAsync(WebSocketCloseStatus.InvalidPayloadData,
|
||||||
|
"response has unexpected size",
|
||||||
|
CancellationToken.None);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (WebSocketException socketException)
|
||||||
|
{
|
||||||
|
logger.LogDebug(socketException, "could not read");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
namespace TanksServer.Models;
|
namespace TanksServer.Models;
|
||||||
|
|
||||||
internal sealed class Bullet(Player tankOwner, FloatPosition position, double rotation): IMapEntity
|
internal sealed class Bullet(Player tankOwner, FloatPosition position, double rotation) : IMapEntity
|
||||||
{
|
{
|
||||||
public Player Owner { get; } = tankOwner;
|
public Player Owner { get; } = tankOwner;
|
||||||
|
|
||||||
public FloatPosition Position { get; set; } = position;
|
|
||||||
|
|
||||||
public double Rotation { get; set; } = rotation;
|
public double Rotation { get; set; } = rotation;
|
||||||
}
|
|
||||||
|
public FloatPosition Position { get; set; } = position;
|
||||||
|
|
||||||
|
public PixelBounds Bounds => new (Position.ToPixelPosition(), Position.ToPixelPosition());
|
||||||
|
}
|
||||||
|
|
|
@ -3,4 +3,6 @@ namespace TanksServer.Models;
|
||||||
internal interface IMapEntity
|
internal interface IMapEntity
|
||||||
{
|
{
|
||||||
FloatPosition Position { get; set; }
|
FloatPosition Position { get; set; }
|
||||||
}
|
|
||||||
|
PixelBounds Bounds { get; }
|
||||||
|
}
|
||||||
|
|
3
TanksServer/Models/PixelBounds.cs
Normal file
3
TanksServer/Models/PixelBounds.cs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
namespace TanksServer.Models;
|
||||||
|
|
||||||
|
internal record struct PixelBounds(PixelPosition TopLeft, PixelPosition BottomRight);
|
|
@ -10,8 +10,8 @@ internal static class PositionHelpers
|
||||||
Debug.Assert(subX < 8);
|
Debug.Assert(subX < 8);
|
||||||
Debug.Assert(subY < 8);
|
Debug.Assert(subY < 8);
|
||||||
return new PixelPosition(
|
return new PixelPosition(
|
||||||
x: (ushort)(position.X * MapService.TileSize + subX),
|
(ushort)(position.X * MapService.TileSize + subX),
|
||||||
y: (ushort)(position.Y * MapService.TileSize + subY)
|
(ushort)(position.Y * MapService.TileSize + subY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,21 +23,26 @@ internal static class PositionHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PixelPosition ToPixelPosition(this FloatPosition position) => new(
|
public static PixelPosition ToPixelPosition(this FloatPosition position) => new(
|
||||||
x: (ushort)((int)position.X % MapService.PixelsPerRow),
|
(ushort)((int)position.X % MapService.PixelsPerRow),
|
||||||
y: (ushort)((int)position.Y % MapService.PixelsPerRow)
|
(ushort)((int)position.Y % MapService.PixelsPerRow)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static PixelPosition ToPixelPosition(this TilePosition position) => new(
|
||||||
|
(ushort)(position.X * MapService.TileSize),
|
||||||
|
(ushort)(position.Y * MapService.TileSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static TilePosition ToTilePosition(this PixelPosition position) => new(
|
public static TilePosition ToTilePosition(this PixelPosition position) => new(
|
||||||
x: (ushort)(position.X / MapService.TileSize),
|
(ushort)(position.X / MapService.TileSize),
|
||||||
y: (ushort)(position.Y / MapService.TileSize)
|
(ushort)(position.Y / MapService.TileSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static FloatPosition ToFloatPosition(this PixelPosition position) => new(position.X, position.Y);
|
public static FloatPosition ToFloatPosition(this PixelPosition position) => new(position.X, position.Y);
|
||||||
|
|
||||||
|
|
||||||
public static double Distance(this FloatPosition p1, FloatPosition p2)
|
public static double Distance(this FloatPosition p1, FloatPosition p2) =>
|
||||||
=> Math.Sqrt(
|
Math.Sqrt(
|
||||||
Math.Pow(p1.X - p2.X, 2) +
|
Math.Pow(p1.X - p2.X, 2) +
|
||||||
Math.Pow(p1.Y - p2.Y, 2)
|
Math.Pow(p1.Y - p2.Y, 2)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,21 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEnt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FloatPosition Position { get; set; } = spawnPosition;
|
|
||||||
|
|
||||||
public DateTime NextShotAfter { get; set; }
|
public DateTime NextShotAfter { get; set; }
|
||||||
|
|
||||||
public bool Moved { get; set; }
|
public bool Moved { get; set; }
|
||||||
}
|
|
||||||
|
public FloatPosition Position { get; set; } = spawnPosition;
|
||||||
|
|
||||||
|
public PixelBounds Bounds => GetBoundsForCenter(Position);
|
||||||
|
|
||||||
|
public static PixelBounds GetBoundsForCenter(FloatPosition position) => new(
|
||||||
|
new PixelPosition(
|
||||||
|
(ushort)(position.X - MapService.TileSize / 2d),
|
||||||
|
(ushort)(position.Y - MapService.TileSize / 2d)
|
||||||
|
), new PixelPosition(
|
||||||
|
(ushort)(position.X + MapService.TileSize / 2d - 1d),
|
||||||
|
(ushort)(position.Y + MapService.TileSize / 2d - 1d)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -100,13 +100,13 @@ public static class Program
|
||||||
builder.Services.AddSingleton<ITickStep, MoveTanks>();
|
builder.Services.AddSingleton<ITickStep, MoveTanks>();
|
||||||
builder.Services.AddSingleton<ITickStep, ShootFromTanks>();
|
builder.Services.AddSingleton<ITickStep, ShootFromTanks>();
|
||||||
builder.Services.AddSingleton<ITickStep, SpawnNewTanks>();
|
builder.Services.AddSingleton<ITickStep, SpawnNewTanks>();
|
||||||
builder.Services.AddSingleton<ITickStep, DrawStateToFrame>();
|
builder.Services.AddSingleton<ITickStep, GeneratePixelsTickStep>();
|
||||||
builder.Services.AddSingleton<ITickStep, SendToServicePointDisplay>();
|
builder.Services.AddSingleton<ITickStep, SendToServicePointDisplay>();
|
||||||
builder.Services.AddSingleton<ITickStep, SendToClientScreen>();
|
builder.Services.AddSingleton<ITickStep, SendToClientScreen>();
|
||||||
|
|
||||||
builder.Services.AddSingleton<IDrawStep, MapDrawer>();
|
builder.Services.AddSingleton<IDrawStep, DrawMapStep>();
|
||||||
builder.Services.AddSingleton<IDrawStep, TankDrawer>();
|
builder.Services.AddSingleton<IDrawStep, DrawTanksStep>();
|
||||||
builder.Services.AddSingleton<IDrawStep, BulletDrawer>();
|
builder.Services.AddSingleton<IDrawStep, DrawBulletsStep>();
|
||||||
|
|
||||||
builder.Services.Configure<TanksConfiguration>(
|
builder.Services.Configure<TanksConfiguration>(
|
||||||
builder.Configuration.GetSection("Tanks"));
|
builder.Configuration.GetSection("Tanks"));
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
<PublishAot>true</PublishAot>
|
<PublishAot>true</PublishAot>
|
||||||
|
|
||||||
<IlcDisableReflection>false</IlcDisableReflection>
|
<IlcDisableReflection>false</IlcDisableReflection>
|
||||||
<InvariantGlobalization>true</InvariantGlobalization>
|
|
||||||
<StaticExecutable>true</StaticExecutable>
|
<StaticExecutable>true</StaticExecutable>
|
||||||
<StripSymbols>true</StripSymbols>
|
<StripSymbols>true</StripSymbols>
|
||||||
<StaticallyLinked>true</StaticallyLinked>
|
<StaticallyLinked>true</StaticallyLinked>
|
||||||
|
@ -31,19 +30,20 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="./assets/tank.png" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="Always" />
|
<None Include="./assets/tank.png" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="Always"/>
|
||||||
|
|
||||||
<Content Include="../Dockerfile">
|
<Content Include="../Dockerfile">
|
||||||
<Link>..\Dockerfile</Link>
|
<Link>Dockerfile</Link>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="../.dockerignore">
|
<Content Include="../.dockerignore">
|
||||||
<Link>../Dockerfile</Link>
|
<Link>Dockerfile</Link>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="../Makefile" />
|
<Content Include="../Makefile"/>
|
||||||
|
<Content Include="../.editorconfig"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\DisplayCommands\DisplayCommands.csproj" />
|
<ProjectReference Include="../DisplayCommands/DisplayCommands.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in a new issue