Skip to content

Commit

Permalink
Reworked cache and loading/unloading of blocks + some refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kaczy93 committed Dec 21, 2023
1 parent 44c8f3d commit 6640bc9
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 89 deletions.
62 changes: 32 additions & 30 deletions CentrED/Map/MapManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,16 @@ public MapManager(GraphicsDevice gd)
};
Client.BlockUnloaded += block =>
{
var landTiles = block.LandBlock.Tiles;
foreach (var landTile in landTiles)
var tile = block.LandBlock.Tiles[0];
if (ViewRange.Contains(tile.X, tile.Y))
{
RemoveTile(landTile);
return;
}
foreach (var staticTile in block.StaticBlock.AllTiles())
foreach (var landTile in block.LandBlock.Tiles)
{
RemoveTile(staticTile);
RemoveTiles(landTile.X, landTile.Y);
}
block.Disposed = true;
};
Client.StaticTileRemoved += RemoveTile;
Client.StaticTileAdded += tile =>
Expand Down Expand Up @@ -193,10 +194,6 @@ public MapManager(GraphicsDevice gd)
AllTiles.Clear();
};

Camera.Position.X = 0;
Camera.Position.Y = 0;
Camera.ScreenSize.X = 0;
Camera.ScreenSize.Y = 0;
Camera.ScreenSize.Width = gd.PresentationParameters.BackBufferWidth;
Camera.ScreenSize.Height = gd.PresentationParameters.BackBufferHeight;
}
Expand Down Expand Up @@ -328,7 +325,7 @@ private MouseDirection ProcessMouseMovement(ref MouseState mouseState, out float

private readonly float WHEEL_DELTA = 1200f;

public List<TileObject> AllTiles = new();
public Dictionary<int, TileObject> AllTiles = new();
public LandObject?[,] LandTiles;
public int LandTilesCount;
public List<LandObject> GhostLandTiles = new();
Expand All @@ -337,24 +334,13 @@ private MouseDirection ProcessMouseMovement(ref MouseState mouseState, out float
public List<StaticObject> GhostStaticTiles = new();
public VirtualLayerObject VirtualLayer = VirtualLayerObject.Instance;


public void AddTile(LandTile landTile)
{
var lo = new LandObject(landTile);
LandTiles[landTile.X, landTile.Y] = lo;
AllTiles.Add(lo);
AllTiles.Add(lo.ObjectId, lo);
LandTilesCount++;
}
public void RemoveTile(LandTile landTile)
{
var lo = LandTiles[landTile.X, landTile.Y];
if (lo != null)
{
LandTiles[landTile.X, landTile.Y] = null;
AllTiles.Remove(lo);
LandTilesCount--;
}
}

public void AddTile(StaticTile staticTile)
{
Expand All @@ -368,7 +354,7 @@ public void AddTile(StaticTile staticTile)
StaticTiles[x, y] = list;
}
list.Add(so);
AllTiles.Add(so);
AllTiles.Add(so.ObjectId, so);
StaticTilesCount++;
}

Expand All @@ -383,10 +369,31 @@ public void RemoveTile(StaticTile staticTile)
if (found != null)
{
list.Remove(found);
AllTiles.Remove(found);
AllTiles.Remove(found.ObjectId);
}
StaticTilesCount--;
}

public void RemoveTiles(ushort x, ushort y)
{
var lo = LandTiles[x, y];
if (lo != null)
{
LandTiles[x, y] = null;
AllTiles.Remove(lo.ObjectId);
LandTilesCount--;
}
var so = StaticTiles[x, y];
if (so != null)
{
StaticTiles[x, y] = null;
StaticTilesCount -= so.Count;
foreach (var staticObject in so)
{
AllTiles.Remove(staticObject.ObjectId);
}
}
}

private MouseState _prevMouseState = Mouse.GetState();
private KeyboardState _prevKeyState = Keyboard.GetState();
Expand Down Expand Up @@ -439,11 +446,6 @@ public void Update(GameTime gameTime, bool isActive, bool processMouse, bool pro
{
var delta = (mouseState.ScrollWheelValue - _prevMouseState.ScrollWheelValue) / WHEEL_DELTA;
Camera.ZoomIn(delta);
//It can get buggy when zooming in due to how BlockCache is working :(
//Just resetting is a safe way in cost of small performance spike and higher network traffic
//TODO: FreeBlocks that are out of view range
if(delta > 0)
Reset();
}

if (Client.Running && _gfxDevice.Viewport.Bounds.Contains(new Point(mouseState.X, mouseState.Y)))
Expand Down Expand Up @@ -559,7 +561,7 @@ public void Reset()
var selectedIndex = pixel.R | (pixel.G << 8) | (pixel.B << 16);
if (selectedIndex < 1)
return null;
return AllTiles.Find(t => t.ObjectId == selectedIndex);
return AllTiles.GetValueOrDefault(selectedIndex);
}

private void CalculateViewRange(Camera camera, out Rectangle rect)
Expand Down
29 changes: 3 additions & 26 deletions Client/CentrEDClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ public void Connect(string hostname, int port, string username, string password)
{
Update();
} while (!Initialized && Running);
if (Initialized)
Connected?.Invoke();
}

public void Disconnect()
Expand Down Expand Up @@ -124,28 +122,17 @@ public void InitLandscape(ushort width, ushort height)
{
Landscape = new ClientLandscape(this, width, height);
Landscape.BlockCache.Resize(1024);
Connected?.Invoke();
Initialized = true;
}

