diff --git a/app/config.go b/app/config.go
index a6352fb..72aa274 100644
--- a/app/config.go
+++ b/app/config.go
@@ -61,6 +61,7 @@ type MapObjectConfig struct {
Fancyvend bool `json:"fancyvend"`
ATM bool `json:"atm"`
Train bool `json:"train"`
+ TrainSignal bool `json:"trainsignal"`
Minecart bool `json:"minecart"`
Locator bool `json:"locator"`
}
@@ -149,6 +150,7 @@ func ParseConfig(filename string) (*Config, error) {
Fancyvend: true,
ATM: true,
Train: true,
+TrainSignal: true,
Minecart: false,
Locator: false,
}
diff --git a/static/js/Overlaysetup.js b/static/js/Overlaysetup.js
index 6e4dfde..5f71749 100644
--- a/static/js/Overlaysetup.js
+++ b/static/js/Overlaysetup.js
@@ -20,6 +20,7 @@ import ATMOverlay from './overlays/ATMOverlay.js';
import LocatorOverlay from './overlays/LocatorOverlay.js';
import BorderOverlay from './overlays/BorderOverlay.js';
import TrainOverlay from './overlays/TrainOverlay.js';
+import TrainsignalOverlay from './overlays/TrainsignalOverlay.js';
export default function(cfg, map, overlays, wsChannel, layerMgr){
@@ -155,11 +156,20 @@ export default function(cfg, map, overlays, wsChannel, layerMgr){
if (cfg.mapobjects.train) {
overlays.Trains = new TrainOverlay(wsChannel, layerMgr);
+
if (isDefault("train")) {
map.addLayer(overlays.Trains);
}
}
+ if (cfg.mapobjects.trainsignal) {
+ overlays.Trainsignals = new TrainsignalOverlay(wsChannel, layerMgr);
+
+ if (isDefault("trainsignal")) {
+ map.addLayer(overlays.Trainsignals);
+ }
+ }
+
if (cfg.mapobjects.minecart) {
overlays.Minecart = new MinecartOverlay(wsChannel, layerMgr);
if (isDefault("minecart")) {
diff --git a/static/js/overlays/TrainsignalOverlay.js b/static/js/overlays/TrainsignalOverlay.js
new file mode 100644
index 0000000..566f9c8
--- /dev/null
+++ b/static/js/overlays/TrainsignalOverlay.js
@@ -0,0 +1,146 @@
+
+export default L.LayerGroup.extend({
+ initialize: function(wsChannel, layerMgr) {
+ L.LayerGroup.prototype.initialize.call(this);
+
+ this.layerMgr = layerMgr;
+ this.wsChannel = wsChannel;
+
+ this.currentObjects = {}; // name => marker
+ this.signals = [];
+
+ this.reDraw = this.reDraw.bind(this);
+ this.onMinetestUpdate = this.onMinetestUpdate.bind(this);
+
+ //update players all the time
+ this.wsChannel.addListener("minetest-info", function(info){
+ this.signals = info.signals || [];
+ }.bind(this));
+ },
+
+ createPopup: function(signal){
+ var html = "Signal
";
+ html += "State: " + signal.green + "
";
+
+ return html;
+ },
+
+ hashPos: function(x,y,z){
+ return x + "/" + y + "/" + z;
+ },
+
+ getMaxDisplayedZoom: function(){
+ return 10;
+ },
+
+ createMarker: function(signal){
+
+ var Icon = L.icon({
+ iconUrl: "TODO",
+
+ iconSize: [16, 16],
+ iconAnchor: [8, 8],
+ popupAnchor: [0, -16]
+ });
+
+ var marker = L.marker([signal.pos.z, signal.pos.x], {icon: Icon});
+ marker.bindPopup(this.createPopup(signal));
+
+ return marker;
+ },
+
+ isSignalInCurrentLayer: function(signal){
+ var mapLayer = this.layerMgr.getCurrentLayer();
+
+ return (signal.pos.y >= (mapLayer.from*16) && signal.pos.y <= (mapLayer.to*16));
+ },
+
+
+ onMinetestUpdate: function(/*info*/){
+
+ if (this.map.getZoom() < this.getMaxDisplayedZoom()) {
+ this.clearLayers();
+ this.currentObjects = {};
+ return;
+ }
+
+ this.signals.forEach(signal => {
+ var isInLayer = this.isSignalInCurrentLayer(signal);
+ var signalId = this.hashPos(signal.pos.x, signal.pos.y, signal.pos.z);
+
+ if (!isInLayer){
+ if (this.currentObjects[signalId]){
+ //signal is displayed and not on the layer anymore
+ //Remove the marker and reference
+ this.currentObjects[signalId].remove();
+ delete this.currentObjects[signalId];
+ }
+
+ return;
+ }
+
+ if (this.currentObjects[signalId]){
+ //marker exists
+ let marker = this.currentObjects[signalId];
+ marker.setLatLng([signal.pos.z, signal.pos.x]);
+ marker.setPopupContent(this.createPopup(signal));
+
+ } else {
+ //marker does not exist
+ let marker = this.createMarker(signal);
+ marker.addTo(this);
+
+ this.currentObjects[signalId] = marker;
+ }
+ });
+
+ Object.keys(this.currentObjects).forEach(existingId => {
+ var signalIsActive = this.signals.find((t) => {
+ var hash = this.hashPos(t.pos.x, t.pos.y, t.pos.z);
+ return hash == existingId;
+ });
+
+ if (!signalIsActive){
+ this.currentObjects[existingId].remove();
+ delete this.currentObjects[existingId];
+ }
+ });
+ },
+
+ reDraw: function(){
+ this.currentObjects = {};
+ this.clearLayers();
+
+ if (this.map.getZoom() < this.getMaxDisplayedZoom()) {
+ return;
+ }
+
+ var mapLayer = this.layerMgr.getCurrentLayer();
+
+ this.signals.forEach(signal => {
+ if (!this.isSignalInCurrentLayer(signal)){
+ //not in current layer
+ return;
+ }
+
+ var marker = this.createMarker(signal);
+ marker.addTo(this);
+ var hash = this.hashPos(signal.pos.x, signal.pos.y, signal.pos.z);
+ this.currentObjects[hash] = marker;
+ });
+
+ },
+
+ onAdd: function(map) {
+ this.map = map;
+ this.layerMgr.addListener(() => this.reDraw());
+ this.wsChannel.addListener("minetest-info", () => this.onMinetestUpdate());
+ this.reDraw();
+ },
+
+ onRemove: function(/*map*/) {
+ this.clearLayers();
+ this.layerMgr.removeListener(() => this.reDraw());
+ this.wsChannel.removeListener("minetest-info", () => this.onMinetestUpdate());
+ }
+});