Skip to content
This repository was archived by the owner on Apr 7, 2019. It is now read-only.

Commit

Permalink
realtime players / tile img function
Browse files Browse the repository at this point in the history
  • Loading branch information
naturefreshmilk committed May 3, 2018
1 parent d708d20 commit 04483fa
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 70 deletions.
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@
<scope>test</scope>
</dependency>

<!-- Guava -->

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.0-jre</version>
</dependency>

<!-- xml bind -->

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static void main(String[] args) throws Exception {

for (int z=minZ; z<=maxZ; z+=step) {

TileInfo tileInfo = CoordinateResolver.fromCoordinates(x, z).toZoom(zoom);
TileInfo tileInfo = CoordinateResolver.fromCoordinatesMinZoom(x, z).toZoom(zoom);

//TileInfo minZoom = tileInfo.toZoom(CoordinateResolver.MIN_ZOOM);

Expand Down
20 changes: 13 additions & 7 deletions src/main/java/io/rudin/minetest/tileserver/TileServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.inject.Guice;
import com.google.inject.Injector;
Expand Down Expand Up @@ -51,13 +52,18 @@ public static void main(String[] args) throws Exception {
UpdateChangedTilesJob tilesJob = injector.getInstance(UpdateChangedTilesJob.class);

executor.scheduleAtFixedRate(tilesJob, 0, 2, TimeUnit.SECONDS);

System.in.read();

stop();

//TODO
executor.shutdown();

AtomicBoolean running = new AtomicBoolean(true);

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
stop();
executor.shutdownNow();
running.set(false);
}));

