using System; using System.Collections.Generic; using System.Collections.Specialized; using Vintagestory.API.MathTools; using Vintagestory.API.Common; using ProtoBuf; using System.IO; using System.Collections.ObjectModel; using System.Text; using Vintagestory.API.Client; namespace Automap { [ProtoContract] public struct ColumnMeta { [ProtoMember(1)] [DisplayName(0, "Coords.")] public Vec2i Location; [ProtoMember(2)] [DisplayName(1, "Age")] public TimeSpan ChunkAge;//OLDEST CHUNK. from chunk last edit [ProtoMember(3)] [DisplayName(2, "Temp.")] public float Temperature;// Temperature - surface [ProtoMember(4)] [DisplayName(3, "Y Max.")] public ushort YMax;// Y feature height [ProtoMember(5)] //[DisplayName(10, "Rocks")] public Dictionary RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count] [ProtoMember(6)] [DisplayName(4, "Fert.")] public float Fertility; [ProtoMember(7)] [DisplayName(5, "Forest")] public float ForestDensity; [ProtoMember(8)] [DisplayName(6, "Rain")] public float Rainfall; [ProtoMember(9)] [DisplayName(7, "Shrub")] public float ShrubDensity; [ProtoMember(10)] [DisplayName(8, "Air blocks")] public uint AirBlocks; [ProtoMember(11)] [DisplayName(9, "Non-air")] public uint NonAirBlocks; [ProtoMember(12)] public byte ChunkSize; [ProtoIgnore] public ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization [ProtoMember(13)] private ushort[] _flattened_HeightMap; public ColumnMeta(Vec2i loc, byte chunkSize = 32) { Location = loc; ChunkAge = TimeSpan.Zero; Temperature = 0f; YMax = 0; RockRatio = new Dictionary(10); Fertility = 0f; ForestDensity = 0f; Rainfall = 0f; ShrubDensity = 0f; AirBlocks = 0; NonAirBlocks = 0; ChunkSize = chunkSize; HeightMap = new ushort[ChunkSize, ChunkSize]; _flattened_HeightMap = null; } internal void UpdateFieldsFrom(ClimateCondition climate, IMapChunk mapChunk, TimeSpan chunkAge) { this.ChunkAge = chunkAge; this.Temperature = climate.Temperature; this.Fertility = climate.Fertility; this.ForestDensity = climate.ForestDensity; this.Rainfall = climate.Rainfall; this.ShrubDensity = climate.ShrubDensity; this.YMax = mapChunk.YMax; } [ProtoBeforeSerialization] private void PrepareData() { if (HeightMap != null) { _flattened_HeightMap = new ushort[ChunkSize * ChunkSize]; int flatIndex = 0; for (byte col = 0; col < ChunkSize; col++) { for (byte row = 0; row < ChunkSize; row++) { _flattened_HeightMap[flatIndex] = HeightMap[col, row]; flatIndex++; } } } } [ProtoAfterDeserialization] private void PostProcess() { if (this.HeightMap == null) this.HeightMap = new ushort[ChunkSize, ChunkSize]; if (_flattened_HeightMap != null) { int col, row; _ = new BitVector32(0); var rowSection = BitVector32.CreateSection((short) (ChunkSize - 1)); var colSection = BitVector32.CreateSection((short) (ChunkSize - 1), rowSection); for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++) { BitVector32 bitMasker = new BitVector32(data: (int) rowcol); row = bitMasker[rowSection]; col = bitMasker[colSection]; HeightMap[col, row] = _flattened_HeightMap[rowcol]; } } } } public class ColumnsMetadata : KeyedCollection { private ColumnsMetadata() { throw new NotSupportedException(); } public ColumnsMetadata(Vec2i startChunkColumn) { North_mostChunk = startChunkColumn.Y; South_mostChunk = startChunkColumn.Y; East_mostChunk = startChunkColumn.X; West_mostChunk = startChunkColumn.X; } public int North_mostChunk { get; private set; } public int South_mostChunk { get; private set; } public int East_mostChunk { get; private set; } public int West_mostChunk { get; private set; } protected override Vec2i GetKeyForItem(ColumnMeta item) { return item.Location; } internal void Update(ColumnMeta metaData) { if (this.Contains(metaData.Location)) { this.Remove(metaData.Location); this.Add(metaData); } else { this.Add(metaData); } } public new void Add(ColumnMeta newItem) { if (North_mostChunk > newItem.Location.Y) { North_mostChunk = newItem.Location.Y; } if (South_mostChunk < newItem.Location.Y) { South_mostChunk = newItem.Location.Y; } if (East_mostChunk < newItem.Location.X) { East_mostChunk = newItem.Location.X; } if (West_mostChunk > newItem.Location.X) { West_mostChunk = newItem.Location.X; } base.Add(newItem); } } }