This commit is contained in:
NatureFreshMilk 2019-02-04 07:26:26 +01:00
commit ca7415f8cc
10 changed files with 187 additions and 27 deletions

View File

@ -23,7 +23,7 @@ function send_stats()
local data = {
time = minetest.get_timeofday() * 24000,
uptime = minetest.get_server_uptime(),
max_lag = get_max_lag(),
max_lag = tonumber(get_max_lag()),
players = {}
}
@ -36,11 +36,11 @@ function send_stats()
velocity = player:get_player_velocity()
}
table.insert(data.players, player)
table.insert(data.players, info)
end
http.fetch({
url = url,
url = url .. "/api/minetest",
extra_headers = { "Content-Type: application/json", "Authorization: " .. key },
timeout = 1,
post_data = minetest.write_json(data)

View File

@ -18,7 +18,7 @@ clean:
rm -rf $(OUT_DIR)
$(STATIC_VFS):
go generate
go run github.com/mjibson/esc -o vfs/static.go -prefix="static/" -pkg vfs static
build: $(STATIC_VFS) $(OUT_DIR)
# native

View File

@ -2,16 +2,15 @@ package main
import (
"fmt"
"github.com/sirupsen/logrus"
"mapserver/app"
"mapserver/mapobject"
"mapserver/params"
"mapserver/tilerendererjob"
"mapserver/web"
"runtime"
)
//go:generate -command go run github.com/mjibson/esc -o vfs/static.go -prefix="static/" -pkg vfs static
"github.com/sirupsen/logrus"
)
func main() {
//Parse command line

View File

@ -11,15 +11,28 @@
<body>
<div id="image-map"></div>
<!-- libs -->
<script src="js/lib/leaflet.js"></script>
<script src="js/lib/mithril.min.js"></script>
<!-- utils -->
<script src="js/util/debounce.js"></script>
<!-- api -->
<script src="js/api.js"></script>
<!-- components -->
<script src="js/LayerManager.js"></script>
<script src="js/SimpleCRS.js"></script>
<script src="js/WebSocketChannel.js"></script>
<script src="js/RealtimeTileLayer.js"></script>
<script src="js/CoordinatesDisplay.js"></script>
<!-- overlays -->
<script src="js/overlays/TravelnetOverlay.js"></script>
<script src="js/overlays/PlayerOverlay.js"></script>
<!-- bootstrap -->
<script src="js/main.js"></script>
</body>

View File

@ -15,6 +15,17 @@ WebSocketChannel.prototype.addListener = function(type, listener){
list.push(listener);
};
WebSocketChannel.prototype.removeListener = function(type, listener){
var list = this.listenerMap[type];
if (!list){
return
}
this.listenerMap[type] = list.filter(function(l){
return l != listener;
});
};
WebSocketChannel.prototype.connect = function(){
var ws = new WebSocket(this.wsUrl);
var self = this;
@ -25,7 +36,7 @@ WebSocketChannel.prototype.connect = function(){
var listeners = self.listenerMap[event.type];
if (listeners){
self.listeners.forEach(function(listener){
listeners.forEach(function(listener){
listener(event.data);
});
}

View File

@ -5,6 +5,10 @@ api.getConfig().then(function(cfg){
var wsChannel = new WebSocketChannel();
wsChannel.connect();
wsChannel.addListener("minetest-info", function(e){
console.log(e); //XXX
});
var rtTiles = new RealtimeTileLayer(wsChannel);
var initialZoom = 11;
@ -18,7 +22,7 @@ api.getConfig().then(function(cfg){
crs: SimpleCRS
});
map.attributionControl.addAttribution('<a href="https://github.com/thomasrudin-mt/mapserver">Mapserver</a>');
map.attributionControl.addAttribution('<a href="https://github.com/thomasrudin-mt/mapserver">Minetest Mapserver</a>');
var layers = {};
var overlays = {}
@ -29,6 +33,7 @@ api.getConfig().then(function(cfg){
tileLayer.addTo(map);
layers["Base"] = tileLayer;
overlays["Players"] = new PlayerOverlay(wsChannel, layerMgr);
overlays["Travelnet"] = new TravelnetOverlay(wsChannel, layerMgr);
L.control.layers(layers, overlays).addTo(map);

View File

@ -0,0 +1,53 @@
'use strict';
var PlayerIcon = L.icon({
iconUrl: 'pics/sam.png',
iconSize: [16, 32],
iconAnchor: [8, 16],
popupAnchor: [0, -16]
});
var PlayerOverlay = L.LayerGroup.extend({
initialize: function(wsChannel, layerMgr) {
L.LayerGroup.prototype.initialize.call(this);
this.layerMgr = layerMgr;
this.wsChannel = wsChannel;
this.currentObjects = [];
this.onLayerChange = this.onLayerChange.bind(this);
this.reDraw = this.reDraw.bind(this);
this.onMapMove = debounce(this.onMapMove.bind(this), 50);
this.wsChannel.addListener("minetest-info", this.onMinetestUpdate.bind(this));
},
onLayerChange: function(layer){
this.reDraw();
},
onMinetestUpdate: function(info){
//TODO
},
reDraw: function(){
var self = this;
this.clearLayers();
var mapLayer = this.layerMgr.getCurrentLayer()
//TODO
},
onAdd: function(map) {
this.layerMgr.addListener(this.reDraw);
this.reDraw(true)
},
onRemove: function(map) {
this.clearLayers();
this.layerMgr.removeListener(this.reDraw);
}
});

View File

@ -10,11 +10,15 @@ var TravelnetIcon = L.icon({
var TravelnetOverlay = L.LayerGroup.extend({
initialize: function(wsChannel, layerMgr) {
L.LayerGroup.prototype.initialize.call(this);
this.layerMgr = layerMgr;
this.wsChannel = wsChannel;
this.currentObjects = [];
this.onLayerChange = this.onLayerChange.bind(this);
this.onMapMove = this.onMapMove.bind(this);
this.onMapMove = debounce(this.onMapMove.bind(this), 50);
},
onLayerChange: function(layer){
@ -28,29 +32,48 @@ var TravelnetOverlay = L.LayerGroup.extend({
reDraw: function(full){
var self = this;
if (full)
if (this._map.getZoom() < 10) {
this.clearLayers();
this.currentObjects = [];
return;
}
if (full){
this.clearLayers();
this.currentObjects = [];
}
var mapLayer = this.layerMgr.getCurrentLayer()
var min = this._map.getBounds().getSouthWest();
var max = this._map.getBounds().getNorthEast();
var y1 = parseInt(mapLayer.from/16);
var y2 = parseInt(mapLayer.to/16);
var x1 = parseInt(min.lng);
var x2 = parseInt(max.lng);
var z1 = parseInt(min.lat);
var z2 = parseInt(max.lat);
//TODO: get coords
api.getMapObjects(-10,-10,-10,10,10,10,"travelnet")
api.getMapObjects(
x1, y1, y1,
x2, y2, z2,
"travelnet")
.then(function(travelnets){
//TODO: remove non-existing markers, add new ones
if (!full)
this.clearLayers();
console.log(travelnets);
//TODO: attributes, coords
var marker = L.marker([travelnet.z, travelnet.x], {icon: TravelnetIcon});
if (!full){
self.clearLayers();
}
travelnets.forEach(function(travelnet){
var popup = "<h4>" + travelnet.name + "</h4><hr>" +
var popup = "<h4>" + travelnet.attributes.station_name + "</h4><hr>" +
"<b>X: </b> " + travelnet.x + "<br>" +
"<b>Y: </b> " + travelnet.y + "<br>" +
"<b>Z: </b> " + travelnet.z + "<br>" +
"<b>Network: </b> " + travelnet.network + "<br>" +
"<b>Owner: </b> " + travelnet.owner + "<br>";
"<b>Network: </b> " + travelnet.attributes.station_network + "<br>" +
"<b>Owner: </b> " + travelnet.attributes.owner + "<br>";
var marker = L.marker([travelnet.z, travelnet.x], {icon: TravelnetIcon});
marker.bindPopup(popup).addTo(self);
});
})
@ -58,12 +81,16 @@ var TravelnetOverlay = L.LayerGroup.extend({
},
onAdd: function(map) {
map.on("zoomend", this.onMapMove);
map.on("moveend", this.onMapMove);
this.layerMgr.addListener(this.onLayerChange);
console.log("TravelnetOverlay.onAdd", map);
this.reDraw(true)
},
onRemove: function(map) {
this.clearLayers();
map.off("zoomend", this.onMapMove);
map.off("moveend", this.onMapMove);
this.layerMgr.removeListener(this.onLayerChange);
console.log("TravelnetOverlay.onRemove");
}
});

View File

@ -0,0 +1,14 @@
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};

View File

@ -6,12 +6,50 @@ import (
"net/http"
)
type PlayerPos struct {
X float64 `json:"x"`
Y float64 `json:"y"`
Z float64 `json:"z"`
}
type Player struct {
Pos PlayerPos `json:"pos"`
Name string `json:"name"`
HP int `json:"hp"`
Breath int `json:"breath"`
//TODO: stamina, skin, etc
}
type MinetestInfo struct {
MaxLag float64 `json:"max_lag"`
Players []Player `json:"players"`
Time float64 `json:"time"`
Uptime float64 `json:"uptime"`
}
type Minetest struct {
ctx *app.App
}
func (t *Minetest) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
resp.Header().Add("content-type", "application/json")
json.NewEncoder(resp).Encode("stub")
func (this *Minetest) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
if req.Header.Get("Authorization") != this.ctx.Config.WebApi.SecretKey {
resp.WriteHeader(403)
resp.Write([]byte("invalid key!"))
return
}
resp.Header().Add("content-type", "application/json")
data := &MinetestInfo{}
err := json.NewDecoder(req.Body).Decode(data)
if err != nil {
resp.WriteHeader(500)
resp.Write([]byte(err.Error()))
return
}
this.ctx.WebEventbus.Emit("minetest-info", data)
json.NewEncoder(resp).Encode("stub")
}