<Compile Include="Data\CommandData.cs" />
<Compile Include="Data\CommandType.cs" />
<Compile Include="Data\PersistedConfiguration.cs" />
+ <Compile Include="Data\DisplayNameAttribute.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="VS_libs\" />
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Vintagestory.API.Common;
using ProtoBuf;
-
+using System.IO;
+using System.Collections.ObjectModel;
+using System.Text;
+using Vintagestory.API.Client;
namespace Automap
{
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<int, uint> 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 ushort[,] HeightMap;//Needs to be 'flattened' for Protocol-Buffer serialization
[ProtoMember(13)]
- private ushort[ ] _flattened_HeightMap;
+ private ushort[] _flattened_HeightMap;
public ColumnMeta(Vec2i loc, byte chunkSize = 32)
this.YMax = mapChunk.YMax;
}
-
+ public void Write(StreamWriter stream, ICoreClientAPI ClientApi)
+ {
+ // this is gross i hate this
+ stream.Write("['{0}_{1}',[",
+ Location.X,
+ Location.Y
+ );
+ stream.Write("'{0}',", Location.PrettyCoords(ClientApi));
+ stream.Write("'{0}',", ChunkAge);
+ stream.Write("'{0}',", Temperature.ToString("F3"));
+ stream.Write("'{0}',", YMax);
+ stream.Write("'{0}',", Fertility.ToString("F3"));
+ stream.Write("'{0}',", ForestDensity.ToString("F3"));
+ stream.Write("'{0}',", Rainfall.ToString("F3"));
+ stream.Write("'{0}',", ShrubDensity.ToString("F3"));
+ stream.Write("'{0}',", AirBlocks);
+ stream.Write("'{0}',", NonAirBlocks);
+ stream.Write("]]");
+ }
[ProtoBeforeSerialization]
- private void PrepareData( )
+ private void PrepareData()
{
- if (HeightMap != null) {
- _flattened_HeightMap = new ushort[ChunkSize * ChunkSize];
- int flatIndex = 0;
+ 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++;
+ }
+ }
- 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( )
+ private void PostProcess()
{
- if (this.HeightMap == null) this.HeightMap = new ushort[ChunkSize, ChunkSize];
-
- if (_flattened_HeightMap != null) {
- int col, row;
+ if (this.HeightMap == null) this.HeightMap = new ushort[ChunkSize, ChunkSize];
- BitVector32 bitMasker = 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++) {
- bitMasker = new BitVector32(data: ( int )rowcol);
- row = bitMasker[rowSection];
- col = bitMasker[colSection];
- HeightMap[col, row] = _flattened_HeightMap[rowcol];
- }
+ 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];
+ }
- }
+ }
}
}
}
-}
-
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Reflection;
+
+namespace Automap
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class DisplayNameAttribute : Attribute
+ {
+ public string name;
+ public byte order;
+ public DisplayNameAttribute(byte order, string name)
+ {
+ this.order = order;
+ this.name = name;
+ }
+ }
+}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-
+using System.IO;
using System.Linq;
-
using Vintagestory.API.Common.Entities;
using Vintagestory.API.MathTools;
+using Vintagestory.API.Client;
namespace Automap
{
/// </summary>
public struct EntityOfInterest
{
+ [DisplayName(1, "Notes")]
public string Notes;
+ [DisplayName(0, "Loc.")]
public BlockPos Location;
+ [DisplayName(2, "Time")]
public DateTimeOffset Timestamp;
+ [DisplayName(3, "ID")]
public long EntityId;
+ public void Write(StreamWriter stream, ICoreClientAPI ClientApi)
+ {
+ // this is gross i hate this
+ stream.Write("['{0}_{1}',[",
+ Location.X,
+ Location.Y
+ );
+ stream.Write("'{0}',", Location.PrettyCoords(ClientApi));
+ stream.Write("'{0}',", System.Web.HttpUtility.HtmlEncode(Notes));
+ stream.Write("'{0}',", Timestamp);
+ stream.Write("'{0}',", EntityId);
+ stream.Write("]]");
+ }
}
/// <summary>
using System;
using System.Collections.ObjectModel;
-
+using System.IO;
+using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.MathTools;
/// </summary>
public struct PointOfInterest
{
+ [DisplayName(1, "Notes")]
public string Notes;
+ [DisplayName(0, "Loc.")]
public BlockPos Location;
+ [DisplayName(2, "Time")]
public DateTimeOffset Timestamp;
+ public void Write(StreamWriter stream, ICoreClientAPI ClientApi)
+ {
+ // this is gross i hate this
+ stream.Write("['{0}_{1}',[",
+ Location.X,
+ Location.Y
+ );
+ stream.Write("'{0}',", Location.PrettyCoords(ClientApi));
+ stream.Write("'{0}',", System.Web.HttpUtility.HtmlEncode(Notes).Replace("\n", " ").Replace("\\","\\\\"));
+ stream.Write("'{0}',", Timestamp);
+ stream.Write("]]");
+ }
}
public class PointsOfInterest : KeyedCollection<BlockPos, PointOfInterest>
--- /dev/null
+#!/usr/local/bin/node
+
+// im sorry
+// cd into MapSRC and run node ./build.js and this will concat and stuff
+const fs = require('fs');
+
+fs.readFile('./src/Automap.html', 'utf8', (err, d) => {
+ if (err) console.log(err);
+ let outD = d.replace(/<link rel=\"stylesheet\" href=\"(.*)\">/g, '<style>REP:$1</style>')
+ .replace(/(<script type=\"text\/javascript\") src=\"(.*)\">/g, '$1>REP:$2')
+ .replace(/REP:(\w*\.\w*)/g, (match, name, offset, string) => {
+ return fs.readFileSync('./src/' + name, 'utf8')
+ .replace(/\/\/.*\n?/g, '');
+ })
+ .replace(/[\t\n]/g, '');
+ fs.writeFile('./dist/automap.html', outD, err => {
+ if (err) console.log(err);
+ });
+ fs.writeFile('../assets/automap/config/automap.html', outD, err => {
+ if (err) console.log(err);
+ });
+});
\ No newline at end of file
--- /dev/null
+html, body, .map {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ overflow: hidden;
+ outline: 1px dotted black;
+}
+
+.infobox {
+ width: 15em;
+ /* height: 15em; */
+ background-color: rgba(200, 200, 200, 0.5);
+ left: 0;
+ top: 0;
+ font-family: sans-serif;
+ position: absolute;
+ z-index: 1;
+}
+
+h1 {
+ font-size: 22px;
+ margin: .6em 1em;
+ text-align: center;
+}
+
+.infoboxTable {
+ margin: .3em auto;
+ width: 90%;
+ outline: 1px solid #333;
+}
+
+.infoboxTable th {
+ width: 30%;
+}
+
+.infoboxTable td {
+ text-align: right;
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+
+<head>
+ <meta charset="utf-8">
+ <title>Automap</title>
+ <link rel="stylesheet" href="Automap.css">
+</head>
+
+<body>
+ <script type="text/javascript" src="ViewFrame.js"></script>
+ <script type="text/javascript" src="ViewFrameUtils.js"></script>
+ <div class="infobox">
+ <h1>Chunk Info</h1>
+ <table class="infoboxTable">
+ </table>
+ </div>
+ <script type="text/javascript" src="index.js"></script>
+
+</body>
+
+</html>
\ No newline at end of file
--- /dev/null
+function ViewFrame() {
+ // dom stuff
+ const map = document.createElement('canvas'); // the map we see
+ map.className = 'map';
+ map.height = window.innerHeight;
+ map.width = window.innerWidth;
+ document.getElementsByTagName('body')[0].append(map);
+ // this is the map that we actually draw on
+ this.map = map.getContext('2d', {
+ alpha: false
+ });
+ this.map.imageSmoothingEnabled = false;
+
+ // the info box in the corner
+ this.infobox = document.getElementsByClassName('infoboxTable')[0];
+ this.infoboxSlots = new Array();
+
+ // load the metadata!
+ this.chunkScript = document.createElement('script');
+ this.chunkScript.type = 'text/javascript';
+ this.chunkScript.src = 'Metadata.js';
+ document.getElementsByTagName('body')[0].append(this.chunkScript);
+ this.chunkScript.addEventListener('load', () => {
+ ViewFrame.initInfobox(this.infobox, this.infoboxSlots);
+ this.x = ViewFrame.chunks.startCoords[0];
+ this.y = ViewFrame.chunks.startCoords[1];
+ this.availableChunks = ViewFrame.chunks.chunkMetadata;
+ this.render();
+ }, {
+ once: true
+ });
+
+ // Tracks images that have been loaded and are on the map
+ this.loadedChunksByName = new Map();
+ // this is needed because [1, 2] != [1, 2] and thats how we store coords.
+ this.loadedChunksByCoords = new Map();
+ this.availableChunks = null; // the chunks in ./Metadata.js
+ // so that we dont render twice at the same time
+ this.rendering = false;
+
+ this.x = -1;
+ this.y = -1; // can be fractional
+ this.zoom = 32; // pixels wide the images are to be
+ this.updateEdges();
+}
+// prototypes, some less... notable? methods are
+// in ViewFrameUtils.js
+ViewFrame.prototype.reloadChunkList = function () {
+ if (this.chunkScript) {
+ this.chunkScript.remove();
+ delete this.chunkScript;
+ }
+
+ this.chunkScript = document.createElement('script');
+ this.chunkScript.type = 'text/javascript';
+ this.chunkScript.src = 'Metadata.js';
+ document.getElementsByTagName('body')[0].append(this.chunkScript);
+
+ this.chunkScript.addEventListener('load', () => {
+ this.availableChunks = ViewFrame.chunks.chunkMetadata;
+ this.render();
+ });
+};
+
+ViewFrame.prototype.render = function () {
+ if (!this.availableChunks) return;
+ if (this.rendering) clearInterval(ViewFrame.intervalRef);
+ this.rendering = true;
+ this.updateEdges();
+ this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
+ // culling
+ this.loadedChunksByCoords
+ .forEach((chunk, coord) => { // check the bounds
+ if (coord[0] < this.eastChunk &&
+ coord[0] >= this.westChunk &&
+ coord[1] <= this.northChunk &&
+ coord[1] >= this.southChunk) {
+
+ this.place(chunk, coord[0], coord[1]);
+ return;
+ }
+ // its out of range!!!
+ // get 'em boys!!!!!
+ this.loadedChunksByCoords.delete(coord);
+ this.loadedChunksByName.delete(coord.join('_'));
+ chunk.remove();
+ });
+
+ // gathering what we need to load
+ const neededChunks = new Set();
+ for (var x = this.westChunk; x < this.eastChunk; x++) {
+ for (var y = this.southChunk; y < this.northChunk; y++) {
+ const chunKey = [x, y]; // chunk + key = chunKey :)
+ const name = chunKey.join('_');
+ // continue if its not available, or it is loaded
+ if (!this.availableChunks.has(name) ||
+ this.loadedChunksByName.has(name)) continue;
+ neededChunks.add(chunKey);
+ }
+ }
+ // iterating over everything we need to load
+ const it = neededChunks.values();
+ ViewFrame.intervalRef = setInterval(() => {
+ let round = it.next();
+ if (!round.done) {
+ // load
+ const img = new Image(32, 32);
+ const name = round.value.join('_');
+
+ img.src = name + '.png';
+
+ decode(img, loadedImage => {
+ this.place(img, round.value[0], round.value[1]);
+ });
+ this.loadedChunksByName.set(name, img);
+ this.loadedChunksByCoords.set(round.value, img);
+ } else {
+ clearInterval(ViewFrame.intervalRef);
+ this.rendering = false;
+ }
+ }, 4);
+};
+
+ViewFrame.prototype.place = function (img, x, y) {
+ x -= this.x;
+ y -= this.y;
+ x *= this.zoom;
+ y *= this.zoom;
+ x += this.width / 2;
+ y += this.height / 2;
+
+ this.map.drawImage(img, Math.floor(x), Math.floor(y), this.zoom, this.zoom);
+};
+
+ViewFrame.prototype.updateInfobox = function (chunkName) {
+ const chunkMeta = this.availableChunks.get(chunkName);
+ this.infoboxSlots.forEach((l, k) => {
+ l.innerText = chunkMeta ? chunkMeta[k] : '0';
+ });
+};
\ No newline at end of file
--- /dev/null
+ViewFrame.initInfobox = function (ibox, iboxSlots) {
+
+ ViewFrame.chunks
+ .chunkMetadataNames.forEach((item, i) => {
+ const slot = document.createElement('tr');
+ const head = document.createElement('th');
+ head.innerText = item;
+ const row = document.createElement('td');
+ row.innerText = '0';
+ iboxSlots[i] = row;
+ slot.append(head, row);
+ ibox.append(slot);
+ });
+};
+
+ViewFrame.prototype.updateEdges = function () {
+ if (this.width != window.innerWidth || this.height != window.innerHeight) {
+ this.width = window.innerWidth;
+ this.map.canvas.width = this.width;
+ this.height = window.innerHeight;
+ this.map.canvas.height = this.height;
+ this.map.imageSmoothingEnabled = false;
+ }
+ const chunksWide = Math.ceil(this.width / this.zoom);
+ const chunksHigh = Math.ceil(this.height / this.zoom);
+
+ this.east = this.x + chunksWide / 2; // this is fractional and is used to keep track of the edges of the window
+ this.eastChunk = Math.ceil(this.east); // this is not and is used to track the chunks that need to load
+ this.west = this.x - chunksWide / 2;
+ this.westChunk = Math.floor(this.west);
+ this.north = this.y + chunksHigh / 2;
+ this.northChunk = Math.ceil(this.north);
+ this.south = this.y - chunksHigh / 2;
+ this.southChunk = Math.floor(this.south);
+};
+
+ViewFrame.prototype.moveCenter = function (dx, dy) {
+ // to pan when we click on the map!
+ this.x += (dx - this.width / 2) / this.zoom;
+ this.y += (dy - this.height / 2) / this.zoom;
+};
+ViewFrame.prototype.setCenter = function (x, y) {
+ this.x = x;
+ this.y = y;
+};
+
+ViewFrame.prototype.clear = function () {
+ this.loadedChunksByName.clear();
+ this.loadedChunksByCoords.clear();
+ if (this.chunkScript) this.chunkScript.remove();
+ delete this.chunkScript;
+ delete ViewFrame.chunks;
+ this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
+};
+
+function decode(img, cb) {
+ img.decode()
+ .then(() => {
+ cb(img);
+ })
+ .catch(() => {}); // so images arent added on error
+}
\ No newline at end of file
--- /dev/null
+const vf = new ViewFrame();
+vf.reloadChunkList();
+
+// the event handlers are in iifes so they dont make unneeded globals.
+// resize, delay re-render to reduce lag.
+(function () {
+ var id;
+ window.addEventListener('resize', () => {
+ clearTimeout(id);
+ id = setTimeout(() => {
+ vf.render();
+ }, 500);
+ });
+}());
+
+// panning
+(function () {
+ var id;
+ vf.map.canvas.addEventListener('mousedown', event => {
+ clearTimeout(id);
+ vf.moveCenter(event.pageX, event.pageY);
+ id = setTimeout(() => {
+ vf.render();
+ }, 250);
+ });
+}());
+
+
+// #### CONTROLS ####
+// hovering
+(function () {
+ var lastX = 0;
+ var lastY = 0;
+ vf.map.canvas.addEventListener('mousemove', event => {
+ // only count if the mouse moved more than a chunk
+ let x = Math.floor(vf.x +
+ (event.clientX - vf.width / 2) / vf.zoom);
+ let y = Math.floor(vf.y +
+ (event.clientY - vf.height / 2) / vf.zoom);
+ if (x == lastX && y == lastY) return;
+ lastX = x;
+ lastY = y;
+ vf.updateInfobox(x + '_' + y);
+ });
+}());
+
+// scroll/zoom
+(function () {
+ var id;
+ vf.map.canvas.addEventListener('wheel', event => {
+ clearTimeout(id);
+ vf.zoom += -Math.sign(event.deltaY);
+ id = setTimeout(() => {
+ vf.render();
+ }, 250);
+ });
+}());
+
+// reload the chunk list every six seconds
+(function () {
+ setInterval(() => {
+ vf.reloadChunkList();
+ }, 6000);
+}());
+//
+// var i = 500;
+// setTimeout(() => {
+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
+// clientX: 879,
+// clientY: 926
+// }));
+// }, i += 1000);
+//
+// setTimeout(() => {
+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
+// clientX: 666,
+// clientY: 924
+// }));
+// }, i += 2000);
+//
+// setTimeout(() => {
+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
+// clientX: 1090,
+// clientY: 936
+// }));
+// }, i += 2000);
+//
+// setTimeout(() => {
+// vf.map.dispatchEvent(new MouseEvent('mousedown', {
+// clientX: 29,
+// clientY: 785
+// }));
+// }, i += 2000);
\ No newline at end of file
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
private ColumnsMetadata chunkTopMetadata;
private PointsOfInterest POIs = new PointsOfInterest();
private EntitiesOfInterest EOIs = new EntitiesOfInterest();
+ private string jsonPreBuilt;
internal Dictionary<int, BlockDesignator> BlockID_Designators { get; private set; }
internal Dictionary<AssetLocation, EntityDesignator> Entity_Designators { get; private set; }
public static string AutomapStatusEventKey = @"AutomapStatus";
public static string AutomapCommandEventKey = @"AutomapCommand";
- PersistedConfiguration cachedConfiguration;
+ //PersistedConfiguration cachedConfiguration;
public AutomapSystem(ICoreClientAPI clientAPI, ILogger logger, PersistedConfiguration config)
{
//Listen on bus for commands
ClientAPI.Event.RegisterEventBusListener(CommandListener, 1.0, AutomapSystem.AutomapCommandEventKey);
- if (configuration.Autostart)
+ if (configuration.Autostart)
{
CurrentState = CommandType.Run;
Logger.Debug("Autostart is Enabled.");
outputText.Write(staticMap.ToText());
outputText.Flush();
+ MakePreBuiltJSON();
+
Prefill_POI_Designators();
startChunkColumn = new Vec2i((ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.X / chunkSize), (ClientAPI.World.Player.Entity.LocalPos.AsBlockPos.Z / chunkSize));
chunkTopMetadata = new ColumnsMetadata(startChunkColumn);
Logger.VerboseDebug("Cartographer re-trigger from [{0}]", cartographer_thread.ThreadState);
#endif
- if (cartographer_thread.ThreadState.HasFlag(ThreadState.Unstarted))
+ if (cartographer_thread.ThreadState.HasFlag(System.Threading.ThreadState.Unstarted))
{
cartographer_thread.Start();
}
- else if (cartographer_thread.ThreadState.HasFlag(ThreadState.WaitSleepJoin))
+ else if (cartographer_thread.ThreadState.HasFlag(System.Threading.ThreadState.WaitSleepJoin))
{
//Time to (re)write chunk shards
cartographer_thread.Interrupt();
if (!columnCounter.IsEmpty)
{
var tempSet = columnCounter.ToArray().OrderByDescending(kvp => kvp.Value);
- UpdateEntityMetadata( );
+ UpdateEntityMetadata();
foreach (var mostActiveCol in tempSet)
{
if (updatedPixels > 0)
{
- #if DEBUG
+#if DEBUG
Logger.VerboseDebug("Wrote chunk shard: ({0}) - Edits#:{1}, Pixels#:{2}", mostActiveCol.Key, mostActiveCol.Value, updatedPixels);
- #endif
+#endif
updatedChunks++;
chunkTopMetadata.Update(chunkMeta);
columnCounter.TryRemove(mostActiveCol.Key, out ejectedItem);
}
private void Reload_POI_Designators()
- {
+ {
Logger.VerboseDebug("Connecting {0} Configured Block-Designators", configuration.BlockDesignators.Count);
foreach (var designator in configuration.BlockDesignators)
{
}
- //TODO: Rewrite as Newtonsoft JsonTextWriter !!!
/// <summary>
/// Generates the JSON Metadata. (in Map object format )
/// </summary>
StreamWriter stream = new StreamWriter(jsonFilename, false, Encoding.UTF8);
- using (stream) {
- JsonTextWriter jsonWriter = new JsonTextWriter(stream);
-
- jsonWriter.Formatting = Formatting.None;
- jsonWriter.StringEscapeHandling = StringEscapeHandling.EscapeHtml;
- jsonWriter.Indentation = 0;
- //jsonWriter.AutoCompleteOnClose = true;
- jsonWriter.QuoteChar = '\'';
- jsonWriter.DateFormatHandling = DateFormatHandling.IsoDateFormat;
- jsonWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
-
- using (jsonWriter)
+ using (stream)
{
- jsonWriter.WriteRaw("ViewFrame.chunks={};\n");
- jsonWriter.WriteRaw("ViewFrame.chunks.worldSeedNum=" );
- jsonWriter.WriteValue(ClientAPI.World.Seed);
- jsonWriter.WriteRaw(";\n");
-
- jsonWriter.WriteRaw("ViewFrame.chunks.genTime=");
- jsonWriter.WriteValue(DateTimeOffset.UtcNow);
- jsonWriter.WriteRaw(";\n");
-
- jsonWriter.WriteRaw("ViewFrame.chunks.startCoords=");
- jsonWriter.WriteStartArray( );
- jsonWriter.WriteValue(startChunkColumn.X);
- jsonWriter.WriteValue(startChunkColumn.Y);
- jsonWriter.WriteEndArray( );
- jsonWriter.WriteRaw(";\n");
+ Stopwatch stopWatch = new Stopwatch();
+ stopWatch.Start();
- jsonWriter.WriteRaw("ViewFrame.chunks.chunkSize=");
- jsonWriter.WriteValue(chunkSize);
- jsonWriter.WriteRaw(";\n");
+ stream.Write(jsonPreBuilt);
- jsonWriter.WriteRaw("ViewFrame.chunks.northMostChunk=");
- jsonWriter.WriteValue(chunkTopMetadata.North_mostChunk);
- jsonWriter.WriteRaw(";\n");
+ stream.Write("ViewFrame.chunks.genTime='{0}';",
+ DateTimeOffset.UtcNow
+ );
- jsonWriter.WriteRaw("ViewFrame.chunks.southMostChunk=");
- jsonWriter.WriteValue(chunkTopMetadata.South_mostChunk);
- jsonWriter.WriteRaw(";\n");
+ stream.Write("ViewFrame.chunks.startCoords=[{0},{1}];",
+ startChunkColumn.X, startChunkColumn.Y
+ );
- jsonWriter.WriteRaw("ViewFrame.chunks.westMostChunk=");
- jsonWriter.WriteValue(chunkTopMetadata.West_mostChunk);
- jsonWriter.WriteRaw(";\n");
-
- jsonWriter.WriteRaw("ViewFrame.chunks.eastMostChunk=");
- jsonWriter.WriteValue(chunkTopMetadata.East_mostChunk);
- jsonWriter.WriteRaw(";\n");
+ stream.Write("ViewFrame.chunks.bounds=[{0},{1},{2},{3}];",
+ chunkTopMetadata.North_mostChunk,
+ chunkTopMetadata.South_mostChunk,
+ chunkTopMetadata.West_mostChunk,
+ chunkTopMetadata.East_mostChunk
+ );
//MAP object format - [key, value]: key is "x_y"
- jsonWriter.WriteRaw("ViewFrame.chunks.chunkMetadata=");
- jsonWriter.WriteStartConstructor("Map");
- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
-
+ stream.Write("ViewFrame.chunks.chunkMetadata=new Map([");
foreach (var shard in chunkTopMetadata)
{
- jsonWriter.WriteStartArray( );//Start tuple
- jsonWriter.WriteValue($"{shard.Location.X}_{shard.Location.Y}");//Key of Tuple
-
- jsonWriter.WriteStartObject( );
- jsonWriter.WritePropertyName("prettyCoord");
- jsonWriter.WriteValue( shard.Location.PrettyCoords(ClientAPI));
-
- jsonWriter.WritePropertyName("chunkAge");
- jsonWriter.WriteValue(shard.ChunkAge);
-
- jsonWriter.WritePropertyName("temp");
- jsonWriter.WriteValue(shard.Temperature);
-
- jsonWriter.WritePropertyName("YMax");
- jsonWriter.WriteValue(shard.YMax);
-
- jsonWriter.WritePropertyName("fert");
- jsonWriter.WriteValue(shard.Fertility);
-
- jsonWriter.WritePropertyName("forestDens");
- jsonWriter.WriteValue( shard.ForestDensity);
-
- jsonWriter.WritePropertyName("rain");
- jsonWriter.WriteValue( shard.Rainfall);
-
- jsonWriter.WritePropertyName("shrubDens");
- jsonWriter.WriteValue( shard.ShrubDensity);
-
- jsonWriter.WritePropertyName("airBlocks");
- jsonWriter.WriteValue( shard.AirBlocks);
-
- jsonWriter.WritePropertyName("nonAirBlocks");
- jsonWriter.WriteValue( shard.NonAirBlocks);
-
- //TODO: Heightmap ?
- //Start rockMap ; FOR a Ratio....on tooltip GUI
- jsonWriter.WritePropertyName("rockRatio");
- jsonWriter.WriteStartConstructor("Map");
- jsonWriter.WriteStartArray( );
- foreach (var rockEntry in shard.RockRatio) {
- var rockBlock = ClientAPI.World.GetBlock(rockEntry.Key);
- jsonWriter.WriteStartArray( );
- jsonWriter.WriteValue(rockBlock.Code.Path);
- jsonWriter.WriteValue(rockEntry.Value);//Total per chunk-column
- jsonWriter.WriteEndArray( );
- }
- jsonWriter.WriteEndArray( );
- jsonWriter.WriteEndConstructor( );//end rock-map
-
- jsonWriter.WriteEndObject( );//end Map value: {Object}
- jsonWriter.WriteEndArray( );//end Tuple
+ shard.Write(stream, ClientAPI);
+ stream.Write(",");
}
+ stream.Write("]);");// Close constructor of Map (chunkMetadata)
- jsonWriter.WriteEndArray( );//Enclose tuples of chunkMetadata
- jsonWriter.WriteEndConstructor( );//Close constructor of Map (chunkMetadata)
- jsonWriter.WriteRaw(";\n");
- jsonWriter.WriteRaw("ViewFrame.chunks.pointsOfInterest=");
- jsonWriter.WriteStartConstructor("Map");
- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
+ stream.Write("ViewFrame.chunks.pointsOfInterest=new Map([");
foreach (var poi in POIs)
{
- jsonWriter.WriteStartArray( );
- jsonWriter.WriteValue($"{poi.Location.X}_{poi.Location.Z}");
-
- jsonWriter.WriteStartObject();
- jsonWriter.WritePropertyName("prettyCoord");
- jsonWriter.WriteValue(poi.Location.PrettyCoords(ClientAPI) );
-
- jsonWriter.WritePropertyName("notes");
- jsonWriter.WriteValue(poi.Notes);//Encoded to HTML Entities
-
- jsonWriter.WritePropertyName("time");
- jsonWriter.WriteValue(poi.Timestamp);
-
- jsonWriter.WritePropertyName("chunkPos");
- jsonWriter.WriteValue($"{(poi.Location.X / chunkSize)}_{(poi.Location.Z / chunkSize)}");
-
- jsonWriter.WriteEndObject( );
- jsonWriter.WriteEndArray( );
+ poi.Write(stream, ClientAPI);
+ stream.Write(",");
}
- jsonWriter.Write("]);");
- jsonWriter.Write("ViewFrame.chunks.entitiesOfInterest=new Map([");
+ stream.Write("]);");
+
+ stream.Write("ViewFrame.chunks.entitiesOfInterest=new Map([");
foreach (var eoi in EOIs)
{
- jsonWriter.WriteStartArray( );
- jsonWriter.WriteValue($"{poi.Location.X}_{poi.Location.Z}");
+ eoi.Write(stream, ClientAPI);
+ stream.Write(",");
+ }
+ stream.Write("]);\n");
- jsonWriter.WriteStartObject( );
- jsonWriter.WritePropertyName("prettyCoord");
- jsonWriter.WriteValue(poi.Location.PrettyCoords(ClientAPI));
+ //stream.Write("//============= BlockID's for Rockmap / Rock-ratios ===============");
- jsonWriter.WritePropertyName("notes");
- jsonWriter.WriteValue(poi.Notes);//Encoded to HTML Entities
+ //stream.Write("ViewFrame.chunks.rockLookup=new Map([");
- jsonWriter.WritePropertyName("time");
- jsonWriter.WriteValue(poi.Timestamp);
+ //foreach (var entry in RockIdCodes)
+ //{
+ // var block = ClientAPI.World.GetBlock(entry.Key);
- jsonWriter.WritePropertyName("chunkPos");
- jsonWriter.WriteValue($"{(poi.Location.X / chunkSize)}_{(poi.Location.Z / chunkSize)}");
+ // stream.Write("[");
+ // stream.Write("'{0},", block.Code.Path);
- jsonWriter.WriteEndObject( );
- jsonWriter.WriteEndArray( );
- }
+ // stream.Write("[");
+ // stream.Write("'{0}',", entry.Value);
- jsonWriter.WriteEndArray( );
- jsonWriter.WriteEndConstructor( );
- jsonWriter.WriteRaw(";\n");
-
- jsonWriter.WriteWhitespace("\n");
- jsonWriter.WriteComment("============= BlockID's for Rockmap / Rock-ratios ===============");
- jsonWriter.WriteWhitespace("\n");
-
- jsonWriter.WriteRaw("ViewFrame.chunks.rock_Lookup =");
- jsonWriter.WriteStartConstructor("Map");
- jsonWriter.WriteStartArray( );//An array of... 2-component arrays
-
- foreach (var entry in RockIdCodes) {
- var block = ClientAPI.World.GetBlock(entry.Key);
-
- jsonWriter.WriteStartArray( );
- jsonWriter.WriteValue(block.Code.Path);
-
- jsonWriter.WriteStartObject( );
- jsonWriter.WritePropertyName("assetCode");
- jsonWriter.WriteValue(entry.Value);
-
- jsonWriter.WritePropertyName("name");
- jsonWriter.WriteValue(Lang.GetUnformatted(block.Code.Path));
- //Color?
-
- jsonWriter.WriteEndObject( );
- jsonWriter.WriteEndArray( );
- }
- jsonWriter.WriteEndArray( );
- jsonWriter.WriteEndConstructor();
-
- jsonWriter.WriteRaw(";\n");
+ // stream.Write("{0},", Lang.GetUnformatted(block.Code.Path));
+ // //Color?
- jsonWriter.Flush();
- }
+ // stream.Write("]],");
+ //}
+
+ //stream.Write("]);\n");
+
+ stream.Flush();
+
+ stopWatch.Stop();
+ Logger.Debug("Run time of chunk write {0}", stopWatch.Elapsed);
}
}
}
chunkMeta.NonAirBlocks++;
-
- ////Heightmap
- //if (chunkMeta.HeightMap[X_index, Z_index] == 0)
- //{
- // chunkMeta.HeightMap[X_index, Z_index]
- // = (ushort) (Y_index + (targetChunkY * chunkSize));
- //}
}
while (X_index++ < (chunkSize - 1));
X_index = 0;
foreach (var loadedEntity in ClientAPI.World.LoadedEntities.ToArray())
{
- #if DEBUG
+#if DEBUG
//Logger.VerboseDebug($"ENTITY: ({loadedEntity.Value.Code}) = #{loadedEntity.Value.EntityId} {loadedEntity.Value.State} {loadedEntity.Value.LocalPos} <<<<<<<<<<<<");
- #endif
+#endif
var dMatch = Entity_Designators.SingleOrDefault(se => se.Key.Equals(loadedEntity.Value.Code));
if (dMatch.Value != null)
}
+ private void MakePreBuiltJSON()
+ {
+ var builder = new StringBuilder(512);
+ builder.Append("ViewFrame.chunks={};\n");
+ builder.AppendFormat("ViewFrame.chunks.worldSeedNum='{0}';",
+ ClientAPI.World.Seed
+ );
+ builder.AppendFormat("ViewFrame.chunks.chunkSize={0};",
+ chunkSize
+ );
+
+ builder.Append("ViewFrame.chunks.chunkMetadataNames=[");
+ var fields = typeof(ColumnMeta).GetFields();
+ var attsToSort = new List<DisplayNameAttribute>();
+ // this is so gross
+ foreach (var f in fields)
+ {
+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
+ if (att != null)
+ {
+ attsToSort.Add((DisplayNameAttribute) att);
+ }
+
+ }
+ foreach (var att in attsToSort.OrderBy(a => a.order))
+ builder.AppendFormat("'{0}',", att.name);
+ builder.Append("];\n");
+
+ builder.Append("ViewFrame.chunks.pointsOfInterestNames=[");
+ fields = typeof(PointOfInterest).GetFields();
+ attsToSort = new List<DisplayNameAttribute>();
+
+ foreach (var f in fields)
+ {
+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
+ if (att != null)
+ attsToSort.Add((DisplayNameAttribute) att);
+ }
+ foreach (var att in attsToSort.OrderBy(a => a.order))
+ builder.AppendFormat("'{0}',", att.name);
+ builder.Append("];\n");
+
+ builder.Append("ViewFrame.chunks.entityOfInterestNames=[");
+ fields = typeof(EntityOfInterest).GetFields();
+ attsToSort = new List<DisplayNameAttribute>();
+
+ foreach (var f in fields)
+ {
+ var att = f.GetCustomAttribute(typeof(DisplayNameAttribute));
+ if (att != null)
+ attsToSort.Add((DisplayNameAttribute) att);
+ }
+ foreach (var att in attsToSort.OrderBy(a => a.order))
+ builder.AppendFormat("'{0}',", att.name);
+ builder.Append("];\n");
+
+ jsonPreBuilt = builder.ToString();
+ }
+
#endregion
}