while (running.get()){
Thread.sleep(500);
}

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface TileServerConfig extends Config {
String tileDirectory();

@Key("minetest.db.url")
@DefaultValue("jdbc:postgresql://10.0.0.147:5432/minetest")
@DefaultValue("jdbc:postgresql://127.0.0.1:5432/minetest")
String minetestDatabaseUrl();

@Key("minetest.db.username")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ public void run() {
Integer x = change.get(TILESERVER_BLOCK_CHANGES.POSX);
Integer z = change.get(TILESERVER_BLOCK_CHANGES.POSZ);

System.out.println("Tile changed: " + x + "/" + z);
TileInfo tileInfo = CoordinateResolver.fromCoordinates(x, z);
System.out.println("Mapblock changed: " + x + "/" + z + " (Coordinates: " + x*16 + "/" + z*16 + ")");

TileInfo tileInfo = CoordinateResolver.fromCoordinatesMinZoom(x, z);

//remove all tiles in every zoom
for (int i=CoordinateResolver.MIN_ZOOM; i<=CoordinateResolver.MAX_ZOOM; i++) {
for (int i=CoordinateResolver.MAX_ZOOM; i>=CoordinateResolver.MIN_ZOOM; i--) {
TileInfo zoomedTile = tileInfo.toZoom(i);

tileCache.remove(zoomedTile.x, zoomedTile.y, zoomedTile.zoom);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.rudin.minetest.tileserver.service.impl;

import com.google.common.util.concurrent.Striped;
import io.rudin.minetest.tileserver.blockdb.tables.records.TileserverTilesRecord;
import io.rudin.minetest.tileserver.service.TileCache;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

import static io.rudin.minetest.tileserver.blockdb.tables.TileserverTiles.TILESERVER_TILES;

Expand All @@ -17,51 +19,102 @@ public class DatabaseTileCache implements TileCache {
@Inject
public DatabaseTileCache(DSLContext ctx){
this.ctx = ctx;
this.lock = Striped.lazyWeakReadWriteLock(50);
}

private final Striped<ReadWriteLock> lock;

private final DSLContext ctx;

private ReadWriteLock getLock(int x, int y, int z){
return lock.get(x + "/" + y + "/" + z);
}

@Override
public void put(int x, int y, int z, byte[] data) throws IOException {
TileserverTilesRecord record = ctx.newRecord(TILESERVER_TILES);
record.setTile(data);
record.setX(x);
record.setY(y);
record.setZ(z);
record.setMtime(System.currentTimeMillis());
record.insert();
public void put(int x, int y, int z, byte[] data) {
ReadWriteLock lock = getLock(x, y, z);
Lock writeLock = lock.writeLock();
writeLock.lock();

try {
//re-check in lock
if (has(x,y,z))
return;

TileserverTilesRecord record = ctx.newRecord(TILESERVER_TILES);
record.setTile(data);
record.setX(x);
record.setY(y);
record.setZ(z);
record.setMtime(System.currentTimeMillis());
record.insert();

} finally {
writeLock.unlock();

}
}

@Override
public byte[] get(int x, int y, int z) throws IOException {
return ctx
.select(TILESERVER_TILES.TILE)
.from(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.fetchOne(TILESERVER_TILES.TILE);
public byte[] get(int x, int y, int z) {
ReadWriteLock lock = getLock(x, y, z);
Lock readLock = lock.readLock();
readLock.lock();

try {
return ctx
.select(TILESERVER_TILES.TILE)
.from(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.fetchOne(TILESERVER_TILES.TILE);

} finally {
readLock.unlock();

}
}

@Override
public boolean has(int x, int y, int z) {
Integer count = ctx
.select(DSL.count())
.from(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.fetchOne(DSL.count());

return count > 0;
ReadWriteLock lock = getLock(x, y, z);
Lock readLock = lock.readLock();
readLock.lock();

try {
Integer count = ctx
.select(DSL.count())
.from(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.fetchOne(DSL.count());

return count > 0;

} finally {
readLock.unlock();

}
}

@Override
public void remove(int x, int y, int z) {
ctx.delete(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.execute();
ReadWriteLock lock = getLock(x, y, z);
Lock writeLock = lock.writeLock();
writeLock.lock();

try {
ctx.delete(TILESERVER_TILES)
.where(TILESERVER_TILES.X.eq(x))
.and(TILESERVER_TILES.Y.eq(y))
.and(TILESERVER_TILES.Z.eq(z))
.execute();

} finally {
writeLock.unlock();

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,45 @@ public TileInfo toZoom(int zoom) {
double deltaFactor = Math.pow(2, zoom - this.zoom);

info.zoom = zoom;
info.x = (int)(this.x * deltaFactor) + (int)((this.x * deltaFactor) % 2);
info.y = (int)(this.y * deltaFactor) + (int)((this.y * deltaFactor) % 2);
//info.x = (int)(this.x * deltaFactor) + (int)((this.x * deltaFactor) % 2);
//info.y = (int)(this.y * deltaFactor) + (int)((this.y * deltaFactor) % 2);
info.x = (int)Math.floor((double)this.x * deltaFactor);
info.y = (int)Math.floor((double)this.y * deltaFactor);

info.height = this.height / deltaFactor;
info.width = this.width / deltaFactor;


return info;
}
}

public static TileInfo fromCoordinates(int x, int z) {
TileInfo info = new TileInfo();

info.zoom = DEFAULT_ZOOM;

info.x = x / 16;
info.y = z / 16 * -1;
info.height = 1;
info.width = 1;

return info;
}


public static TileInfo fromCoordinatesMinZoom(int x, int z) {
TileInfo info = new TileInfo();

info.zoom = MAX_ZOOM;

info.x = x;
info.y = z * -1;
info.height = 1/16;
info.width = 1/16;

return info;
}

public static class MapBlockCoordinateInfo {
public int x, z;
public double width, height; //in map-blocks
Expand All @@ -52,10 +68,11 @@ public static class MapBlockCoordinateInfo {
* ...
* 7 == 0.25
* 8 == 0.5
* 9 == 1
* 10 == 2
* 11 == 4
* 12 == 8
* 9 == 1 (16x16 mapblocks)
* 10 == 2 (8x8 mapblocks)
* 11 == 4 (4x4 mapblocks)
* 12 == 8 (2x2 mapblocks)
* 13 == 16 (1 mapblock)
* ...
*/
public static double getZoomFactor(int zoom) {
Expand Down
75 changes: 65 additions & 10 deletions src/main/resources/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,82 @@
return Math.pow(2, zoom-9);
}
});

var initialZoom = 11;
var initialCenter = [0, 0];

var hashParts = location.hash.substring(1).split("/");
if (hashParts.length == 3){
initialCenter[0] = +hashParts[1];
initialCenter[1] = +hashParts[0];
initialZoom = +hashParts[2]
}

var map = L.map('image-map', {
minZoom: 1,
maxZoom: 13,
center: [0, 0],
zoom: 9,
center: initialCenter,
zoom: initialZoom,
crs: crs
});

//works: map.on('mousemove', ev => console.log(ev.latlng));

L.tileLayer('tiles/{z}/{x}/{y}').addTo(map);

function updateHash(){
var center = map.getCenter();
location.hash = center.lng + "/" + center.lat + "/" + map.getZoom();
}

map.on('zoomend', updateHash)
map.on('moveend', updateHash)
updateHash();

var RealtimeTileLayer = L.TileLayer.extend({
createTile(coords){
var tile = document.createElement('img');
tile.src = "tiles/" + coords.z + "/" + coords.x + "/" + coords.y;
//insert update logic here...
return tile;
}
});

var tileLayer = new RealtimeTileLayer();
tileLayer.addTo(map);

//L.tileLayer('tiles/{z}/{x}/{y}').addTo(map);
//L.marker([-207, 7]).bindPopup("Spawn").addTo(map);


var playerMarkers = {}; // name -> L.Marker

var playerMapper = player => {
L.marker([player.posz/10, player.posx/10]).bindPopup(player.name).addTo(map);
var marker = playerMarkers[player.name];
var latLng = [player.posz/10, player.posx/10];
var popup = player.name + " @ " + player.posx/10 + "/" + player.posz/10;

if (!marker){
//Create marker
marker = L.marker(latLng);
marker.bindPopup(popup).addTo(map);
playerMarkers[player.name] = marker;

} else {
//Update marker
marker.setLatLng(latLng);
marker.bindPopup(popup);

}

};

fetch("player")
.then(res => res.json())
.then(players => players.forEach(playerMapper));

function updatePlayers(){
fetch("player")
.then(res => res.json())
.then(players => players.forEach(playerMapper))
.then(() => setTimeout(updatePlayers, 5000))
}

updatePlayers();

</script>

</body>
Expand Down
Loading

0 comments on commit 04483fa

Please sign in to comment.