Merge branch 'master' into HEAD
2
.github/workflows/go-test.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: go-test
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
2
.github/workflows/jshint.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: jshint
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
@ -89,6 +89,8 @@ func Setup(p params.ParamsType, cfg *Config) *App {
|
||||
"/colors/vanessa.txt",
|
||||
"/colors/advtrains.txt",
|
||||
"/colors/scifi_nodes.txt",
|
||||
"/colors/mcl2_colors.txt",
|
||||
"/colors/miles.txt",
|
||||
"/colors/custom.txt",
|
||||
}
|
||||
|
||||
|
BIN
doc/Overview.png
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 13 KiB |
61
doc/api.md
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
# Api documentation
|
||||
|
||||
REST Api documentation
|
||||
|
||||
## Mapobjects
|
||||
|
||||
Query for `bones` / `poi`/ `shop` / etc
|
||||
|
||||
* **Path:** `api/mapobjects`
|
||||
* **Method:** `POST`
|
||||
* **Consumes:** `application/json`
|
||||
* **Produces:** `application/json`
|
||||
|
||||
POST-Payload:
|
||||
```json
|
||||
{
|
||||
"pos1": {
|
||||
"x":-2048,
|
||||
"y":-2048,
|
||||
"z":-2048
|
||||
},
|
||||
"pos2": {
|
||||
"x":2048,
|
||||
"y":2048,
|
||||
"z":2048
|
||||
},
|
||||
"type":"bones"
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: `pos1` and `pos2` are in mapblocks
|
||||
|
||||
|
||||
Example query:
|
||||
```bash
|
||||
curl 'http://127.0.0.1:8080/api/mapobjects/' \
|
||||
-H 'Content-Type: application/json; charset=utf-8' \
|
||||
--data '{"pos1":{"x":-2048,"y":-2048,"z":-2048},"pos2":{"x":2048,"y":2048,"z":2048},"type":"bones"}' \
|
||||
| jq
|
||||
```
|
||||
|
||||
Result:
|
||||
```json
|
||||
[{
|
||||
"mapblock": {
|
||||
"x": -1671,
|
||||
"y": 0,
|
||||
"z": -82
|
||||
},
|
||||
"x": -26729,
|
||||
"y": 1,
|
||||
"z": -1306,
|
||||
"type": "bones",
|
||||
"mtime": 1554099532,
|
||||
"attributes": {
|
||||
"owner": "Brzezowski58",
|
||||
"time": "0"
|
||||
}
|
||||
}]
|
||||
```
|
Before Width: | Height: | Size: 299 KiB After Width: | Height: | Size: 288 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 375 KiB After Width: | Height: | Size: 359 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 227 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 92 KiB |
BIN
doc/pics/stats_webfragment.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 249 KiB |
@ -10,3 +10,20 @@ Searchable objects:
|
||||
Example:
|
||||
|
||||
<img src="../pics/search.png">
|
||||
|
||||
|
||||
# Ingame search
|
||||
|
||||
The ingame-search is enabled if the mapserver active mode is configured.
|
||||
|
||||
Commands:
|
||||
|
||||
```
|
||||
/search bones SomeDude
|
||||
/search bones *
|
||||
/search shop papyrus
|
||||
/search shop *
|
||||
```
|
||||
|
||||
Result (Exmple):
|
||||
<img src="../pics/ingame-search.png">
|
||||
|
11
doc/stats_webfragment.md
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
# Stats webfragment
|
||||
|
||||
<img src="./pics/stats_webfragment.png"></img>
|
||||
|
||||
The "world stats" info from the bottom right corner of the mapserver
|
||||
can be embedded as an iframe into any existing web-page:
|
||||
|
||||
```html
|
||||
<iframe src="http://127.0.0.1:8080/stats.html"></iframe>
|
||||
```
|
2
go.mod
@ -3,7 +3,7 @@ module mapserver
|
||||
require (
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/lib/pq v1.3.0
|
||||
github.com/mattn/go-sqlite3 v1.13.0
|
||||
github.com/mjibson/esc v0.1.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
|
2
go.sum
@ -37,6 +37,8 @@ github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
|
@ -69,10 +69,6 @@ func parseMetadata(mapblock *MapBlock, data []byte) (int, error) {
|
||||
return cr.Count, nil
|
||||
}
|
||||
|
||||
if version != 2 {
|
||||
return 0, errors.New("Wrong metadata version: " + strconv.Itoa(int(version)))
|
||||
}
|
||||
|
||||
offset++
|
||||
count := readU16(metadata, offset)
|
||||
|
||||
@ -106,7 +102,15 @@ func parseMetadata(mapblock *MapBlock, data []byte) (int, error) {
|
||||
|
||||
pairsMap[key] = value
|
||||
|
||||
offset++
|
||||
priv := 0
|
||||
if version >= 2 { /* private tag doesn't exist in version=1 */
|
||||
priv = readU8(metadata, offset)
|
||||
offset++
|
||||
}
|
||||
if priv != 0 {
|
||||
// do something usefull
|
||||
logrus.Info("Private items in Inventory")
|
||||
}
|
||||
}
|
||||
|
||||
var currentInventoryName *string
|
||||
|
@ -68,6 +68,7 @@ type SearchQuery struct {
|
||||
Pos2 *coords.MapBlockCoords `json:"pos2"`
|
||||
Type string `json:"type"`
|
||||
AttributeLike *SearchAttributeLike `json:"attributelike"`
|
||||
Limit *int `json:"limit"`
|
||||
}
|
||||
|
||||
type DBAccessor interface {
|
||||
|
@ -10,6 +10,11 @@ func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobject
|
||||
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
var limit = 1000
|
||||
|
||||
if q.Limit != nil {
|
||||
limit = *q.Limit
|
||||
}
|
||||
|
||||
if q.AttributeLike == nil {
|
||||
//plain pos search
|
||||
@ -17,6 +22,7 @@ func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobject
|
||||
q.Type,
|
||||
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
|
||||
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
|
||||
limit,
|
||||
)
|
||||
|
||||
} else {
|
||||
@ -26,6 +32,7 @@ func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobject
|
||||
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
|
||||
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
|
||||
q.AttributeLike.Key, q.AttributeLike.Value,
|
||||
limit,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ where o.type = $1
|
||||
and o.posx >= $2 and o.posy >= $3 and o.posz >= $4
|
||||
and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
|
||||
order by o.id
|
||||
limit $8
|
||||
`
|
||||
const getMapDataWithAttributeLikePosQuery = `
|
||||
select o.id, o.type, o.mtime,
|
||||
@ -26,6 +27,7 @@ and o.type = $1
|
||||
and o.posx >= $2 and o.posy >= $3 and o.posz >= $4
|
||||
and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
|
||||
order by o.id
|
||||
limit $10
|
||||
`
|
||||
|
||||
const removeMapDataQuery = `
|
||||
|
@ -11,12 +11,18 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
|
||||
var limit = 1000
|
||||
if q.Limit != nil {
|
||||
limit = *q.Limit
|
||||
}
|
||||
|
||||
if q.AttributeLike == nil {
|
||||
//plain pos search
|
||||
rows, err = db.db.Query(getMapDataPosQuery,
|
||||
q.Type,
|
||||
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
|
||||
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
|
||||
limit,
|
||||
)
|
||||
|
||||
} else {
|
||||
@ -26,6 +32,7 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
|
||||
q.Type,
|
||||
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
|
||||
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
|
||||
limit,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ where o.type = ?
|
||||
and o.posx >= ? and o.posy >= ? and o.posz >= ?
|
||||
and o.posx <= ? and o.posy <= ? and o.posz <= ?
|
||||
order by o.id
|
||||
limit ?
|
||||
`
|
||||
|
||||
const getMapDataWithAttributeLikePosQuery = `
|
||||
@ -27,6 +28,7 @@ and o.type = ?
|
||||
and o.posx >= ? and o.posy >= ? and o.posz >= ?
|
||||
and o.posx <= ? and o.posy <= ? and o.posz <= ?
|
||||
order by o.id
|
||||
limit ?
|
||||
`
|
||||
|
||||
const removeMapDataQuery = `
|
||||
|
BIN
pics/bones.png
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
BIN
pics/ingame-search.png
Normal file
After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 37 KiB |
BIN
pics/poi.png
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 376 KiB After Width: | Height: | Size: 294 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 67 KiB |
BIN
pics/search.png
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 123 KiB |
BIN
pics/trains.png
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
BIN
pics/trains2.png
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 44 KiB |
BIN
pics/web.png
Before Width: | Height: | Size: 452 KiB After Width: | Height: | Size: 449 KiB |
11
readme.md
@ -5,8 +5,17 @@ Minetest mapserver
|
||||
![](https://github.com/minetest-mapserver/mapserver/workflows/jshint/badge.svg)
|
||||
![](https://github.com/minetest-mapserver/mapserver/workflows/go-test/badge.svg)
|
||||
|
||||
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/minetest-mapserver/mapserver)
|
||||
![GitHub repo size](https://img.shields.io/github/repo-size/minetest-tools/mapserver.svg)
|
||||
![GitHub closed issues](https://img.shields.io/github/issues-closed/minetest-tools/mapserver.svg)
|
||||
![GitHub issues](https://img.shields.io/github/issues/minetest-mapserver/mapserver)
|
||||
|
||||
![GitHub All Releases](https://img.shields.io/github/downloads/minetest-mapserver/mapserver/total)
|
||||
![Docker Pulls](https://img.shields.io/docker/pulls/minetestmapserver/mapserver)
|
||||
|
||||
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/minetest-mapserver/mapserver)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/minetest-mapserver/mapserver)](https://goreportcard.com/report/github.com/minetest-mapserver/mapserver)
|
||||
|
||||
|
||||
<img src="./doc/pics/General_map_preview.png">
|
||||
|
||||
@ -23,6 +32,8 @@ Demo: [Pandorabox Server map](https://pandorabox.io/map/#-1782.25/493.5/10)
|
||||
* [Search](doc/search.md)
|
||||
* [Configuration](doc/config.md)
|
||||
* [Recommended specs](doc/recommended_specs.md)
|
||||
* [Stats webfragment](doc/stats_webfragment.md)
|
||||
* [Web API](doc/api.md)
|
||||
* [Contribution](doc/contrib.md)
|
||||
* [Development](doc/dev.md)
|
||||
* [License](doc/license.md)
|
||||
|
1416
static/colors/mcl2_colors.txt
Normal file
28562
static/colors/miles.txt
Normal file
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 101 KiB |
@ -1,2 +1,3 @@
|
||||
bundle.js
|
||||
bundle-stats.js
|
||||
lib/*
|
||||
|
104
static/js/bundle-stats.js
Normal file
@ -0,0 +1,104 @@
|
||||
(function(f){typeof define==='function'&&define.amd?define(f):f();}((function(){'use strict';function WorldStats(info){
|
||||
|
||||
var timeIcon = m("span", { class: "fa fa-sun", style: "color: orange;" });
|
||||
|
||||
if (info.time < 5500 || info.time > 19000) //0 - 24'000
|
||||
timeIcon = m("span", { class: "fa fa-moon", style: "color: blue;" });
|
||||
|
||||
function getHour(){
|
||||
return Math.floor(info.time/1000);
|
||||
}
|
||||
|
||||
function getMinute(){
|
||||
var min = Math.floor((info.time % 1000) / 1000 * 60);
|
||||
return min > 10 ? min : "0" + min;
|
||||
}
|
||||
|
||||
function getLag(){
|
||||
var color = "green";
|
||||
if (info.max_lag > 0.8)
|
||||
color = "orange";
|
||||
else if (info.max_lag > 1.2)
|
||||
color = "red";
|
||||
|
||||
return [
|
||||
m("span", { class: "fa fa-wifi", style: "color: " + color }),
|
||||
parseInt(info.max_lag*1000),
|
||||
" ms"
|
||||
];
|
||||
}
|
||||
|
||||
function getPlayers(){
|
||||
return [
|
||||
m("span", { class: "fa fa-users" }),
|
||||
info.players ? info.players.length : "0"
|
||||
];
|
||||
}
|
||||
|
||||
return m("div", [
|
||||
getPlayers(),
|
||||
" ",
|
||||
getLag(),
|
||||
" ",
|
||||
m("span", { class: "fa fa-clock" }),
|
||||
timeIcon,
|
||||
getHour(), ":", getMinute()
|
||||
]);
|
||||
|
||||
}class WebSocketChannel {
|
||||
constructor(){
|
||||
this.wsUrl = window.location.protocol.replace("http", "ws") +
|
||||
"//" + window.location.host +
|
||||
window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/")) +
|
||||
"/api/ws";
|
||||
|
||||
this.listenerMap = {/* type -> [listeners] */};
|
||||
}
|
||||
|
||||
addListener(type, listener){
|
||||
var list = this.listenerMap[type];
|
||||
if (!list){
|
||||
list = [];
|
||||
this.listenerMap[type] = list;
|
||||
}
|
||||
|
||||
list.push(listener);
|
||||
}
|
||||
|
||||
removeListener(type, listener){
|
||||
var list = this.listenerMap[type];
|
||||
if (!list){
|
||||
return;
|
||||
}
|
||||
|
||||
this.listenerMap[type] = list.filter(l => l != listener);
|
||||
}
|
||||
|
||||
connect(){
|
||||
var ws = new WebSocket(this.wsUrl);
|
||||
var self = this;
|
||||
|
||||
ws.onmessage = function(e){
|
||||
var event = JSON.parse(e.data);
|
||||
//rendered-tile, mapobject-created, mapobjects-cleared
|
||||
|
||||
var listeners = self.listenerMap[event.type];
|
||||
if (listeners){
|
||||
listeners.forEach(function(listener){
|
||||
listener(event.data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = function(){
|
||||
//reconnect after some time
|
||||
setTimeout(self.connect.bind(self), 1000);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var wsChannel = new WebSocketChannel();wsChannel.connect();
|
||||
|
||||
wsChannel.addListener("minetest-info", function(info){
|
||||
m.render(document.getElementById("app"), WorldStats(info));
|
||||
});})));//# sourceMappingURL=bundle-stats.js.map
|
1
static/js/bundle-stats.js.map
Normal file
49
static/js/components/WorldStats.js
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
export default function(info){
|
||||
|
||||
var timeIcon = m("span", { class: "fa fa-sun", style: "color: orange;" });
|
||||
|
||||
if (info.time < 5500 || info.time > 19000) //0 - 24'000
|
||||
timeIcon = m("span", { class: "fa fa-moon", style: "color: blue;" });
|
||||
|
||||
function getHour(){
|
||||
return Math.floor(info.time/1000);
|
||||
}
|
||||
|
||||
function getMinute(){
|
||||
var min = Math.floor((info.time % 1000) / 1000 * 60);
|
||||
return min >= 10 ? min : "0" + min;
|
||||
}
|
||||
|
||||
function getLag(){
|
||||
var color = "green";
|
||||
if (info.max_lag > 0.8)
|
||||
color = "orange";
|
||||
else if (info.max_lag > 1.2)
|
||||
color = "red";
|
||||
|
||||
return [
|
||||
m("span", { class: "fa fa-wifi", style: "color: " + color }),
|
||||
parseInt(info.max_lag*1000),
|
||||
" ms"
|
||||
];
|
||||
}
|
||||
|
||||
function getPlayers(){
|
||||
return [
|
||||
m("span", { class: "fa fa-users" }),
|
||||
info.players ? info.players.length : "0"
|
||||
];
|
||||
}
|
||||
|
||||
return m("div", [
|
||||
getPlayers(),
|
||||
" ",
|
||||
getLag(),
|
||||
" ",
|
||||
m("span", { class: "fa fa-clock" }),
|
||||
timeIcon,
|
||||
getHour(), ":", getMinute()
|
||||
]);
|
||||
|
||||
}
|
@ -1,53 +1,5 @@
|
||||
/* exported WorldInfoDisplay */
|
||||
|
||||
var worldInfoRender = function(info){
|
||||
|
||||
var timeIcon = m("span", { class: "fa fa-sun", style: "color: orange;" });
|
||||
|
||||
if (info.time < 5500 || info.time > 19000) //0 - 24'000
|
||||
timeIcon = m("span", { class: "fa fa-moon", style: "color: blue;" });
|
||||
|
||||
function getHour(){
|
||||
return Math.floor(info.time/1000);
|
||||
}
|
||||
|
||||
function getMinute(){
|
||||
var min = Math.floor((info.time % 1000) / 1000 * 60);
|
||||
return min > 10 ? min : "0" + min;
|
||||
}
|
||||
|
||||
function getLag(){
|
||||
var color = "green";
|
||||
if (info.max_lag > 0.8)
|
||||
color = "orange";
|
||||
else if (info.max_lag > 1.2)
|
||||
color = "red";
|
||||
|
||||
return [
|
||||
m("span", { class: "fa fa-wifi", style: "color: " + color }),
|
||||
parseInt(info.max_lag*1000),
|
||||
" ms"
|
||||
];
|
||||
}
|
||||
|
||||
function getPlayers(){
|
||||
return [
|
||||
m("span", { class: "fa fa-users" }),
|
||||
info.players ? info.players.length : "0"
|
||||
];
|
||||
}
|
||||
|
||||
return m("div", [
|
||||
getPlayers(),
|
||||
" ",
|
||||
getLag(),
|
||||
" ",
|
||||
m("span", { class: "fa fa-clock" }),
|
||||
timeIcon,
|
||||
getHour(), ":", getMinute()
|
||||
]);
|
||||
|
||||
};
|
||||
import WorldStats from '../components/WorldStats.js';
|
||||
|
||||
// coord display
|
||||
export default L.Control.extend({
|
||||
@ -60,7 +12,7 @@ export default L.Control.extend({
|
||||
var div = L.DomUtil.create('div', 'leaflet-bar leaflet-custom-display');
|
||||
|
||||
this.wsChannel.addListener("minetest-info", function(info){
|
||||
m.render(div, worldInfoRender(info));
|
||||
m.render(div, WorldStats(info));
|
||||
});
|
||||
|
||||
return div;
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
export default {
|
||||
export default [{
|
||||
input: 'main.js',
|
||||
output: {
|
||||
file :'bundle.js',
|
||||
@ -7,4 +7,12 @@ export default {
|
||||
sourcemap: true,
|
||||
compact: true
|
||||
}
|
||||
};
|
||||
},{
|
||||
input: 'stats.js',
|
||||
output: {
|
||||
file :'bundle-stats.js',
|
||||
format: 'umd',
|
||||
sourcemap: true,
|
||||
compact: true
|
||||
}
|
||||
}];
|
||||
|
9
static/js/stats.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
import WorldStats from './components/WorldStats.js';
|
||||
import wsChannel from './WebSocketChannel.js';
|
||||
|
||||
wsChannel.connect();
|
||||
|
||||
wsChannel.addListener("minetest-info", function(info){
|
||||
m.render(document.getElementById("app"), WorldStats(info));
|
||||
});
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 662 B After Width: | Height: | Size: 435 B |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 548 B |
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 507 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
22
static/stats.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<!-- styles -->
|
||||
<link rel="stylesheet" href="css/fontawesome.min.css"/>
|
||||
<title>Minetest Mapserver stats</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<!-- libraries -->
|
||||
<script src="js/lib/mithril.min.js"></script>
|
||||
|
||||
<!-- main module -->
|
||||
<script src="js/stats.js" type="module"></script>
|
||||
|
||||
<!-- no modules -->
|
||||
<script src="js/bundle-stats.js" nomodule></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 678 KiB After Width: | Height: | Size: 673 KiB |
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 798 KiB After Width: | Height: | Size: 786 KiB |
@ -1,16 +1,14 @@
|
||||
package tiledb
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io/ioutil"
|
||||
"mapserver/coords"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var mutex = &sync.RWMutex{}
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func New(path string) (*TileDB, error) {
|
||||
return &TileDB{
|
||||
@ -40,9 +38,6 @@ func (this *TileDB) GetTile(pos *coords.TileCoords) ([]byte, error) {
|
||||
timer := prometheus.NewTimer(tiledbLoadDuration)
|
||||
defer timer.ObserveDuration()
|
||||
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
|
||||
fields := logrus.Fields{
|
||||
"pos": pos,
|
||||
}
|
||||
@ -66,9 +61,6 @@ func (this *TileDB) SetTile(pos *coords.TileCoords, tile []byte) error {
|
||||
timer := prometheus.NewTimer(tiledbSaveDuration)
|
||||
defer timer.ObserveDuration()
|
||||
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
fields := logrus.Fields{
|
||||
"pos": pos,
|
||||
"size": len(tile),
|
||||
|