public List<Block> LoadBlocks(List<BlockCoords> blockCoords)
public void LoadBlocks(List<BlockCoords> blockCoords)
{
var filteredBlockCoords = blockCoords.FindAll
(b => !Landscape.BlockCache.Contains(Block.Id(b.X, b.Y)) && isValidX(b.X) && isValidY(b.Y));
if (filteredBlockCoords.Count <= 0)
return new List<Block>();
return;
Send(new RequestBlocksPacket(filteredBlockCoords));
List<Block> result = new List<Block>(filteredBlockCoords.Count);
foreach (var block in filteredBlockCoords)
{
var blockId = Block.Id(block.X, block.Y);
while (!Landscape.BlockCache.Contains(blockId))
{
Thread.Sleep(1);
Update();
}
result.Add(Landscape.BlockCache.Get(blockId));
}
return result;
}

public bool isValidX(int x)
Expand All @@ -158,16 +145,6 @@ public bool isValidY(int y)
return y >= 0 && y < Height * 8;
}

public ushort ClampX(int x)
{
return (ushort)Math.Min(x, Width - 1);
}

public ushort ClampY(int y)
{
return (ushort)Math.Min(y, Height - 1);
}

public void SetPos(ushort x, ushort y)
{
if (x == X && y == Y)
Expand Down
10 changes: 9 additions & 1 deletion Client/Map/ClientLandscape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,16 @@ public ClientLandscape(CentrEDClient client, ushort width, ushort height) : base
// ClientLandscape events are used to send changes done by the user to the server
BlockUnloaded += block =>
{
_client.Send(new FreeBlockPacket(block.LandBlock.X, block.LandBlock.Y));
_client.OnBlockReleased(block);
if(block.Disposed)
{
_client.Send(new FreeBlockPacket(block.LandBlock.X, block.LandBlock.Y));
}
else
{
//Not disposed because still used, put it back
BlockCache.Add(Block.Id(block), block);
}
};

LandTileReplaced += (tile, newId) =>
Expand Down
4 changes: 2 additions & 2 deletions Client/Map/ClientLandscapePacketHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ private void OnBlockPacket(BinaryReader reader, NetState<CentrEDClient> ns)
index.Length = StaticTile.Size * staticsCount;
var staticBlock = new StaticBlock(this, reader, index, coords.X, coords.Y);
var block = new Block(landBlock, staticBlock);
BlockCache.Add(Block.Id(block), block);
ns.Parent.OnBlockLoaded(block);
if(BlockCache.Add(Block.Id(block), block))
ns.Parent.OnBlockLoaded(block);
}
}

Expand Down
6 changes: 2 additions & 4 deletions Shared/BaseLandscape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@ protected BaseLandscape(ushort width, ushort height)
Height = height;
CellWidth = (ushort)(width * 8);
CellHeight = (ushort)(height * 8);
BlockCache = new BlockCache
{
OnRemovedItem = OnBlockReleased
};
BlockCache = new BlockCache();
BlockCache.OnRemovedItem = OnBlockReleased;
}

public ushort Width { get; }
Expand Down
1 change: 1 addition & 0 deletions Shared/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public Block(LandBlock land, StaticBlock statics)

public LandBlock LandBlock { get; }
public StaticBlock StaticBlock { get; }
public bool Disposed { get; set; }

public static int Id(Block block)
{
Expand Down
43 changes: 17 additions & 26 deletions Shared/BlockCache.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,41 @@
using System.Collections.Concurrent;

namespace CentrED;
namespace CentrED;

public class BlockCache
{
public delegate void CacheChanged(Block block);

private readonly ConcurrentDictionary<int, Block> blocks;
private readonly ConcurrentQueue<int> _queue;
private int _maxSize;
public CacheChanged? OnRemovedItem;
public CacheChanged? OnAddedItem;

public BlockCache(int maxSize = 256)
{
_maxSize = maxSize;
_queue = new ConcurrentQueue<int>();
blocks = new ConcurrentDictionary<int, Block>();
}

private readonly Dictionary<int, Block> _blocks = new();
private readonly Queue<int> _queue = new();
private int _maxSize = 256;

public void Add(int id, Block block)
public bool Add(int id, Block block)
{
blocks.TryAdd(id, block);
if (_blocks.ContainsKey(id))
return false;
_blocks.TryAdd(id, block);
_queue.Enqueue(id);
if (blocks.Count > _maxSize)
if (_blocks.Count > _maxSize)
{
Dequeue(out _);
}
return true;
}

public void Clear()
{
while (!_queue.IsEmpty)
{
Dequeue(out _);
}
_blocks.Clear();
_queue.Clear();
}

public bool Contains(int id)
{
return Get(id) != null;
return _blocks.ContainsKey(id);
}

public Block? Get(int id)
{
blocks.TryGetValue(id, out Block? block);
_blocks.TryGetValue(id, out Block? block);
return block;
}

Expand All @@ -53,7 +44,7 @@ private bool Dequeue(out Block? block)
block = default;
if (!_queue.TryDequeue(out var id))
return false;
if (!blocks.TryRemove(id, out block))
if (!_blocks.Remove(id, out block))
return false;
OnRemovedItem?.Invoke(block);
return true;
Expand All @@ -64,7 +55,7 @@ public void Resize(int newSize)
if (newSize < 0)
newSize = 0;
_maxSize = newSize;
while (blocks.Count > _maxSize)
while (_blocks.Count > _maxSize)
{
Dequeue(out _);
}
Expand Down

0 comments on commit 6640bc9

Please sign in to comment.