X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Automap%2FAutomapMod.cs;h=7b24649005f7410c1b8e5efa665b1fcfcc9ae529;hb=fabec3e99852e26734177455a7c8745f87533308;hp=73fc20308345d714ede912c6f19a8b4b478f15d8;hpb=5dfa52b08402347a6ffdb64843aedaac9a8136f5;p=automap%2Fautomap.git diff --git a/Automap/AutomapMod.cs b/Automap/AutomapMod.cs index 73fc203..7b24649 100644 --- a/Automap/AutomapMod.cs +++ b/Automap/AutomapMod.cs @@ -1,282 +1,121 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Threading; -using System.Drawing; -using System.Drawing.Imaging; +using System.Collections.ObjectModel; using System.Linq; - using Vintagestory.API.Client; using Vintagestory.API.Common; -using Vintagestory.API.Common.Entities; -using Vintagestory.API.Config; -using Vintagestory.API.MathTools; -using Vintagestory.API.Server; -using Vintagestory.GameContent; -using Vintagestory.API.Datastructures; namespace Automap { - public class AutomapMod : ModSystem - { - private ICoreAPI API { get; set; } - private ICoreClientAPI ClientAPI { get; set; } - private ILogger Logger { get; set; } + public class AutomapMod : ModSystem + { + public const string _configFilename = @"automap.json"; - private const string _mapPath = @"Maps"; - private const string _chunkPath = @"Chunks"; - private readonly object colLock = new object( ); - private Dictionary columnCounter = new Dictionary(); - private HashSet knownChunkTops = new HashSet(); - private Vec2i startPosition; + private ICoreAPI API { get; set; } + private ICoreClientAPI ClientAPI { get; set; } + private ILogger Logger { get; set; } + private AutomapSystem _localAutomap; + private AutomapGUIDialog _automapDialog; - private Thread cartographer_thread; - public override bool ShouldLoad(EnumAppSide forSide) - { - return forSide.IsClient(); - } + public override bool ShouldLoad(EnumAppSide forSide) + { + return forSide.IsClient(); + } public override void StartClientSide(ICoreClientAPI api) - { + { this.API = api; - if (api.Side == EnumAppSide.Client) { - this.ClientAPI = api as ICoreClientAPI; - this.Logger = Mod.Logger; - - ClientAPI.Event.LevelFinalize += StartAutomap; - } + if (api.Side == EnumAppSide.Client) + { + this.ClientAPI = api as ICoreClientAPI; + this.Logger = Mod.Logger; - base.StartClientSide(api); - } + ClientAPI.Logger.VerboseDebug("Automap Present!"); + PrepareClientsideConfig( ); + _localAutomap = new AutomapSystem(this.ClientAPI, this.Logger, this.CachedConfiguration); + _automapDialog = new AutomapGUIDialog(ClientAPI, _localAutomap, this.CachedConfiguration); - public override double ExecuteOrder( ) - { - return 0.2; - } + ClientAPI.Input.RegisterHotKey(AutomapGUIDialog._automapControlPanelKey, "Automap control panel", GlKeys.M, HotkeyType.GUIOrOtherControls, shiftPressed: true); + ClientAPI.Input.SetHotKeyHandler(AutomapGUIDialog._automapControlPanelKey, ToggleAM_Dialog); + ClientAPI.Event.LeaveWorld += PersistParameterChange; + } + base.StartClientSide(api); + } - #region Internals - private void StartAutomap( ) + public override double ExecuteOrder() { - Mod.Logger.Notification("AUTOMAP SETUP"); - startPosition = new Vec2i(ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X, ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z); - ClientAPI.Event.ChunkDirty += ChunkAChanging; - - cartographer_thread = new Thread(Cartographer); - cartographer_thread.Name = "Cartographer"; - cartographer_thread.Priority = ThreadPriority.Lowest; - cartographer_thread.IsBackground = true; - - ClientAPI.Event.RegisterGameTickListener(AwakenCartographer, 6000); + return 1.2; } - private void AwakenCartographer(float delayed) + private bool ToggleAM_Dialog(KeyCombination comb) { + if (_automapDialog.IsOpened()) _automapDialog.TryClose(); + else _automapDialog.TryOpen(); - if (ClientAPI.IsGamePaused != false || ClientAPI.IsShuttingDown != true) - { - #if DEBUG - Logger.VerboseDebug("Cartographer re-trigger from [{0}]", cartographer_thread.ThreadState); - #endif - - if (cartographer_thread.ThreadState.HasFlag(ThreadState.Unstarted)) - { - cartographer_thread.Start( ); - } - else if (cartographer_thread.ThreadState.HasFlag(ThreadState.WaitSleepJoin)) { - //Time to (re)write chunk shards - cartographer_thread.Interrupt( ); - } + return true; } - } - - - private void Cartographer( ) - { - wake: - Logger.VerboseDebug("Cartographer thread awoken"); - - try { - - while (columnCounter.Count > 0) + internal PersistedConfiguration CachedConfiguration { + get { - var mostActiveCol = columnCounter.OrderByDescending(kvp => kvp.Value).First(); - var mapChunk = ClientAPI.World.BlockAccessor.GetMapChunk(mostActiveCol.Key); - Logger.VerboseDebug("Selected: ({0}) - Edits#:{1}", mostActiveCol.Key, mostActiveCol.Value); - - if (mapChunk == null) { - Logger.Warning("SKIP CHUNK: ({0}) - Map Chunk NULL!",mostActiveCol.Key); - columnCounter.Remove(mostActiveCol.Key); - continue; + return ( PersistedConfiguration )ClientAPI.ObjectCache[_configFilename]; } - - string filename = $"{mostActiveCol.Key.X}_{mostActiveCol.Key.Y}.png"; - - filename = Path.Combine(ClientAPI.GetOrCreateDataPath(_mapPath), filename); - - var chkImg = GenerateChunkImage(mostActiveCol.Key, mapChunk); - - chkImg.Save(filename, ImageFormat.Png); - - knownChunkTops.Add(mostActiveCol.Key); - columnCounter.Remove(mostActiveCol.Key); - } - - - - //Then sleep until interupted again, and repeat - - Logger.VerboseDebug("Thread '{0}' about to sleep indefinitely.", Thread.CurrentThread.Name); - - Thread.Sleep(Timeout.Infinite); - - } catch (ThreadInterruptedException) { - - Logger.VerboseDebug("Thread '{0}' interupted [awoken]", Thread.CurrentThread.Name); - goto wake; - - } catch (ThreadAbortException) { - Logger.VerboseDebug("Thread '{0}' aborted.", Thread.CurrentThread.Name); - - } finally { - Logger.VerboseDebug("Thread '{0}' executing finally block.", Thread.CurrentThread.Name); - } - } - #endregion - - - - private void ChunkAChanging(Vec3i chunkCoord, IWorldChunk chunk, EnumChunkDirtyReason reason) - { - //Logger.VerboseDebug($"Change: @({chunkCoord}) R: {reason}"); - Vec2i topPosition = new Vec2i(chunkCoord.X, chunkCoord.Z); - - lock (colLock) + set { - if (columnCounter.ContainsKey(topPosition)) { columnCounter[topPosition]++; } else { columnCounter.Add(topPosition, 1); } + ClientAPI.ObjectCache.Add(_configFilename, value); } - } - private void print_stats(float interval) + private void PrepareClientsideConfig( ) { - if (columnCounter != null && columnCounter.Count > 0) { - foreach (var count in columnCounter) { - Logger.VerboseDebug($"({count.Key}): {count.Value}"); - } - } + PersistedConfiguration config = ClientAPI.LoadModConfig(_configFilename); + if (config == null) { + //Regen default + Mod.Logger.Warning("Regenerating default config as it was missing / unparsable..."); + ClientAPI.StoreModConfig(new PersistedConfiguration(defaults: true ), _configFilename); + config = ClientAPI.LoadModConfig(_configFilename); } - - #region COPYPASTA - public Bitmap GenerateChunkImage(Vec2i chunkPos, IMapChunk mc) - { - BlockPos tmpPos = new BlockPos( ); - Vec2i localpos = new Vec2i( ); - int chunkSize = ClientAPI.World.BlockAccessor.ChunkSize; - var chunksColumn = new IWorldChunk[ClientAPI.World.BlockAccessor.MapSizeY / chunkSize]; - Bitmap chunkImage = new Bitmap(chunkSize, chunkSize, PixelFormat.Format24bppRgb ); - int topChunkY = mc.YMax / chunkSize;//Heywaitaminute -- this isn't a highest FEATURE, if Rainmap isn't accurate! - //Metadata of DateTime chunk was edited, chunk coords.,world-seed? Y-Max feature height - //Grab a chunk COLUMN... Topmost Y down... - for (int chunkY = 0; chunkY < topChunkY; chunkY++) { - chunksColumn[chunkY] = ClientAPI.World.BlockAccessor.GetChunk(chunkPos.X, chunkY, chunkPos.Y); - //What to do if chunk is a void? invalid? + this.CachedConfiguration = config; } - - // Prefetch map chunks, in pattern - IMapChunk[ ] mapChunks = new IMapChunk[ ] - { - ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y - 1), - ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X - 1, chunkPos.Y), - ClientAPI.World.BlockAccessor.GetMapChunk(chunkPos.X, chunkPos.Y - 1) - }; - - - for (int posIndex = 0; posIndex < (chunkSize * chunkSize); posIndex++) { - int mapY = mc.RainHeightMap[posIndex]; - int localChunkY = mapY / chunkSize; - if (localChunkY >= (chunksColumn.Length ) ) continue;//Out of range! - - MapUtil.PosInt2d(posIndex, chunkSize, localpos); - int localX = localpos.X; - int localZ = localpos.Y; - float b = 1; - int leftTop, rightTop, leftBot; - - IMapChunk leftTopMapChunk = mc; - IMapChunk rightTopMapChunk = mc; - IMapChunk leftBotMapChunk = mc; - - int topX = localX - 1; - int botX = localX; - int leftZ = localZ - 1; - int rightZ = localZ; + internal void PersistParameterChange( ) + { + //Store altered parameters - if (topX < 0 && leftZ < 0) { - leftTopMapChunk = mapChunks[0]; - rightTopMapChunk = mapChunks[1]; - leftBotMapChunk = mapChunks[2]; - } - else { - if (topX < 0) { - leftTopMapChunk = mapChunks[1]; - rightTopMapChunk = mapChunks[1]; + ClientAPI.StoreModConfig(this.CachedConfiguration, _configFilename); } - if (leftZ < 0) { - leftTopMapChunk = mapChunks[2]; - leftBotMapChunk = mapChunks[2]; - } - } - - topX = GameMath.Mod(topX, chunkSize); - leftZ = GameMath.Mod(leftZ, chunkSize); - - leftTop = leftTopMapChunk == null ? 0 : Math.Sign(mapY - leftTopMapChunk.RainHeightMap[leftZ * chunkSize + topX]); - rightTop = rightTopMapChunk == null ? 0 : Math.Sign(mapY - rightTopMapChunk.RainHeightMap[rightZ * chunkSize + topX]); - leftBot = leftBotMapChunk == null ? 0 : Math.Sign(mapY - leftBotMapChunk.RainHeightMap[leftZ * chunkSize + botX]); - - float slopeness = (leftTop + rightTop + leftBot); - if (slopeness > 0) b = 1.2f; - if (slopeness < 0) b = 0.8f; + #region External Interfaces + //Perhaps Other mods can make use of POI / EOI? - b -= 0.15f; // Map seems overally a bit too bright - //b = 1; - if (chunksColumn[localChunkY] == null) { - - continue; + public ReadOnlyCollection PointsOfInterest { + get + { + return _localAutomap.POIs.ToList().AsReadOnly(); + } } - chunksColumn[localChunkY].Unpack( ); - int blockId = chunksColumn[localChunkY].Blocks[MapUtil.Index3d(localpos.X, mapY % chunkSize, localpos.Y, chunkSize, chunkSize)]; - Block block = ClientAPI.World.Blocks[blockId]; - - tmpPos.Set(chunkSize * chunkPos.X + localpos.X, mapY, chunkSize * chunkPos.Y + localpos.Y); - - int avgCol = block.GetColor(ClientAPI, tmpPos); - int rndCol = block.GetRandomColor(ClientAPI, tmpPos, BlockFacing.UP); - //Merge color? - int col = ColorUtil.ColorOverlay(avgCol, rndCol, 0.25f); - var packedFormat = ColorUtil.ColorMultiply3Clamped(col, b) | 255 << 24;//Is the Struct, truly so undesirable? - - Color pixelColor = Color.FromArgb(ColorUtil.ColorR(packedFormat), ColorUtil.ColorG(packedFormat), ColorUtil.ColorB(packedFormat)); - chunkImage.SetPixel(localX,localZ, pixelColor); + public ReadOnlyCollection EntitiesOfInterest { + get + { + return _localAutomap.EOIs.ToList().AsReadOnly(); + } } - - return chunkImage; + public CommandType Status + { + get { return _localAutomap.CurrentState; } } + #endregion + + } }