From 0a0a5d57ed7675f1d798eb46113cfa61137b9e57 Mon Sep 17 00:00:00 2001 From: BillyGalbreath Date: Sat, 1 Jun 2024 13:56:28 -0500 Subject: [PATCH] some progress on the config and structure layers --- src/LiveMap.cs | 2 +- src/command/subcommand/ApothemRenderCmd.cs | 2 +- src/command/subcommand/FullRenderCmd.cs | 2 +- src/configuration/Config.cs | 2 +- src/configuration/Layers.cs | 4 ++ src/configuration/Players.cs | 4 +- src/configuration/Traders.cs | 21 +++++++ src/configuration/Translocators.cs | 21 +++++++ src/configuration/Web.cs | 2 +- src/configuration/Zoom.cs | 2 +- src/data/ChunkLoader.cs | 33 +++++------ src/task/RenderTask.cs | 64 ++++++++++++++++++++-- 12 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 src/configuration/Traders.cs create mode 100644 src/configuration/Translocators.cs diff --git a/src/LiveMap.cs b/src/LiveMap.cs index a9a10b6..469c48c 100644 --- a/src/LiveMap.cs +++ b/src/LiveMap.cs @@ -119,7 +119,7 @@ public void SaveConfig() { new JsonSerializerSettings { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Include, ContractResolver = new CamelCasePropertyNamesContractResolver() } )); diff --git a/src/command/subcommand/ApothemRenderCmd.cs b/src/command/subcommand/ApothemRenderCmd.cs index 7ba9568..92d54af 100644 --- a/src/command/subcommand/ApothemRenderCmd.cs +++ b/src/command/subcommand/ApothemRenderCmd.cs @@ -46,7 +46,7 @@ public override TextCommandResult Execute(TextCommandCallingArgs args) { // queue up all existing chunks within range Vec2i min = new(Math.Max(0, blockPos.X - apothem) >> 9, Math.Max(0, blockPos.Y - apothem) >> 9); Vec2i max = new(Math.Min(mapX, blockPos.X + apothem) >> 9, Math.Min(mapZ, blockPos.Y + apothem) >> 9); - foreach (ChunkPos regionPos in _server.RenderTaskManager.ChunkLoader.GetAllServerMapRegionPositions()) { + foreach (ChunkPos regionPos in _server.RenderTaskManager.ChunkLoader.GetAllMapRegionPositions()) { if (min != null && (regionPos.X < min.X || regionPos.Z < min.Y)) { continue; } diff --git a/src/command/subcommand/FullRenderCmd.cs b/src/command/subcommand/FullRenderCmd.cs index c19cb90..7aab56c 100644 --- a/src/command/subcommand/FullRenderCmd.cs +++ b/src/command/subcommand/FullRenderCmd.cs @@ -21,7 +21,7 @@ public override TextCommandResult Execute(TextCommandCallingArgs args) { return; } // queue up all existing chunks in the whole world - foreach (ChunkPos regionPos in _server.RenderTaskManager.ChunkLoader.GetAllServerMapRegionPositions()) { + foreach (ChunkPos regionPos in _server.RenderTaskManager.ChunkLoader.GetAllMapRegionPositions()) { _server.RenderTaskManager.Queue(regionPos.X, regionPos.Z); } // trigger autosave to process queue diff --git a/src/configuration/Config.cs b/src/configuration/Config.cs index dcd12b2..2e77a7e 100644 --- a/src/configuration/Config.cs +++ b/src/configuration/Config.cs @@ -4,7 +4,7 @@ namespace livemap.configuration; [PublicAPI] public class Config { - public bool DebugMode { get; set; } + public bool DebugMode { get; set; } = false; public Httpd Httpd { get; set; } = new(); diff --git a/src/configuration/Layers.cs b/src/configuration/Layers.cs index b3a2618..d27de0b 100644 --- a/src/configuration/Layers.cs +++ b/src/configuration/Layers.cs @@ -7,4 +7,8 @@ public class Layers { public Players Players { get; set; } = new(); public Spawn Spawn { get; set; } = new(); + + public Traders Traders { get; set; } = new(); + + public Translocators Translocators { get; set; } = new(); } diff --git a/src/configuration/Players.cs b/src/configuration/Players.cs index ca1047f..1af9020 100644 --- a/src/configuration/Players.cs +++ b/src/configuration/Players.cs @@ -10,9 +10,9 @@ public class Players { public bool DefaultShowLayer { get; set; } = true; - public bool HideUnderBlocks { get; set; } + public bool HideUnderBlocks { get; set; } = false; - public bool HideIfSneaking { get; set; } + public bool HideIfSneaking { get; set; } = false; public bool HideSpectators { get; set; } = true; } diff --git a/src/configuration/Traders.cs b/src/configuration/Traders.cs new file mode 100644 index 0000000..e83dace --- /dev/null +++ b/src/configuration/Traders.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using livemap.layer.marker.options.type; +using Point = livemap.data.Point; + +namespace livemap.configuration; + +[PublicAPI] +public class Traders { + public bool Enabled { get; set; } = false; + + public int UpdateInterval { get; set; } = 30; + + public bool DefaultShowLayer { get; set; } = true; + + public IconOptions IconOptions { get; set; } = new() { + Title = "", + Alt = "", + IconUrl = "#svg-trader", + IconSize = new Point(16, 16) + }; +} diff --git a/src/configuration/Translocators.cs b/src/configuration/Translocators.cs new file mode 100644 index 0000000..802e0e2 --- /dev/null +++ b/src/configuration/Translocators.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using livemap.layer.marker.options.type; +using Point = livemap.data.Point; + +namespace livemap.configuration; + +[PublicAPI] +public class Translocators { + public bool Enabled { get; set; } = false; + + public int UpdateInterval { get; set; } = 30; + + public bool DefaultShowLayer { get; set; } = true; + + public IconOptions IconOptions { get; set; } = new() { + Title = "", + Alt = "", + IconUrl = "#svg-spiral", + IconSize = new Point(16, 16) + }; +} diff --git a/src/configuration/Web.cs b/src/configuration/Web.cs index 340bd46..11b7ee9 100644 --- a/src/configuration/Web.cs +++ b/src/configuration/Web.cs @@ -11,7 +11,7 @@ public class Web { public string Url { get; set; } = "http://localhost:8080"; - public bool ReadOnly { get; set; } + public bool ReadOnly { get; set; } = false; [JsonConverter(typeof(TileTypeJsonConverter))] public TileType TileType { get; set; } = TileType.Webp; diff --git a/src/configuration/Zoom.cs b/src/configuration/Zoom.cs index 21070c6..f897c6b 100644 --- a/src/configuration/Zoom.cs +++ b/src/configuration/Zoom.cs @@ -4,7 +4,7 @@ namespace livemap.configuration; [PublicAPI] public class Zoom { - public int Default { get; set; } + public int Default { get; set; } = 0; public int MaxIn { get; set; } = -3; diff --git a/src/data/ChunkLoader.cs b/src/data/ChunkLoader.cs index 60386c9..5f9bff7 100644 --- a/src/data/ChunkLoader.cs +++ b/src/data/ChunkLoader.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; -using JetBrains.Annotations; using livemap.util; using Microsoft.Data.Sqlite; using Vintagestory.API.Common; @@ -13,7 +12,6 @@ namespace livemap.data; -[PublicAPI] public class ChunkLoader { private readonly ServerMain _server; private readonly SqliteConnection _sqliteConn; @@ -21,7 +19,7 @@ public class ChunkLoader { public ChunkLoader(ICoreServerAPI api) { _server = (api.World as ServerMain)!; - // do not use server's connection, create our own to prevent issues + // do not use server's connection, create our own to prevent concurrency issues (_sqliteConn = new SqliteConnection(new DbConnectionStringBuilder { { "Data Source", _server @@ -36,37 +34,34 @@ public ChunkLoader(ICoreServerAPI api) { _chunkDataPool = new ChunkDataPool(32, _server); } - public IEnumerable GetAllServerMapRegionPositions() { - using SqliteCommand sqlite = _sqliteConn.CreateCommand(); - sqlite.CommandText = "SELECT position, data FROM mapregion"; - using SqliteDataReader reader = sqlite.ExecuteReader(); - while (reader.Read()) { - yield return ChunkPos.FromChunkIndex_saveGamev2((ulong)(long)reader["position"]); - } + public IEnumerable GetAllMapRegionPositions() { + return GetAllMapPositions("region"); } - public IEnumerable GetAllMapChunkPositions() { + return GetAllMapPositions("chunk"); + } + + private IEnumerable GetAllMapPositions(string type) { using SqliteCommand sqlite = _sqliteConn.CreateCommand(); - sqlite.CommandText = "SELECT position FROM mapchunk"; + sqlite.CommandText = $"SELECT position FROM map{type}"; using SqliteDataReader reader = sqlite.ExecuteReader(); while (reader.Read()) { yield return ChunkPos.FromChunkIndex_saveGamev2((ulong)(long)reader["position"]); } } - public ServerMapRegion GetServerMapRegion(ulong position) { + public ServerMapRegion? GetMapRegion(ulong position) { byte[]? regionData = GetTableData(position, "mapregion"); - ServerMapRegion? serverMapChunk = ServerMapRegion.FromBytes(regionData); - return serverMapChunk; + return regionData == null ? null : ServerMapRegion.FromBytes(regionData); } - public ServerMapChunk? GetServerMapChunk(ulong position) { - byte[]? mapChunkData = GetTableData(position, "mapchunk"); - return mapChunkData == null ? null : ServerMapChunk.FromBytes(mapChunkData); + public ServerMapChunk? GetMapChunk(ulong position) { + byte[]? chunkData = GetTableData(position, "mapchunk"); + return chunkData == null ? null : ServerMapChunk.FromBytes(chunkData); } - public ServerChunk? GetServerChunk(ulong position) { + public ServerChunk? GetChunk(ulong position) { byte[]? chunkData = GetTableData(position, "chunk"); ServerChunk? chunk = chunkData == null ? null : ServerChunk.FromBytes(chunkData, _chunkDataPool, _server); chunk?.Unpack_ReadOnly(); diff --git a/src/task/RenderTask.cs b/src/task/RenderTask.cs index a0efa19..7aa78d2 100644 --- a/src/task/RenderTask.cs +++ b/src/task/RenderTask.cs @@ -6,6 +6,7 @@ using livemap.util; using Vintagestory.API.Common; using Vintagestory.API.MathTools; +using Vintagestory.API.Util; using Vintagestory.Common.Database; using Vintagestory.GameContent; using Vintagestory.Server; @@ -27,6 +28,11 @@ public RenderTask(LiveMap server, RenderTaskManager renderTaskManager) { public void ScanRegion(int regionX, int regionZ) { try { + ServerMapRegion? region = _renderTaskManager.ChunkLoader.GetMapRegion(ChunkPos.ToChunkIndex(regionX, 0, regionZ)); + if (region == null) { + return; + } + // check for existing chunks only in this region int chunkX1 = regionX << 4; int chunkZ1 = regionZ << 4; @@ -38,7 +44,7 @@ public void ScanRegion(int regionX, int regionZ) { .Where(chunkPos => chunkPos.X >= chunkX1 && chunkPos.Z >= chunkZ1 && chunkPos.X < chunkX2 && chunkPos.Z < chunkZ2); BlockData blockData = new(); foreach (ChunkPos chunkPos in chunks) { - ScanChunkColumn(chunkPos, blockData); + ScanChunkColumn(region, chunkPos, blockData); } // process the region through all the renderers @@ -53,10 +59,10 @@ public void ScanRegion(int regionX, int regionZ) { } } - private void ScanChunkColumn(ChunkPos chunkPos, BlockData blockData) { + private void ScanChunkColumn(ServerMapRegion region, ChunkPos chunkPos, BlockData blockData) { // get chunkmap from game save // this is just basic info about a chunk column, like heightmaps - ServerMapChunk? mapChunk = _renderTaskManager.ChunkLoader.GetServerMapChunk(ChunkPos.ToChunkIndex(chunkPos.X, chunkPos.Y, chunkPos.Z)); + ServerMapChunk? mapChunk = _renderTaskManager.ChunkLoader.GetMapChunk(ChunkPos.ToChunkIndex(chunkPos.X, chunkPos.Y, chunkPos.Z)); if (mapChunk == null) { return; } @@ -73,10 +79,28 @@ private void ScanChunkColumn(ChunkPos chunkPos, BlockData blockData) { } } + // check which chunk slices need to be loaded to get specific structure data + region.GeneratedStructures? + .Where(s => + s.Code.Contains("trader") || + s.Code.Contains("gates") + ) + .Where(s => + (chunkPos.X << 5) < s.Location.MaxX && + (chunkPos.Z << 5) < s.Location.MaxZ && + (chunkPos.X << 5) + 32 > s.Location.MinX && + (chunkPos.Z << 5) + 32 > s.Location.MinZ + ) + .Foreach(s => { + for (int y = s.Location.Y1 >> 5; y <= s.Location.Y2 >> 5; y++) { + chunkIndexesToLoad.AddIfNotExists(y); + } + }); + // load the actual chunks slices from game save ServerChunk?[] chunkSlices = new ServerChunk?[_server.Sapi.WorldManager.MapSizeY >> 5]; foreach (int y in chunkIndexesToLoad) { - chunkSlices[y] = _renderTaskManager.ChunkLoader.GetServerChunk(ChunkPos.ToChunkIndex(chunkPos.X, y, chunkPos.Z)); + chunkSlices[y] = _renderTaskManager.ChunkLoader.GetChunk(ChunkPos.ToChunkIndex(chunkPos.X, y, chunkPos.Z)); } int startX = chunkPos.X << 5; @@ -95,6 +119,38 @@ private void ScanChunkColumn(ChunkPos chunkPos, BlockData blockData) { foreach ((string _, Renderer renderer) in _server.RendererRegistry) { renderer.ScanChunkColumn(chunkPos, blockData); } + + // process things from structures + // todo - wipe things that are no longer there + chunkSlices.Foreach(chunk => { + if (_server.Config.Layers.Translocators.Enabled) { + chunk?.BlockEntities.Values.Foreach(be => { + if (be is not BlockEntityStaticTranslocator { TargetLocation: not null } tl) { + return; + } + + BlockPos pos = tl.Pos; + BlockPos loc = tl.TargetLocation; + + // save tl to file + Logger.Warn($"Translocator at {pos} points to {loc}"); + }); + } + if (_server.Config.Layers.Traders.Enabled) { + chunk?.Entities.Foreach(e => { + if (e is not EntityTrader trader) { + return; + } + + string type = trader.GetName(); + string? name = trader.WatchedAttributes.GetTreeAttribute("nametag")?.GetString("name"); + BlockPos pos = trader.Pos.AsBlockPos; + + // save trader to file + Logger.Warn($"Trader at {pos} is named {name} (type: {type})"); + }); + } + }); } private BlockData.Data ScanBlockColumn(int x, int z, ServerMapChunk? mapChunk, ServerChunk?[] chunkSlices) {