• R/O
  • HTTP
  • SSH
  • HTTPS

automap: 提交

Automap (OSS) GIT software repository


Commit MetaInfo

修订版01a930a1c73adca96b7f4b23b4cffff18f24c45d (tree)
时间2020-03-31 00:35:38
作者melchior <melchior@user...>
Commitermelchior

Log Message

Merge branch 'vgd' of into Split_renderers
(Pass 1, absent new Json generation, incomplete)

更改概述

差异

--- a/Automap/Automap.csproj
+++ b/Automap/Automap.csproj
@@ -79,22 +79,24 @@
7979 <Compile Include="AutomapMod.cs" />
8080 <Compile Include="Properties\AssemblyInfo.cs" />
8181 <Compile Include="Helpers.cs" />
82- <Compile Include="Data\PointOfInterest.cs" />
83- <Compile Include="Data\BlockDesignator.cs" />
84- <Compile Include="Designators\DefaultDesignators.cs" />
85- <Compile Include="Data\ColumnMeta.cs" />
82+ <Compile Include="Data\PointOfInterest.cs" />
83+ <Compile Include="Data\BlockDesignator.cs" />
84+ <Compile Include="Data\EntitiesOfInterest.cs" />
85+ <Compile Include="Data\EntityDesignator.cs" />
86+ <Compile Include="Data\ColumnMeta.cs" />
8687 <Compile Include="Data\PngMetadataChunk.cs" />
88+ <Compile Include="Designators\DefaultDesignators.cs" />
8789 <Compile Include="Subsystems\AutomapSystem.cs" />
8890 <Compile Include="Subsystems\AutomapGUIDialog.cs" />
8991 <Compile Include="Renderers\IChunkRenderer.cs" />
90- <Compile Include="Renderers\StandardRenerer.cs" />
92+ <Compile Include="Renderers\StandardRenderer.cs" />
9193 <Compile Include="Renderers\AlternateRenderer.cs" />
92- <Compile Include="Data\EntitiesOfInterest.cs" />
93- <Compile Include="Data\EntityDesignator.cs" />
9494 <Compile Include="Data\StatusData.cs" />
9595 <Compile Include="Data\CommandData.cs" />
9696 <Compile Include="Data\CommandType.cs" />
9797 <Compile Include="Data\PersistedConfiguration.cs" />
98+ <Compile Include="Data\DisplayNameAttribute.cs" />
99+ <Compile Include="Subsystems\JsonGenerator.cs" />
98100 </ItemGroup>
99101 <ItemGroup>
100102 <Folder Include="VS_libs\" />
--- a/Automap/Data/BlockDesignator.cs
+++ b/Automap/Data/BlockDesignator.cs
@@ -12,7 +12,7 @@ using Vintagestory.API.MathTools;
1212
1313 namespace Automap
1414 {
15- public delegate void BlockDesignatonAction(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block);
15+ public delegate void BlockDesignatorAction(ICoreClientAPI clientAPI, PointsOfInterest poi, BlockPos posn, Block block);
1616
1717 /// <summary>
1818 /// Point of Interest Rule Designator
@@ -24,7 +24,7 @@ namespace Automap
2424 public Color OverwriteColor;
2525
2626 [JsonIgnore]
27- public BlockDesignatonAction SpecialAction;
27+ public BlockDesignatorAction SpecialAction;
2828
2929 [JsonProperty]
3030 public string SpecialActionName;
@@ -51,7 +51,7 @@ namespace Automap
5151 this.Enabled = true;
5252 }
5353
54- public BlockDesignator(AssetLocation pattern, Color overwriteColor, EnumBlockMaterial? material, BlockDesignatonAction specialAct)
54+ public BlockDesignator(AssetLocation pattern, Color overwriteColor, EnumBlockMaterial? material, BlockDesignatorAction specialAct)
5555 {
5656 this.Pattern = pattern;
5757 this.OverwriteColor = overwriteColor;
--- a/Automap/Data/ColumnMeta.cs
+++ b/Automap/Data/ColumnMeta.cs
@@ -1,6 +1,5 @@
11 using System;
22 using System.Collections.Generic;
3-using System.Collections.ObjectModel;
43 using System.Collections.Specialized;
54
65
@@ -8,7 +7,10 @@ using Vintagestory.API.MathTools;
87 using Vintagestory.API.Common;
98
109 using ProtoBuf;
11-
10+using System.IO;
11+using System.Collections.ObjectModel;
12+using System.Text;
13+using Vintagestory.API.Client;
1214
1315 namespace Automap
1416 {
@@ -16,36 +18,47 @@ namespace Automap
1618 public struct ColumnMeta
1719 {
1820 [ProtoMember(1)]
21+ [DisplayName(0, "Coords.")]
1922 public Vec2i Location;
2023
2124 [ProtoMember(2)]
25+ [DisplayName(1, "Age")]
2226 public TimeSpan ChunkAge;//OLDEST CHUNK. from chunk last edit
2327
2428 [ProtoMember(3)]
29+ [DisplayName(2, "Temp.")]
2530 public float Temperature;// Temperature - surface
2631
2732 [ProtoMember(4)]
33+ [DisplayName(3, "Y Max.")]
2834 public ushort YMax;// Y feature height
2935
3036 [ProtoMember(5)]
37+ //[DisplayName(10, "Rocks")]
3138 public Dictionary<int, uint> RockRatio;//[Column] Geographic region (rock) Ratio. [BlockID * count]
3239
3340 [ProtoMember(6)]
41+ [DisplayName(4, "Fert.")]
3442 public float Fertility;
3543
3644 [ProtoMember(7)]
45+ [DisplayName(5, "Forest")]
3746 public float ForestDensity;
3847
3948 [ProtoMember(8)]
49+ [DisplayName(6, "Rain")]
4050 public float Rainfall;
4151
4252 [ProtoMember(9)]
53+ [DisplayName(7, "Shrub")]
4354 public float ShrubDensity;
4455
4556 [ProtoMember(10)]
57+ [DisplayName(8, "Air blocks")]
4658 public uint AirBlocks;
4759
4860 [ProtoMember(11)]
61+ [DisplayName(9, "Non-air")]
4962 public uint NonAirBlocks;
5063
5164 [ProtoMember(12)]
@@ -56,7 +69,7 @@ namespace Automap
5669 public ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization
5770
5871 [ProtoMember(13)]
59- private ushort[ ] _flattened_HeightMap;
72+ private ushort[] _flattened_HeightMap;
6073
6174
6275 public ColumnMeta(Vec2i loc, byte chunkSize = 32)
@@ -89,48 +102,70 @@ namespace Automap
89102 this.YMax = mapChunk.YMax;
90103 }
91104
92-
105+ public void Write(StreamWriter stream, ICoreClientAPI ClientApi)
106+ {
107+ // this is gross i hate this
108+ stream.Write("['{0}_{1}',[",
109+ Location.X,
110+ Location.Y
111+ );
112+ stream.Write("'{0}',", Location.PrettyCoords(ClientApi));
113+ stream.Write("'{0}',", ChunkAge);
114+ stream.Write("'{0}',", Temperature.ToString("F3"));
115+ stream.Write("'{0}',", YMax);
116+ stream.Write("'{0}',", Fertility.ToString("F3"));
117+ stream.Write("'{0}',", ForestDensity.ToString("F3"));
118+ stream.Write("'{0}',", Rainfall.ToString("F3"));
119+ stream.Write("'{0}',", ShrubDensity.ToString("F3"));
120+ stream.Write("'{0}',", AirBlocks);
121+ stream.Write("'{0}',", NonAirBlocks);
122+ stream.Write("]]");
123+ }
93124
94125 [ProtoBeforeSerialization]
95- private void PrepareData( )
126+ private void PrepareData()
96127 {
97128
98- if (HeightMap != null) {
99- _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
100- int flatIndex = 0;
129+ if (HeightMap != null)
130+ {
131+ _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
132+ int flatIndex = 0;
133+
134+ for (byte col = 0; col < ChunkSize; col++)
135+ {
136+ for (byte row = 0; row < ChunkSize; row++)
137+ {
138+ _flattened_HeightMap[flatIndex] = HeightMap[col, row];
139+ flatIndex++;
140+ }
141+ }
101142
102- for (byte col = 0; col < ChunkSize; col++) {
103- for (byte row = 0; row < ChunkSize; row++) {
104- _flattened_HeightMap[flatIndex] = HeightMap[col, row];
105- flatIndex++;
106143 }
107- }
108-
109- }
110144
111145 }
112146
113147
114148 [ProtoAfterDeserialization]
115- private void PostProcess( )
149+ private void PostProcess()
116150 {
117- if (this.HeightMap == null) this.HeightMap = new ushort[ChunkSize, ChunkSize];
118-
119- if (_flattened_HeightMap != null) {
120- int col, row;
151+ if (this.HeightMap == null) this.HeightMap = new ushort[ChunkSize, ChunkSize];
121152
122- BitVector32 bitMasker = new BitVector32(0);
123- var rowSection = BitVector32.CreateSection(( short )(ChunkSize - 1));
124- var colSection = BitVector32.CreateSection(( short )(ChunkSize - 1), rowSection);
125-
126- for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++) {
127- bitMasker = new BitVector32(data: ( int )rowcol);
128- row = bitMasker[rowSection];
129- col = bitMasker[colSection];
130- HeightMap[col, row] = _flattened_HeightMap[rowcol];
131- }
153+ if (_flattened_HeightMap != null)
154+ {
155+ int col, row;
156+ _ = new BitVector32(0);
157+ var rowSection = BitVector32.CreateSection((short) (ChunkSize - 1));
158+ var colSection = BitVector32.CreateSection((short) (ChunkSize - 1), rowSection);
159+
160+ for (uint rowcol = 0; rowcol < (ChunkSize * ChunkSize); rowcol++)
161+ {
162+ BitVector32 bitMasker = new BitVector32(data: (int) rowcol);
163+ row = bitMasker[rowSection];
164+ col = bitMasker[colSection];
165+ HeightMap[col, row] = _flattened_HeightMap[rowcol];
166+ }
132167
133- }
168+ }
134169
135170 }
136171
@@ -217,5 +252,4 @@ namespace Automap
217252 }
218253
219254 }
220-}
221-
255+}
\ No newline at end of file
--- /dev/null
+++ b/Automap/Data/DisplayNameAttribute.cs
@@ -0,0 +1,17 @@
1+using System;
2+using System.Reflection;
3+
4+namespace Automap
5+{
6+ [AttributeUsage(AttributeTargets.Field)]
7+ public class DisplayNameAttribute : Attribute
8+ {
9+ public string name;
10+ public byte order;
11+ public DisplayNameAttribute(byte order, string name)
12+ {
13+ this.order = order;
14+ this.name = name;
15+ }
16+ }
17+}
\ No newline at end of file
--- a/Automap/Data/EntitiesOfInterest.cs
+++ b/Automap/Data/EntitiesOfInterest.cs
@@ -1,36 +1,46 @@
11 using System;
22 using System.Collections.Generic;
33 using System.Collections.ObjectModel;
4-
4+using System.IO;
55 using System.Linq;
66
77 using Vintagestory.API.Common.Entities;
88 using Vintagestory.API.MathTools;
9+using Vintagestory.API.Client;
910
1011 using ProtoBuf;
1112
13+using Newtonsoft.Json;
14+
1215 namespace Automap
1316 {
1417 /// <summary>
15- /// Actual Physical Point in space - that is interesting.
18+ /// Basically the same as a POI but for an entity
1619 /// </summary>
1720 [ProtoContract]
1821 public struct EntityOfInterest
1922 {
23+
2024 [ProtoMember(1)]
2125 public string Name;
22-
26+
27+ [DisplayName(1, "Notes")]
2328 [ProtoMember(2)]
2429 public string Notes;
2530
31+ [DisplayName(0, "Loc.")]
2632 [ProtoMember(3)]
2733 public BlockPos Location;
2834
35+ [DisplayName(2, "Time")]
2936 [ProtoMember(4)]
3037 public DateTime Timestamp;
3138
39+ [DisplayName(3, "ID")]
3240 [ProtoMember(5)]
3341 public long EntityId;
42+
43+
3444 }
3545
3646 /// <summary>
@@ -39,6 +49,8 @@ namespace Automap
3949 /// <remarks>Tracked by ID - these never leave.</remarks>
4050 public class EntitiesOfInterest : KeyedCollection<long, EntityOfInterest>
4151 {
52+ protected override long GetKeyForItem(EntityOfInterest item)
53+ => item.EntityId;
4254
4355 internal void AddReplace(EntityOfInterest entity)
4456 {
@@ -48,8 +60,6 @@ namespace Automap
4860 Add(entity);
4961 }
5062
51- protected override long GetKeyForItem(EntityOfInterest item)
52- => item.EntityId;
5363 }
5464 }
5565
--- a/Automap/Data/EntityDesignator.cs
+++ b/Automap/Data/EntityDesignator.cs
@@ -13,7 +13,7 @@ using Vintagestory.API.MathTools;
1313
1414 namespace Automap
1515 {
16- public delegate void EntityDesignatonAction(ICoreClientAPI clientAPI, EntitiesOfInterest poi, BlockPos posn, Entity entity);
16+ public delegate void EntityDesignatorAction(ICoreClientAPI clientAPI, EntitiesOfInterest poi, BlockPos posn, Entity entity);
1717
1818 /// <summary>
1919 /// Point of Interest Rule Designator
@@ -25,7 +25,7 @@ namespace Automap
2525 public Color Color;
2626
2727 [JsonIgnore]
28- public EntityDesignatonAction SpecialAction;
28+ public EntityDesignatorAction SpecialAction;
2929
3030 [JsonProperty]
3131 public string SpecialActionName;
@@ -52,7 +52,7 @@ namespace Automap
5252 Enabled = true;
5353 }
5454
55- public EntityDesignator(AssetLocation pattern, Color color, EnumEntityState? state, EntityDesignatonAction specialAct)
55+ public EntityDesignator(AssetLocation pattern, Color color, EnumEntityState? state, EntityDesignatorAction specialAct)
5656 {
5757 Pattern = pattern;
5858 Color = color;
--- a/Automap/Data/PointOfInterest.cs
+++ b/Automap/Data/PointOfInterest.cs
@@ -1,11 +1,15 @@
11 using System;
22 using System.Collections.ObjectModel;
3+using System.IO;
34
5+using Vintagestory.API.Client;
46 using Vintagestory.API.Common;
57 using Vintagestory.API.MathTools;
68
79 using ProtoBuf;
810
11+using Newtonsoft.Json;
12+
913 namespace Automap
1014 {
1115 /// <summary>
@@ -17,14 +21,19 @@ namespace Automap
1721 [ProtoMember(1)]
1822 public string Name;
1923
24+ [DisplayName(1, "Notes")]
2025 [ProtoMember(2)]
2126 public string Notes;
2227
28+ [DisplayName(0, "Loc.")]
2329 [ProtoMember(3)]
2430 public BlockPos Location;
2531
32+ [DisplayName(2, "Time")]
2633 [ProtoMember(4)]
2734 public DateTime Timestamp;
35+
36+
2837 }
2938
3039 public class PointsOfInterest : KeyedCollection<BlockPos, PointOfInterest>
--- a/Automap/Designators/DefaultDesignators.cs
+++ b/Automap/Designators/DefaultDesignators.cs
@@ -135,7 +135,7 @@ namespace Automap
135135
136136 internal static void KeepTrackOfMerchant(ICoreClientAPI clientAPI, EntitiesOfInterest poi, BlockPos posn, Entity entity)
137137 {
138- clientAPI.Logger.VerboseDebug("Trader: {0} @ {1}", entity.GetName(), posn);
138+ //clientAPI.Logger.VerboseDebug("Trader: {0} @ {1}", entity.GetName(), posn);
139139
140140 var traderJoe = entity as EntityTrader;
141141 var message = $"{entity.GetName()} Alive: {traderJoe.Alive}";
--- /dev/null
+++ b/Automap/MapSRC/build.js
@@ -0,0 +1,22 @@
1+#!/usr/local/bin/node
2+
3+// im sorry
4+// cd into MapSRC and run node ./build.js and this will concat and stuff
5+const fs = require('fs');
6+
7+fs.readFile('./src/Automap.html', 'utf8', (err, d) => {
8+ if (err) console.log(err);
9+ let outD = d.replace(/<link rel=\"stylesheet\" href=\"(.*)\">/g, '<style>REP:$1</style>')
10+ .replace(/(<script type=\"text\/javascript\") src=\"(.*)\">/g, '$1>REP:$2')
11+ .replace(/REP:(\w*\.\w*)/g, (match, name, offset, string) => {
12+ return fs.readFileSync('./src/' + name, 'utf8')
13+ .replace(/\/\/.*\n?/g, '');
14+ })
15+ .replace(/[\t\n]/g, '');
16+ fs.writeFile('./dist/automap.html', outD, err => {
17+ if (err) console.log(err);
18+ });
19+ fs.writeFile('../assets/automap/config/automap.html', outD, err => {
20+ if (err) console.log(err);
21+ });
22+});
\ No newline at end of file
--- /dev/null
+++ b/Automap/MapSRC/src/Automap.css
@@ -0,0 +1,38 @@
1+html, body, .map {
2+ width: 100%;
3+ height: 100%;
4+ margin: 0;
5+ overflow: hidden;
6+ outline: 1px dotted black;
7+}
8+
9+.infobox {
10+ width: 15em;
11+ /* height: 15em; */
12+ background-color: rgba(200, 200, 200, 0.5);
13+ left: 0;
14+ top: 0;
15+ font-family: sans-serif;
16+ position: absolute;
17+ z-index: 1;
18+}
19+
20+h1 {
21+ font-size: 22px;
22+ margin: .6em 1em;
23+ text-align: center;
24+}
25+
26+.infoboxTable {
27+ margin: .3em auto;
28+ width: 90%;
29+ outline: 1px solid #333;
30+}
31+
32+.infoboxTable th {
33+ width: 30%;
34+}
35+
36+.infoboxTable td {
37+ text-align: right;
38+}
\ No newline at end of file
--- /dev/null
+++ b/Automap/MapSRC/src/Automap.html
@@ -0,0 +1,22 @@
1+<!DOCTYPE html>
2+<html lang="en" dir="ltr">
3+
4+<head>
5+ <meta charset="utf-8">
6+ <title>Automap</title>
7+ <link rel="stylesheet" href="Automap.css">
8+</head>
9+
10+<body>
11+ <script type="text/javascript" src="ViewFrame.js"></script>
12+ <script type="text/javascript" src="ViewFrameUtils.js"></script>
13+ <div class="infobox">
14+ <h1>Chunk Info</h1>
15+ <table class="infoboxTable">
16+ </table>
17+ </div>
18+ <script type="text/javascript" src="index.js"></script>
19+
20+</body>
21+
22+</html>
\ No newline at end of file
--- /dev/null
+++ b/Automap/MapSRC/src/ViewFrame.js
@@ -0,0 +1,140 @@
1+function ViewFrame() {
2+ // dom stuff
3+ const map = document.createElement('canvas'); // the map we see
4+ map.className = 'map';
5+ map.height = window.innerHeight;
6+ map.width = window.innerWidth;
7+ document.getElementsByTagName('body')[0].append(map);
8+ // this is the map that we actually draw on
9+ this.map = map.getContext('2d', {
10+ alpha: false
11+ });
12+ this.map.imageSmoothingEnabled = false;
13+
14+ // the info box in the corner
15+ this.infobox = document.getElementsByClassName('infoboxTable')[0];
16+ this.infoboxSlots = new Array();
17+
18+ // load the metadata!
19+ this.chunkScript = document.createElement('script');
20+ this.chunkScript.type = 'text/javascript';
21+ this.chunkScript.src = 'Metadata.js';
22+ document.getElementsByTagName('body')[0].append(this.chunkScript);
23+ this.chunkScript.addEventListener('load', () => {
24+ ViewFrame.initInfobox(this.infobox, this.infoboxSlots);
25+ this.x = ViewFrame.chunks.startCoords[0];
26+ this.y = ViewFrame.chunks.startCoords[1];
27+ this.availableChunks = ViewFrame.chunks.chunkMetadata;
28+ this.render();
29+ }, {
30+ once: true
31+ });
32+
33+ // Tracks images that have been loaded and are on the map
34+ this.loadedChunksByName = new Map();
35+ // this is needed because [1, 2] != [1, 2] and thats how we store coords.
36+ this.loadedChunksByCoords = new Map();
37+ this.availableChunks = null; // the chunks in ./Metadata.js
38+ // so that we dont render twice at the same time
39+ this.rendering = false;
40+
41+ this.x = -1;
42+ this.y = -1; // can be fractional
43+ this.zoom = 32; // pixels wide the images are to be
44+ this.updateEdges();
45+}
46+// prototypes, some less... notable? methods are
47+// in ViewFrameUtils.js
48+ViewFrame.prototype.reloadChunkList = function () {
49+ if (this.chunkScript) {
50+ this.chunkScript.remove();
51+ delete this.chunkScript;
52+ }
53+
54+ this.chunkScript = document.createElement('script');
55+ this.chunkScript.type = 'text/javascript';
56+ this.chunkScript.src = 'Metadata.js';
57+ document.getElementsByTagName('body')[0].append(this.chunkScript);
58+
59+ this.chunkScript.addEventListener('load', () => {
60+ this.availableChunks = ViewFrame.chunks.chunkMetadata;
61+ this.render();
62+ });
63+};
64+
65+ViewFrame.prototype.render = function () {
66+ if (!this.availableChunks) return;
67+ if (this.rendering) clearInterval(ViewFrame.intervalRef);
68+ this.rendering = true;
69+ this.updateEdges();
70+ this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
71+ // culling
72+ this.loadedChunksByCoords
73+ .forEach((chunk, coord) => { // check the bounds
74+ if (coord[0] < this.eastChunk &&
75+ coord[0] >= this.westChunk &&
76+ coord[1] <= this.northChunk &&
77+ coord[1] >= this.southChunk) {
78+
79+ this.place(chunk, coord[0], coord[1]);
80+ return;
81+ }
82+ // its out of range!!!
83+ // get 'em boys!!!!!
84+ this.loadedChunksByCoords.delete(coord);
85+ this.loadedChunksByName.delete(coord.join('_'));
86+ chunk.remove();
87+ });
88+
89+ // gathering what we need to load
90+ const neededChunks = new Set();
91+ for (var x = this.westChunk; x < this.eastChunk; x++) {
92+ for (var y = this.southChunk; y < this.northChunk; y++) {
93+ const chunKey = [x, y]; // chunk + key = chunKey :)
94+ const name = chunKey.join('_');
95+ // continue if its not available, or it is loaded
96+ if (!this.availableChunks.has(name) ||
97+ this.loadedChunksByName.has(name)) continue;
98+ neededChunks.add(chunKey);
99+ }
100+ }
101+ // iterating over everything we need to load
102+ const it = neededChunks.values();
103+ ViewFrame.intervalRef = setInterval(() => {
104+ let round = it.next();
105+ if (!round.done) {
106+ // load
107+ const img = new Image(32, 32);
108+ const name = round.value.join('_');
109+
110+ img.src = name + '.png';
111+
112+ decode(img, loadedImage => {
113+ this.place(img, round.value[0], round.value[1]);
114+ });
115+ this.loadedChunksByName.set(name, img);
116+ this.loadedChunksByCoords.set(round.value, img);
117+ } else {
118+ clearInterval(ViewFrame.intervalRef);
119+ this.rendering = false;
120+ }
121+ }, 4);
122+};
123+
124+ViewFrame.prototype.place = function (img, x, y) {
125+ x -= this.x;
126+ y -= this.y;
127+ x *= this.zoom;
128+ y *= this.zoom;
129+ x += this.width / 2;
130+ y += this.height / 2;
131+
132+ this.map.drawImage(img, Math.floor(x), Math.floor(y), this.zoom, this.zoom);
133+};
134+
135+ViewFrame.prototype.updateInfobox = function (chunkName) {
136+ const chunkMeta = this.availableChunks.get(chunkName);
137+ this.infoboxSlots.forEach((l, k) => {
138+ l.innerText = chunkMeta ? chunkMeta[k] : '0';
139+ });
140+};
\ No newline at end of file
--- /dev/null
+++ b/Automap/MapSRC/src/ViewFrameUtils.js
@@ -0,0 +1,62 @@
1+ViewFrame.initInfobox = function (ibox, iboxSlots) {
2+
3+ ViewFrame.chunks
4+ .chunkMetadataNames.forEach((item, i) => {
5+ const slot = document.createElement('tr');
6+ const head = document.createElement('th');
7+ head.innerText = item;
8+ const row = document.createElement('td');
9+ row.innerText = '0';
10+ iboxSlots[i] = row;
11+ slot.append(head, row);
12+ ibox.append(slot);
13+ });
14+};
15+
16+ViewFrame.prototype.updateEdges = function () {
17+ if (this.width != window.innerWidth || this.height != window.innerHeight) {
18+ this.width = window.innerWidth;
19+ this.map.canvas.width = this.width;
20+ this.height = window.innerHeight;
21+ this.map.canvas.height = this.height;
22+ this.map.imageSmoothingEnabled = false;
23+ }
24+ const chunksWide = Math.ceil(this.width / this.zoom);
25+ const chunksHigh = Math.ceil(this.height / this.zoom);
26+
27+ this.east = this.x + chunksWide / 2; // this is fractional and is used to keep track of the edges of the window
28+ this.eastChunk = Math.ceil(this.east); // this is not and is used to track the chunks that need to load
29+ this.west = this.x - chunksWide / 2;
30+ this.westChunk = Math.floor(this.west);
31+ this.north = this.y + chunksHigh / 2;
32+ this.northChunk = Math.ceil(this.north);
33+ this.south = this.y - chunksHigh / 2;
34+ this.southChunk = Math.floor(this.south);
35+};
36+
37+ViewFrame.prototype.moveCenter = function (dx, dy) {
38+ // to pan when we click on the map!
39+ this.x += (dx - this.width / 2) / this.zoom;
40+ this.y += (dy - this.height / 2) / this.zoom;
41+};
42+ViewFrame.prototype.setCenter = function (x, y) {
43+ this.x = x;
44+ this.y = y;
45+};
46+
47+ViewFrame.prototype.clear = function () {
48+ this.loadedChunksByName.clear();
49+ this.loadedChunksByCoords.clear();
50+ if (this.chunkScript) this.chunkScript.remove();
51+ delete this.chunkScript;
52+ delete ViewFrame.chunks;
53+ this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
54+};
55+
56+function decode(img, cb) {
57+ img.decode()
58+ .then(() => {
59+ cb(img);
60+ })
61+ .catch(() => {}); // so images arent added on error
62+}
\ No newline at end of file
--- /dev/null
+++ b/Automap/MapSRC/src/index.js
@@ -0,0 +1,93 @@
1+const vf = new ViewFrame();
2+vf.reloadChunkList();
3+
4+// the event handlers are in iifes so they dont make unneeded globals.
5+// resize, delay re-render to reduce lag.
6+(function () {
7+ var id;
8+ window.addEventListener('resize', () => {
9+ clearTimeout(id);
10+ id = setTimeout(() => {
11+ vf.render();
12+ }, 500);
13+ });
14+}());
15+
16+// panning
17+(function () {
18+ var id;
19+ vf.map.canvas.addEventListener('mousedown', event => {
20+ clearTimeout(id);
21+ vf.moveCenter(event.pageX, event.pageY);
22+ id = setTimeout(() => {
23+ vf.render();
24+ }, 250);
25+ });
26+}());
27+
28+
29+// #### CONTROLS ####
30+// hovering
31+(function () {
32+ var lastX = 0;
33+ var lastY = 0;
34+ vf.map.canvas.addEventListener('mousemove', event => {
35+ // only count if the mouse moved more than a chunk
36+ let x = Math.floor(vf.x +
37+ (event.clientX - vf.width / 2) / vf.zoom);
38+ let y = Math.floor(vf.y +
39+ (event.clientY - vf.height / 2) / vf.zoom);
40+ if (x == lastX && y == lastY) return;
41+ lastX = x;
42+ lastY = y;
43+ vf.updateInfobox(x + '_' + y);
44+ });
45+}());
46+
47+// scroll/zoom
48+(function () {
49+ var id;
50+ vf.map.canvas.addEventListener('wheel', event => {
51+ clearTimeout(id);
52+ vf.zoom += -Math.sign(event.deltaY);
53+ id = setTimeout(() => {
54+ vf.render();
55+ }, 250);
56+ });
57+}());
58+
59+// reload the chunk list every six seconds
60+(function () {
61+ setInterval(() => {
62+ vf.reloadChunkList();
63+ }, 6000);
64+}());
65+//
66+// var i = 500;
67+// setTimeout(() => {
68+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
69+// clientX: 879,
70+// clientY: 926
71+// }));
72+// }, i += 1000);
73+//
74+// setTimeout(() => {
75+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
76+// clientX: 666,
77+// clientY: 924
78+// }));
79+// }, i += 2000);
80+//
81+// setTimeout(() => {
82+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
83+// clientX: 1090,
84+// clientY: 936
85+// }));
86+// }, i += 2000);
87+//
88+// setTimeout(() => {
89+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
90+// clientX: 29,
91+// clientY: 785
92+// }));
93+// }, i += 2000);
\ No newline at end of file
--- a/Automap/Subsystems/AutomapSystem.cs
+++ b/Automap/Subsystems/AutomapSystem.cs
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
33 using System.Collections.Generic;
44 using System.IO;
55 using System.Linq;
6+using System.Reflection;
67 using System.Text;
78 using System.Text.RegularExpressions;
89 using System.Threading;
@@ -29,6 +30,7 @@ namespace Automap
2930 private ICoreClientAPI ClientAPI { get; set; }
3031 private ILogger Logger { get; set; }
3132 private IChunkRenderer ChunkRenderer { get; set; }
33+ private JsonGenerator JsonGenerator { get; set; }
3234
3335 private const string _mapPath = @"Maps";
3436 private const string _chunkPath = @"Chunks";
@@ -43,6 +45,7 @@ namespace Automap
4345 private ColumnsMetadata chunkTopMetadata;
4446 private PointsOfInterest POIs = new PointsOfInterest();
4547 private EntitiesOfInterest EOIs = new EntitiesOfInterest();
48+ private string jsonPreBuilt;
4649
4750 internal Dictionary<int, BlockDesignator> BlockID_Designators { get; private set; }
4851 internal Dictionary<AssetLocation, EntityDesignator> Entity_Designators { get; private set; }
@@ -72,14 +75,13 @@ namespace Automap
7275 configuration = config;
7376
7477
75-
7678 //TODO:Choose which one from GUI
7779 this.ChunkRenderer = new StandardRenderer(clientAPI, logger);
7880
7981 //Listen on bus for commands
8082 ClientAPI.Event.RegisterEventBusListener(CommandListener, 1.0, AutomapSystem.AutomapCommandEventKey);
8183
82- if (configuration.Autostart)
84+ if (configuration.Autostart)
8385 {
8486 CurrentState = CommandType.Run;
8587 Logger.Debug("Autostart is Enabled.");
@@ -93,7 +95,7 @@ namespace Automap
9395 {
9496 path = ClientAPI.GetOrCreateDataPath(_mapPath);
9597 path = ClientAPI.GetOrCreateDataPath(Path.Combine(path, "World_" + ClientAPI.World.Seed));//Add name of World too...'ServerApi.WorldManager.CurrentWorldName'
96-
98+ JsonGenerator = new JsonGenerator(ClientAPI, Logger, path);
9799
98100 string mapFilename = Path.Combine(path, "automap.html");
99101 StreamWriter outputText = new StreamWriter(File.Open(mapFilename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite));
@@ -102,6 +104,8 @@ namespace Automap
102104 outputText.Write(staticMap.ToText());
103105 outputText.Flush();
104106
107+ jsonPreBuilt = JsonGenerator.MakePreBuiltJSON();
108+
105109 Prefill_POI_Designators();
106110 startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X / chunkSize), (ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z / chunkSize));
107111 chunkTopMetadata = new ColumnsMetadata(startChunkColumn);
@@ -173,7 +177,7 @@ namespace Automap
173177 if (!columnCounter.IsEmpty)
174178 {
175179 var tempSet = columnCounter.ToArray().OrderByDescending(kvp => kvp.Value);
176- UpdateEntityMetadata( );
180+ UpdateEntityMetadata();
177181
178182 foreach (var mostActiveCol in tempSet)
179183 {
@@ -188,11 +192,13 @@ namespace Automap
188192 }
189193
190194 ColumnMeta chunkMeta;
191- if (chunkTopMetadata.Contains(mostActiveCol.Key)) {
192- chunkMeta = chunkTopMetadata[mostActiveCol.Key];
195+ if (chunkTopMetadata.Contains(mostActiveCol.Key))
196+ {
197+ chunkMeta = chunkTopMetadata[mostActiveCol.Key];
193198 }
194- else {
195- chunkMeta = CreateColumnMetadata(mostActiveCol, mapChunk);
199+ else
200+ {
201+ chunkMeta = CreateColumnMetadata(mostActiveCol, mapChunk);
196202 }
197203
198204 ProcessChunkBlocks(mostActiveCol.Key, mapChunk, ref chunkMeta);
@@ -225,7 +231,7 @@ namespace Automap
225231 {
226232 //What about chunk updates themselves; a update bitmap isn't kept...
227233 updatedChunksTotal += updatedChunks;
228- GenerateJSONMetadata();
234+ JsonGenerator.GenerateJSONMetadata(chunkTopMetadata, startChunkColumn, POIs, EOIs, RockIdCodes);
229235 updatedChunks = 0;
230236 }
231237
@@ -275,7 +281,7 @@ namespace Automap
275281 }
276282
277283 private void Reload_POI_Designators()
278- {
284+ {
279285 Logger.VerboseDebug("Connecting {0} Configured Block-Designators", configuration.BlockDesignators.Count);
280286 foreach (var designator in configuration.BlockDesignators)
281287 {
@@ -310,223 +316,6 @@ namespace Automap
310316 }
311317
312318
313- /// <summary>
314- /// Generates the JSON Metadata. (in Map object format )
315- /// </summary>
316- private void GenerateJSONMetadata()
317- {
318- string jsonFilename = Path.Combine(path, "Metadata.js");
319-
320- StreamWriter stream = new StreamWriter(jsonFilename, false, Encoding.UTF8);
321-
322- using (stream) {
323- JsonTextWriter jsonWriter = new JsonTextWriter(stream);
324-
325- jsonWriter.Formatting = Formatting.None;
326- jsonWriter.StringEscapeHandling = StringEscapeHandling.EscapeHtml;
327- jsonWriter.Indentation = 0;
328- //jsonWriter.AutoCompleteOnClose = true;
329- jsonWriter.QuoteChar = '\'';
330- jsonWriter.DateFormatHandling = DateFormatHandling.IsoDateFormat;
331- jsonWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
332-
333- using (jsonWriter)
334- {
335- jsonWriter.WriteRaw("ViewFrame.chunks={};\n");
336- jsonWriter.WriteRaw("ViewFrame.chunks.worldSeedNum=" );
337- jsonWriter.WriteValue(ClientAPI.World.Seed);
338- jsonWriter.WriteRaw(";\n");
339-
340- jsonWriter.WriteRaw("ViewFrame.chunks.genTime=");
341- jsonWriter.WriteValue(DateTimeOffset.UtcNow);
342- jsonWriter.WriteRaw(";\n");
343-
344- jsonWriter.WriteRaw("ViewFrame.chunks.startCoords=");
345- jsonWriter.WriteStartArray( );
346- jsonWriter.WriteValue(startChunkColumn.X);
347- jsonWriter.WriteValue(startChunkColumn.Y);
348- jsonWriter.WriteEndArray( );
349- jsonWriter.WriteRaw(";\n");
350-
351- jsonWriter.WriteRaw("ViewFrame.chunks.chunkSize=");
352- jsonWriter.WriteValue(chunkSize);
353- jsonWriter.WriteRaw(";\n");
354-
355- jsonWriter.WriteRaw("ViewFrame.chunks.northMostChunk=");
356- jsonWriter.WriteValue(chunkTopMetadata.North_mostChunk);
357- jsonWriter.WriteRaw(";\n");
358-
359- jsonWriter.WriteRaw("ViewFrame.chunks.southMostChunk=");
360- jsonWriter.WriteValue(chunkTopMetadata.South_mostChunk);
361- jsonWriter.WriteRaw(";\n");
362-
363- jsonWriter.WriteRaw("ViewFrame.chunks.westMostChunk=");
364- jsonWriter.WriteValue(chunkTopMetadata.West_mostChunk);
365- jsonWriter.WriteRaw(";\n");
366-
367- jsonWriter.WriteRaw("ViewFrame.chunks.eastMostChunk=");
368- jsonWriter.WriteValue(chunkTopMetadata.East_mostChunk);
369- jsonWriter.WriteRaw(";\n");
370-
371-
372- //MAP object format - [key, value]: key is "x_y"
373- jsonWriter.WriteRaw("ViewFrame.chunks.chunkMetadata=");
374- jsonWriter.WriteStartConstructor("Map");
375- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
376-
377-
378- foreach (var shard in chunkTopMetadata)
379- {
380- jsonWriter.WriteStartArray( );//Start tuple
381- jsonWriter.WriteValue($"{shard.Location.X}_{shard.Location.Y}");//Key of Tuple
382-
383- jsonWriter.WriteStartObject( );
384- jsonWriter.WritePropertyName("prettyCoord");
385- jsonWriter.WriteValue( shard.Location.PrettyCoords(ClientAPI));
386-
387- jsonWriter.WritePropertyName("chunkAge");
388- jsonWriter.WriteValue(shard.ChunkAge);
389-
390- jsonWriter.WritePropertyName("temp");
391- jsonWriter.WriteValue(shard.Temperature);
392-
393- jsonWriter.WritePropertyName("YMax");
394- jsonWriter.WriteValue(shard.YMax);
395-
396- jsonWriter.WritePropertyName("fert");
397- jsonWriter.WriteValue(shard.Fertility);
398-
399- jsonWriter.WritePropertyName("forestDens");
400- jsonWriter.WriteValue( shard.ForestDensity);
401-
402- jsonWriter.WritePropertyName("rain");
403- jsonWriter.WriteValue( shard.Rainfall);
404-
405- jsonWriter.WritePropertyName("shrubDens");
406- jsonWriter.WriteValue( shard.ShrubDensity);
407-
408- jsonWriter.WritePropertyName("airBlocks");
409- jsonWriter.WriteValue( shard.AirBlocks);
410-
411- jsonWriter.WritePropertyName("nonAirBlocks");
412- jsonWriter.WriteValue( shard.NonAirBlocks);
413-
414- //TODO: Heightmap ?
415- //Start rockMap ; FOR a Ratio....on tooltip GUI
416- jsonWriter.WritePropertyName("rockRatio");
417- jsonWriter.WriteStartConstructor("Map");
418- jsonWriter.WriteStartArray( );
419- foreach (var rockEntry in shard.RockRatio) {
420- var rockBlock = ClientAPI.World.GetBlock(rockEntry.Key);
421- jsonWriter.WriteStartArray( );
422- jsonWriter.WriteValue(rockBlock.Code.Path);
423- jsonWriter.WriteValue(rockEntry.Value);//Total per chunk-column
424- jsonWriter.WriteEndArray( );
425- }
426- jsonWriter.WriteEndArray( );
427- jsonWriter.WriteEndConstructor( );//end rock-map
428-
429- jsonWriter.WriteEndObject( );//end Map value: {Object}
430- jsonWriter.WriteEndArray( );//end Tuple
431- }
432-
433- jsonWriter.WriteEndArray( );//Enclose tuples of chunkMetadata
434- jsonWriter.WriteEndConstructor( );//Close constructor of Map (chunkMetadata)
435- jsonWriter.WriteRaw(";\n");
436-
437- jsonWriter.WriteRaw("ViewFrame.chunks.pointsOfInterest=");
438- jsonWriter.WriteStartConstructor("Map");
439- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
440-
441- foreach (var poi in POIs)
442- {
443- jsonWriter.WriteStartArray( );
444- jsonWriter.WriteValue($"{poi.Location.X}_{poi.Location.Z}");
445-
446- jsonWriter.WriteStartObject();
447- jsonWriter.WritePropertyName("Name");
448- jsonWriter.WriteValue(poi.Name);
449-
450- jsonWriter.WritePropertyName("prettyCoord");
451- jsonWriter.WriteValue(poi.Location.PrettyCoords(ClientAPI) );
452-
453- jsonWriter.WritePropertyName("notes");
454- jsonWriter.WriteValue(poi.Notes);//Encoded to HTML Entities
455-
456- jsonWriter.WritePropertyName("time");
457- jsonWriter.WriteValue(poi.Timestamp);
458-
459- jsonWriter.WritePropertyName("chunkPos");
460- jsonWriter.WriteValue($"{(poi.Location.X / chunkSize)}_{(poi.Location.Z / chunkSize)}");
461-
462- jsonWriter.WriteEndObject( );
463- jsonWriter.WriteEndArray( );
464- }
465-
466- foreach (var poi in EOIs)
467- {
468- jsonWriter.WriteStartArray( );
469- jsonWriter.WriteValue($"{poi.Location.X}_{poi.Location.Z}");
470-
471- jsonWriter.WriteStartObject( );
472- jsonWriter.WritePropertyName("Name");
473- jsonWriter.WriteValue(poi.Name);
474-
475- jsonWriter.WritePropertyName("prettyCoord");
476- jsonWriter.WriteValue(poi.Location.PrettyCoords(ClientAPI));
477-
478- jsonWriter.WritePropertyName("notes");
479- jsonWriter.WriteValue(poi.Notes);//Encoded to HTML Entities
480-
481- jsonWriter.WritePropertyName("time");
482- jsonWriter.WriteValue(poi.Timestamp);
483-
484- jsonWriter.WritePropertyName("chunkPos");
485- jsonWriter.WriteValue($"{(poi.Location.X / chunkSize)}_{(poi.Location.Z / chunkSize)}");
486-
487- jsonWriter.WriteEndObject( );
488- jsonWriter.WriteEndArray( );
489- }
490-
491- jsonWriter.WriteEndArray( );
492- jsonWriter.WriteEndConstructor( );
493- jsonWriter.WriteRaw(";\n");
494-
495- jsonWriter.WriteWhitespace("\n");
496- jsonWriter.WriteComment("============= BlockID's for Rockmap / Rock-ratios ===============");
497- jsonWriter.WriteWhitespace("\n");
498-
499- jsonWriter.WriteRaw("ViewFrame.chunks.rock_Lookup =");
500- jsonWriter.WriteStartConstructor("Map");
501- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
502-
503- foreach (var entry in RockIdCodes) {
504- var block = ClientAPI.World.GetBlock(entry.Key);
505-
506- jsonWriter.WriteStartArray( );
507- jsonWriter.WriteValue(block.Code.Path);
508-
509- jsonWriter.WriteStartObject( );
510- jsonWriter.WritePropertyName("assetCode");
511- jsonWriter.WriteValue(entry.Value);
512-
513- jsonWriter.WritePropertyName("name");
514- jsonWriter.WriteValue(Lang.GetUnformatted(block.Code.Path));
515- //Color?
516-
517- jsonWriter.WriteEndObject( );
518- jsonWriter.WriteEndArray( );
519- }
520- jsonWriter.WriteEndArray( );
521- jsonWriter.WriteEndConstructor();
522-
523- jsonWriter.WriteRaw(";\n");
524-
525- jsonWriter.Flush();
526- }
527- }
528-
529- }
530319
531320 /// <summary>
532321 /// Store Points/Entity of Interest
@@ -550,7 +339,7 @@ namespace Automap
550339 }
551340 }
552341
553- //Create Easy to Parse CSV file for tool/human use....
342+ //Create Easy to Parse TSV file for tool/human use....
554343 string pointsTsvPath = Path.Combine(path, pointsTsvFileName);
555344
556345 using (var tsvWriter = new StreamWriter(pointsTsvPath, false, Encoding.UTF8))
@@ -578,7 +367,7 @@ namespace Automap
578367
579368 private ColumnMeta CreateColumnMetadata(KeyValuePair<Vec2i, uint> mostActiveCol, IMapChunk mapChunk)
580369 {
581- ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy(), ( byte )chunkSize);
370+ ColumnMeta data = new ColumnMeta(mostActiveCol.Key.Copy(), (byte) chunkSize);
582371 BlockPos equivBP = new BlockPos(mostActiveCol.Key.X * chunkSize,
583372 mapChunk.YMax,
584373 mostActiveCol.Key.Y * chunkSize);
@@ -630,12 +419,12 @@ namespace Automap
630419 }
631420
632421 }
633- catch (PngjException someEx)
422+ catch (PngjException someEx)
634423 {
635- Logger.Error("PNG Corruption in file '{0}' - Reason: {1}", shardFile.Name, someEx);
424+ Logger.Error("PNG Corruption file '{0}' - Reason: {1}", shardFile.Name, someEx);
636425 continue;
637426 }
638- }
427+ }
639428
640429 }
641430 }
@@ -860,8 +649,10 @@ namespace Automap
860649 }
861650
862651
652+
653+
863654 #endregion
864655
865656 }
866657
867-}
\ No newline at end of file
658+}
--- /dev/null
+++ b/Automap/Subsystems/JsonGenerator.cs
@@ -0,0 +1,318 @@
1+using System;
2+using System.Collections.Generic;
3+using System.IO;
4+using System.Linq;
5+using System.Reflection;
6+using System.Text;
7+using System.Text.RegularExpressions;
8+
9+using Newtonsoft.Json;
10+
11+using Vintagestory.API.Client;
12+using Vintagestory.API.Common;
13+using Vintagestory.API.Config;
14+using Vintagestory.API.Datastructures;
15+using Vintagestory.API.MathTools;
16+using Vintagestory.Common;
17+
18+
19+
20+namespace Automap
21+{
22+ public class JsonGenerator
23+ {
24+ private ICoreClientAPI ClientAPI { get; set; }
25+ private ILogger Logger { get; set; }
26+ private string path { get; set; }
27+ private readonly int chunkSize;
28+
29+
30+ public JsonGenerator(ICoreClientAPI _ClientAPI, ILogger _Logger, string _path )
31+ {
32+ this.ClientAPI = _ClientAPI;
33+ this.Logger = _Logger;
34+ this.path = _path;
35+ this.chunkSize = ClientAPI.World.BlockAccessor.ChunkSize;
36+ }
37+
38+
39+ /// <summary>
40+ /// Generates the JSON Metadata. (in Map object format )
41+ /// </summary>
42+ public void GenerateJSONMetadata(ColumnsMetadata chunkTopMetadata, Vec2i startChunkColumn, PointsOfInterest POIs, EntitiesOfInterest EOIs, Dictionary<int, string> RockIdCodes )
43+ {
44+ string jsonFilename = Path.Combine(path, "Metadata.js");
45+
46+ StreamWriter stream = new StreamWriter(jsonFilename, false, Encoding.UTF8);
47+
48+ using (stream) {
49+ JsonTextWriter jsonWriter = new JsonTextWriter(stream);
50+
51+ jsonWriter.Formatting = Formatting.None;
52+ jsonWriter.StringEscapeHandling = StringEscapeHandling.EscapeHtml;
53+ jsonWriter.Indentation = 0;
54+ //jsonWriter.AutoCompleteOnClose = true;
55+ jsonWriter.QuoteChar = '\'';
56+ jsonWriter.DateFormatHandling = DateFormatHandling.IsoDateFormat;
57+ jsonWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
58+
59+ using (jsonWriter) {
60+ jsonWriter.WriteRaw("ViewFrame.chunks={};\n");
61+ jsonWriter.WriteRaw("ViewFrame.chunks.worldSeedNum=");
62+ jsonWriter.WriteValue(ClientAPI.World.Seed);
63+ jsonWriter.WriteRaw(";\n");
64+
65+ jsonWriter.WriteRaw("ViewFrame.chunks.genTime=");
66+ jsonWriter.WriteValue(DateTimeOffset.UtcNow);
67+ jsonWriter.WriteRaw(";\n");
68+
69+ jsonWriter.WriteRaw("ViewFrame.chunks.startCoords=");
70+ jsonWriter.WriteStartArray( );
71+ jsonWriter.WriteValue(startChunkColumn.X);
72+ jsonWriter.WriteValue(startChunkColumn.Y);
73+ jsonWriter.WriteEndArray( );
74+ jsonWriter.WriteRaw(";\n");
75+
76+ jsonWriter.WriteRaw("ViewFrame.chunks.chunkSize=");
77+ jsonWriter.WriteValue(chunkSize);
78+ jsonWriter.WriteRaw(";\n");
79+
80+ jsonWriter.WriteRaw("ViewFrame.chunks.northMostChunk=");
81+ jsonWriter.WriteValue(chunkTopMetadata.North_mostChunk);
82+ jsonWriter.WriteRaw(";\n");
83+
84+ jsonWriter.WriteRaw("ViewFrame.chunks.southMostChunk=");
85+ jsonWriter.WriteValue(chunkTopMetadata.South_mostChunk);
86+ jsonWriter.WriteRaw(";\n");
87+
88+ jsonWriter.WriteRaw("ViewFrame.chunks.westMostChunk=");
89+ jsonWriter.WriteValue(chunkTopMetadata.West_mostChunk);
90+ jsonWriter.WriteRaw(";\n");
91+
92+ jsonWriter.WriteRaw("ViewFrame.chunks.eastMostChunk=");
93+ jsonWriter.WriteValue(chunkTopMetadata.East_mostChunk);
94+ jsonWriter.WriteRaw(";\n");
95+
96+
97+ //MAP object format - [key, value]: key is "x_y"
98+ jsonWriter.WriteRaw("ViewFrame.chunks.chunkMetadata=");
99+ jsonWriter.WriteStartConstructor("Map");
100+ jsonWriter.WriteStartArray( );//An array of... 2-component arrays
101+
102+
103+ foreach (var shard in chunkTopMetadata) {
104+ jsonWriter.WriteStartArray( );//Start tuple
105+ jsonWriter.WriteValue($"{shard.Location.X}_{shard.Location.Y}");//Key of Tuple
106+
107+ jsonWriter.WriteStartObject( );
108+ jsonWriter.WritePropertyName("prettyCoord");
109+ jsonWriter.WriteValue(shard.Location.PrettyCoords(ClientAPI));
110+
111+ jsonWriter.WritePropertyName("chunkAge");
112+ jsonWriter.WriteValue(shard.ChunkAge);
113+
114+ jsonWriter.WritePropertyName("temp");
115+ jsonWriter.WriteValue(shard.Temperature);
116+
117+ jsonWriter.WritePropertyName("YMax");
118+ jsonWriter.WriteValue(shard.YMax);
119+
120+ jsonWriter.WritePropertyName("fert");
121+ jsonWriter.WriteValue(shard.Fertility);
122+
123+ jsonWriter.WritePropertyName("forestDens");
124+ jsonWriter.WriteValue(shard.ForestDensity);
125+
126+ jsonWriter.WritePropertyName("rain");
127+ jsonWriter.WriteValue(shard.Rainfall);
128+
129+ jsonWriter.WritePropertyName("shrubDens");
130+ jsonWriter.WriteValue(shard.ShrubDensity);
131+
132+ jsonWriter.WritePropertyName("airBlocks");
133+ jsonWriter.WriteValue(shard.AirBlocks);
134+
135+ jsonWriter.WritePropertyName("nonAirBlocks");
136+ jsonWriter.WriteValue(shard.NonAirBlocks);
137+
138+ //TODO: Heightmap ?
139+ //Start rockMap ; FOR a Ratio....on tooltip GUI
140+ jsonWriter.WritePropertyName("rockRatio");
141+ jsonWriter.WriteStartConstructor("Map");
142+ jsonWriter.WriteStartArray( );
143+ foreach (var rockEntry in shard.RockRatio) {
144+ var rockBlock = ClientAPI.World.GetBlock(rockEntry.Key);
145+ jsonWriter.WriteStartArray( );
146+ jsonWriter.WriteValue(rockBlock.Code.Path);
147+ jsonWriter.WriteValue(rockEntry.Value);//Total per chunk-column
148+ jsonWriter.WriteEndArray( );
149+ }
150+ jsonWriter.WriteEndArray( );
151+ jsonWriter.WriteEndConstructor( );//end rock-map
152+
153+ jsonWriter.WriteEndObject( );//end Map value: {Object}
154+ jsonWriter.WriteEndArray( );//end Tuple
155+ }
156+
157+ jsonWriter.WriteEndArray( );//Enclose tuples of chunkMetadata
158+ jsonWriter.WriteEndConstructor( );//Close constructor of Map (chunkMetadata)
159+ jsonWriter.WriteRaw(";\n");
160+
161+ jsonWriter.WriteRaw("ViewFrame.chunks.pointsOfInterest=");
162+ jsonWriter.WriteStartConstructor("Map");
163+ jsonWriter.WriteStartArray( );//An array of... 2-component arrays
164+
165+ foreach (var poi in POIs) {
166+ EmitJsonMap(poi, jsonWriter);
167+ }
168+
169+ foreach (var poi in EOIs) {
170+ EmitJsonMap(poi, jsonWriter);
171+ }
172+
173+ jsonWriter.WriteEndArray( );
174+ jsonWriter.WriteEndConstructor( );
175+ jsonWriter.WriteRaw(";\n");
176+
177+ jsonWriter.WriteWhitespace("\n");
178+ jsonWriter.WriteComment("============= BlockID's for Rockmap / Rock-ratios ===============");
179+ jsonWriter.WriteWhitespace("\n");
180+
181+ jsonWriter.WriteRaw("ViewFrame.chunks.rock_Lookup =");
182+ jsonWriter.WriteStartConstructor("Map");
183+ jsonWriter.WriteStartArray( );//An array of... 2-component arrays
184+
185+ foreach (var entry in RockIdCodes) {
186+ var block = ClientAPI.World.GetBlock(entry.Key);
187+ // stream.Write("{0},", Lang.GetUnformatted(block.Code.Path));
188+ jsonWriter.WriteStartArray( );
189+ jsonWriter.WriteValue(block.Code.Path);
190+
191+ jsonWriter.WriteStartObject( );
192+ jsonWriter.WritePropertyName("assetCode");
193+ jsonWriter.WriteValue(entry.Value);
194+
195+ jsonWriter.WritePropertyName("name");
196+ jsonWriter.WriteValue(Lang.GetUnformatted(block.Code.Path));
197+ //}
198+
199+ jsonWriter.WriteEndObject( );
200+ jsonWriter.WriteEndArray( );
201+ }
202+ jsonWriter.WriteEndArray( );
203+ jsonWriter.WriteEndConstructor( );
204+ //stream.Write("]);\n");
205+ jsonWriter.WriteRaw(";\n");
206+
207+ jsonWriter.Flush( );
208+ }
209+ }
210+
211+ }
212+
213+ public void EmitJsonMap(PointOfInterest @this, JsonTextWriter jsonWriter)
214+ {
215+ jsonWriter.WriteStartArray( );
216+ jsonWriter.WriteValue($"{@this.Location.X}_{@this.Location.Z}");
217+
218+ jsonWriter.WriteStartArray( );
219+ //jsonWriter.WriteValue(@this.Name);
220+
221+ jsonWriter.WriteValue(@this.Location.X);
222+ jsonWriter.WriteValue(@this.Location.Z); //Y is HEIGHT from Mantle... Z is Right from edge of world
223+
224+ jsonWriter.WriteValue(@this.Location.PrettyCoords(ClientAPI));
225+
226+ jsonWriter.WriteValue(@this.Notes);//put more escaping in Java-script if needed
227+
228+ jsonWriter.WriteValue(@this.Timestamp);
229+
230+ jsonWriter.WriteEndArray( );
231+ jsonWriter.WriteEndArray( );
232+ }
233+
234+ public void EmitJsonMap(EntityOfInterest @this, JsonTextWriter jsonWriter)
235+ {
236+ jsonWriter.WriteStartArray( );
237+ jsonWriter.WriteValue($"{@this.Location.X}_{@this.Location.Z}");
238+
239+
240+ jsonWriter.WriteStartArray( );
241+ //jsonWriter.WriteValue(@this.Name);
242+
243+ jsonWriter.WriteValue(@this.Location.X);
244+ jsonWriter.WriteValue(@this.Location.Z); //Y is HEIGHT from Mantle... Z is Right from edge of world
245+
246+ jsonWriter.WriteValue(@this.Location.PrettyCoords(ClientAPI));
247+
248+ jsonWriter.WriteValue(@this.Notes);//put more escaping in Java-script if needed
249+
250+ jsonWriter.WriteValue(@this.Timestamp);
251+
252+ jsonWriter.WriteValue(@this.EntityId);
253+
254+ jsonWriter.WriteEndArray( );
255+ jsonWriter.WriteEndArray( );
256+ }
257+
258+ /// <summary>
259+ /// Dynamically reflect Points-of-Something fields for metadata descriptors
260+ /// </summary>
261+ /// <returns>Json-array names of fields for use in map display.</returns>
262+ public string MakePreBuiltJSON( )
263+ {
264+ var builder = new StringBuilder(512);
265+ builder.Append("ViewFrame.chunks={};\n");
266+ builder.AppendFormat("ViewFrame.chunks.worldSeedNum='{0}';",
267+ ClientAPI.World.Seed
268+ );
269+ builder.AppendFormat("ViewFrame.chunks.chunkSize={0};",
270+ chunkSize
271+ );
272+
273+ builder.Append("ViewFrame.chunks.chunkMetadataNames=[");
274+ var fields = typeof(ColumnMeta).GetFields( );
275+ var attsToSort = new List<DisplayNameAttribute>( );
276+ // this is so gross
277+ foreach (var f in fields) {
278+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
279+ if (att != null) {
280+ attsToSort.Add(( DisplayNameAttribute )att);
281+ }
282+
283+ }
284+ foreach (var att in attsToSort.OrderBy(a => a.order))
285+ builder.AppendFormat("'{0}',", att.name);
286+ builder.Append("];\n");
287+
288+ builder.Append("ViewFrame.chunks.pointsOfInterestNames=[");
289+ fields = typeof(PointOfInterest).GetFields( );
290+ attsToSort = new List<DisplayNameAttribute>( );
291+
292+ foreach (var f in fields) {
293+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
294+ if (att != null)
295+ attsToSort.Add(( DisplayNameAttribute )att);
296+ }
297+ foreach (var att in attsToSort.OrderBy(a => a.order))
298+ builder.AppendFormat("'{0}',", att.name);
299+ builder.Append("];\n");
300+
301+ builder.Append("ViewFrame.chunks.entityOfInterestNames=[");
302+ fields = typeof(EntityOfInterest).GetFields( );
303+ attsToSort = new List<DisplayNameAttribute>( );
304+
305+ foreach (var f in fields) {
306+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
307+ if (att != null)
308+ attsToSort.Add(( DisplayNameAttribute )att);
309+ }
310+ foreach (var att in attsToSort.OrderBy(a => a.order))
311+ builder.AppendFormat("'{0}',", att.name);
312+ builder.Append("];\n");
313+
314+ return builder.ToString( );
315+ }
316+ }
317+}
318+
Show on old repository browser