OSDN Git Service

Initial 0.1 W.I.P. version
authormelchior <melchior@users.osdn.me>
Wed, 4 Dec 2019 21:47:25 +0000 (16:47 -0500)
committermelchior <melchior@users.osdn.me>
Wed, 4 Dec 2019 21:47:25 +0000 (16:47 -0500)
.gitignore [new file with mode: 0644]
Automap.sln [new file with mode: 0644]
Automap/Automap.csproj [new file with mode: 0644]
Automap/AutomapMod.cs [new file with mode: 0644]
Automap/Properties/AssemblyInfo.cs [new file with mode: 0644]
Automap/modinfo.json [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7bbcfed
--- /dev/null
@@ -0,0 +1,40 @@
+#Autosave files\r
+*~\r
+\r
+#build\r
+[Oo]bj/\r
+[Bb]in/\r
+packages/\r
+TestResults/\r
+\r
+# globs\r
+Makefile.in\r
+*.DS_Store\r
+*.sln.cache\r
+*.suo\r
+*.cache\r
+*.pidb\r
+*.userprefs\r
+*.usertasks\r
+config.log\r
+config.make\r
+config.status\r
+aclocal.m4\r
+install-sh\r
+autom4te.cache/\r
+*.user\r
+*.tar.gz\r
+tarballs/\r
+test-results/\r
+Thumbs.db\r
+\r
+#Mac bundle stuff\r
+*.dmg\r
+*.app\r
+\r
+#resharper\r
+*_Resharper.*\r
+*.Resharper\r
+\r
+#dotCover\r
+*.dotCover\r
diff --git a/Automap.sln b/Automap.sln
new file mode 100644 (file)
index 0000000..6555777
--- /dev/null
@@ -0,0 +1,17 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 2012\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automap", "Automap\Automap.csproj", "{0287E0DF-B785-40E8-BB50-2D684B45FC61}"\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Any CPU = Debug|Any CPU\r
+               Release|Any CPU = Release|Any CPU\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {0287E0DF-B785-40E8-BB50-2D684B45FC61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {0287E0DF-B785-40E8-BB50-2D684B45FC61}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {0287E0DF-B785-40E8-BB50-2D684B45FC61}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {0287E0DF-B785-40E8-BB50-2D684B45FC61}.Release|Any CPU.Build.0 = Release|Any CPU\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/Automap/Automap.csproj b/Automap/Automap.csproj
new file mode 100644 (file)
index 0000000..ba82df0
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{0287E0DF-B785-40E8-BB50-2D684B45FC61}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Automap</RootNamespace>
+    <AssemblyName>Automap</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>              
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="AfterBuild" command="7z -tzip a ${ProjectName}_${ProjectConfig}.zip" workingdir="${TargetDir}" />
+        <Command type="AfterClean" command="rm -f *.zip" workingdir="${TargetDir}" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="AfterBuild" command="7z -tzip a ${ProjectName}_${ProjectConfig}.zip" workingdir="${TargetDir}" />
+        <Command type="AfterClean" command="rm -f *.zip" workingdir="${TargetDir}" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="VintagestoryAPI">
+      <HintPath>VS_libs\VintagestoryAPI.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VintagestoryLib">
+      <HintPath>VS_libs\VintagestoryLib.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VSCreativeMod">
+      <HintPath>VS_libs\VSCreativeMod.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VSEssentials">
+      <HintPath>VS_libs\VSEssentials.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VSSurvivalMod">
+      <HintPath>VS_libs\VSSurvivalMod.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System.Drawing" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AutomapMod.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="VS_libs\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="modinfo.json">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/Automap/AutomapMod.cs b/Automap/AutomapMod.cs
new file mode 100644 (file)
index 0000000..73fc203
--- /dev/null
@@ -0,0 +1,282 @@
+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.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; }
+
+               private const string _mapPath = @"Maps";
+               private const string _chunkPath = @"Chunks";
+               private readonly object colLock = new object( );
+               private Dictionary<Vec2i, uint> columnCounter = new Dictionary<Vec2i, uint>();
+               private HashSet<Vec2i> knownChunkTops = new HashSet<Vec2i>();
+               private Vec2i startPosition;
+
+               private Thread cartographer_thread;
+
+               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;
+                       }
+
+                       base.StartClientSide(api);
+               }
+
+               public override double ExecuteOrder( )
+               {
+               return 0.2;
+               }
+
+
+
+               #region Internals
+               private void StartAutomap( )
+               {
+               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);
+               }
+
+               private void AwakenCartographer(float delayed)
+               {
+
+               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( );
+                       }
+               }
+
+               }
+
+
+               private void Cartographer( )
+               {
+       wake:
+               Logger.VerboseDebug("Cartographer thread awoken");
+
+               try {
+
+                       while (columnCounter.Count > 0) 
+                       {
+                       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;
+                       }
+
+                       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)
+                       {
+                       if (columnCounter.ContainsKey(topPosition)) { columnCounter[topPosition]++; } else { columnCounter.Add(topPosition, 1); }
+                       }
+
+               }
+
+               private void print_stats(float interval)
+               {
+               if (columnCounter != null && columnCounter.Count > 0) {
+               foreach (var count in columnCounter) {
+               Logger.VerboseDebug($"({count.Key}): {count.Value}");
+               }
+               }
+
+               }
+
+
+               #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?
+               }
+               
+               // 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;
+
+               if (topX < 0 && leftZ < 0) {
+               leftTopMapChunk = mapChunks[0];
+               rightTopMapChunk = mapChunks[1];
+               leftBotMapChunk = mapChunks[2];
+               }
+               else {
+               if (topX < 0) {
+               leftTopMapChunk = mapChunks[1];
+               rightTopMapChunk = mapChunks[1];
+               }
+               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;
+
+               b -= 0.15f; // Map seems overally a bit too bright
+                                       //b = 1;
+               if (chunksColumn[localChunkY] == null) {
+                       
+               continue;
+               }
+
+               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);
+               }
+
+
+               return chunkImage;
+               }
+               #endregion
+       }
+}
+
diff --git a/Automap/Properties/AssemblyInfo.cs b/Automap/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..5ff8c4c
--- /dev/null
@@ -0,0 +1,31 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes. 
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Automap")]
+[assembly: AssemblyDescription("Automap Plugin for V.S.")]
+#if DEBUG
+[assembly: AssemblyConfiguration("DEBUG")]
+#else
+[assembly: AssemblyConfiguration("RELEASE")]
+#endif
+[assembly: AssemblyCompany("MelCo.")]
+[assembly: AssemblyProduct("Automap Plugin")]
+[assembly: AssemblyCopyright("Melchior")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly, 
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/Automap/modinfo.json b/Automap/modinfo.json
new file mode 100644 (file)
index 0000000..a233f40
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "type": "code",
+  "name": "Automap",
+  "description" : "Automap; slices, dices and lightly sautees your map!",
+  "authors": ["Melchior"],
+  "version": "0.1.0",
+  "dependencies": { 
+       "game": "1.11.0"        
+  },
+  "website": "http://nowebsite.nope"
+}
\ No newline at end of file