diff --git a/EOLib.IO/Map/IMapFile.cs b/EOLib.IO/Map/IMapFile.cs index 8c899fb52..1cdb63d7f 100644 --- a/EOLib.IO/Map/IMapFile.cs +++ b/EOLib.IO/Map/IMapFile.cs @@ -9,6 +9,7 @@ public interface IMapFile IReadOnlyMatrix Tiles { get; } IReadOnlyMatrix Warps { get; } IReadOnlyDictionary> GFX { get; } + IReadOnlyDictionary> EmptyGFXRows { get; } IReadOnlyList NPCSpawns { get; } IReadOnlyList Unknowns { get; } IReadOnlyList Chests { get; } @@ -22,7 +23,7 @@ public interface IMapFile IMapFile WithWarps(Matrix warps); - IMapFile WithGFX(Dictionary> gfx); + IMapFile WithGFX(Dictionary> gfx, Dictionary> emptyLayers); IMapFile WithNPCSpawns(List npcSpawns); diff --git a/EOLib.IO/Map/MapFile.cs b/EOLib.IO/Map/MapFile.cs index 49cc19d90..98b56678c 100644 --- a/EOLib.IO/Map/MapFile.cs +++ b/EOLib.IO/Map/MapFile.cs @@ -13,6 +13,7 @@ public class MapFile : IMapFile public IReadOnlyMatrix Tiles => _mutableTiles; public IReadOnlyMatrix Warps => _mutableWarps; public IReadOnlyDictionary> GFX => _readOnlyGFX; + public IReadOnlyDictionary> EmptyGFXRows => _readOnlyEmptyGFXRows; public IReadOnlyList NPCSpawns => _mutableNPCSpawns; public IReadOnlyList Unknowns => _mutableUnknowns; public IReadOnlyList Chests => _mutableChestSpawns; @@ -22,6 +23,8 @@ public class MapFile : IMapFile private Matrix _mutableWarps; private Dictionary> _mutableGFX; private IReadOnlyDictionary> _readOnlyGFX; + private Dictionary> _mutableEmptyGFXRows; + private IReadOnlyDictionary> _readOnlyEmptyGFXRows; private List _mutableNPCSpawns; private List _mutableUnknowns; private List _mutableChestSpawns; @@ -32,6 +35,7 @@ public MapFile() Matrix.Empty, Matrix.Empty, new Dictionary>(), + new Dictionary>(), new List(), new List(), new List(), @@ -46,6 +50,7 @@ public MapFile() Matrix tiles, Matrix warps, Dictionary> gfx, + Dictionary> emptyGFXRows, List npcSpawns, List unknowns, List chests, @@ -55,6 +60,7 @@ public MapFile() _mutableTiles = tiles; _mutableWarps = warps; _mutableGFX = gfx; + _mutableEmptyGFXRows = emptyGFXRows; SetReadOnlyGFX(); _mutableNPCSpawns = npcSpawns; _mutableUnknowns = unknowns; @@ -89,10 +95,11 @@ public IMapFile WithWarps(Matrix warps) return newMap; } - public IMapFile WithGFX(Dictionary> gfx) + public IMapFile WithGFX(Dictionary> gfx, Dictionary> emptyRows) { var newMap = MakeCopy(this); newMap._mutableGFX = gfx; + newMap._mutableEmptyGFXRows = emptyRows; SetReadOnlyGFX(); return newMap; } @@ -177,6 +184,7 @@ private static MapFile MakeCopy(MapFile source) source._mutableTiles, source._mutableWarps, source._mutableGFX, + source._mutableEmptyGFXRows, source._mutableNPCSpawns, source._mutableUnknowns, source._mutableChestSpawns, @@ -186,6 +194,7 @@ private static MapFile MakeCopy(MapFile source) private void SetReadOnlyGFX() { _readOnlyGFX = _mutableGFX.ToDictionary(k => k.Key, v => (IReadOnlyMatrix)v.Value); + _readOnlyEmptyGFXRows = _mutableEmptyGFXRows.ToDictionary(k => k.Key, v => (IReadOnlyList)v.Value); } } } diff --git a/EOLib.IO/Services/Serializers/MapFileSerializer.cs b/EOLib.IO/Services/Serializers/MapFileSerializer.cs index 40afa303d..98bcdd0ac 100644 --- a/EOLib.IO/Services/Serializers/MapFileSerializer.cs +++ b/EOLib.IO/Services/Serializers/MapFileSerializer.cs @@ -85,7 +85,7 @@ public IMapFile DeserializeFromByteArray(byte[] data) var mapChests = ReadMapChests(ms); var tileSpecs = ReadTileSpecs(ms, properties); var warpTiles = ReadWarpTiles(ms, properties); - var gfxLayers = ReadGFXLayers(ms, properties); + var (gfxLayers, emptyLayers) = ReadGFXLayers(ms, properties); var mapSigns = new List(); if (ms.Position < ms.Length) @@ -101,7 +101,7 @@ public IMapFile DeserializeFromByteArray(byte[] data) .WithChests(mapChests) .WithTiles(tileSpecs) .WithWarps(warpTiles) - .WithGFX(gfxLayers) + .WithGFX(gfxLayers, emptyLayers) .WithSigns(mapSigns); } } @@ -204,9 +204,10 @@ private Matrix ReadWarpTiles(MemoryStream ms, IMapFileProperties return warps; } - private Dictionary> ReadGFXLayers(MemoryStream ms, IMapFileProperties properties) + private (Dictionary>, Dictionary>) ReadGFXLayers(MemoryStream ms, IMapFileProperties properties) { var gfx = new Dictionary>(); + var emptyRows = new Dictionary>(); var layers = (MapLayer[])Enum.GetValues(typeof(MapLayer)); var twoByteBuffer = new byte[2]; @@ -223,6 +224,14 @@ private Matrix ReadWarpTiles(MemoryStream ms, IMapFileProperties var y = _numberEncoderService.DecodeNumber((byte)ms.ReadByte()); var numberOfColsThisLayer = _numberEncoderService.DecodeNumber((byte)ms.ReadByte()); + if (numberOfColsThisLayer == 0) + { + if (!emptyRows.ContainsKey(layer)) + emptyRows.Add(layer, new List()); + + emptyRows[layer].Add(y); + } + for (int j = 0; j < numberOfColsThisLayer; ++j) { var x = _numberEncoderService.DecodeNumber((byte)ms.ReadByte()); @@ -236,7 +245,7 @@ private Matrix ReadWarpTiles(MemoryStream ms, IMapFileProperties } } - return gfx; + return (gfx, emptyRows); } private List ReadMapSigns(MemoryStream ms) @@ -365,7 +374,9 @@ private List WriteGFXLayers(IMapFile mapFile) .Where(rowList => rowList.EntityItems.Any(item => item != DEFAULT_GFX)) .ToList(); - ret.AddRange(_numberEncoderService.EncodeNumber(gfxRowsForLayer.Count, 1)); + var rowsForLayerCount = gfxRowsForLayer.Count + (mapFile.EmptyGFXRows.ContainsKey(layer) ? mapFile.EmptyGFXRows[layer].Count : 0); + ret.AddRange(_numberEncoderService.EncodeNumber(rowsForLayerCount, 1)); + foreach (var row in gfxRowsForLayer) { var entityItems = row.EntityItems @@ -381,6 +392,15 @@ private List WriteGFXLayers(IMapFile mapFile) ret.AddRange(_numberEncoderService.EncodeNumber(item.Value, 2)); } } + + if (mapFile.EmptyGFXRows.ContainsKey(layer)) + { + foreach (var emptyLayer in mapFile.EmptyGFXRows[layer]) + { + ret.AddRange(_numberEncoderService.EncodeNumber(emptyLayer, 1)); + ret.AddRange(_numberEncoderService.EncodeNumber(0, 1)); + } + } } return ret; } diff --git a/EOLib/Domain/Map/CurrentMapProvider.cs b/EOLib/Domain/Map/CurrentMapProvider.cs index 3e189b770..9181cc718 100644 --- a/EOLib/Domain/Map/CurrentMapProvider.cs +++ b/EOLib/Domain/Map/CurrentMapProvider.cs @@ -17,7 +17,6 @@ public class CurrentMapProvider : ICurrentMapProvider _mapFileProvider = mapFileProvider; } - public IMapFile CurrentMap => _mapFileProvider.MapFiles[_currentMapStateProvider.CurrentMapID]; }