mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-09-27 06:42:42 +02:00
Add own metrics and save and load the state the render-manager of the sponge-plugin
This commit is contained in:
parent
731c31e601
commit
82ab8c2c7c
@ -0,0 +1,7 @@
|
|||||||
|
package de.bluecolored.bluemap.core;
|
||||||
|
|
||||||
|
public class BlueMap {
|
||||||
|
|
||||||
|
public static final String VERSION = "0.0.0";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package de.bluecolored.bluemap.core.metrics;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
|
|
||||||
|
public class Metrics {
|
||||||
|
|
||||||
|
private static final String METRICS_REPORT_URL = "https://metrics.bluecolored.de/bluemap/";
|
||||||
|
|
||||||
|
public static void sendReportAsync(String implementation) {
|
||||||
|
new Thread(() -> sendReport(implementation)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendReport(String implementation) {
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("implementation", implementation);
|
||||||
|
data.addProperty("version", BlueMap.VERSION);
|
||||||
|
|
||||||
|
try {
|
||||||
|
sendData(data.toString());
|
||||||
|
} catch (Exception ex) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String sendData(String data) throws MalformedURLException, IOException {
|
||||||
|
byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
HttpsURLConnection connection = (HttpsURLConnection) new URL(METRICS_REPORT_URL).openConnection();
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.addRequestProperty("Content-Length", String.valueOf(bytes.length));
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||||
|
connection.addRequestProperty("Connection", "close");
|
||||||
|
connection.setRequestProperty("User-Agent", "BlueMap");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
try (OutputStream out = connection.getOutputStream()){
|
||||||
|
out.write(bytes);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
|
String line;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
builder.append(line + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -111,4 +111,15 @@ public int getUpdateBufferCount() {
|
|||||||
return updateBuffer.size();
|
return updateBuffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void flushTileBuffer() {
|
||||||
|
RenderManager renderManager = SpongePlugin.getInstance().getRenderManager();
|
||||||
|
|
||||||
|
synchronized (updateBuffer) {
|
||||||
|
for (MapType map : updateBuffer.keySet()) {
|
||||||
|
renderManager.createTickets(map, updateBuffer.get(map));
|
||||||
|
}
|
||||||
|
updateBuffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package de.bluecolored.bluemap.sponge;
|
package de.bluecolored.bluemap.sponge;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -7,9 +9,13 @@
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.MultimapBuilder;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
|
||||||
@ -151,4 +157,77 @@ public boolean isRunning() {
|
|||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeState(DataOutputStream out) throws IOException {
|
||||||
|
//prepare renderTickets
|
||||||
|
ListMultimap<MapType, Vector2i> tileMap = MultimapBuilder.hashKeys().arrayListValues().<MapType, Vector2i>build();
|
||||||
|
synchronized (renderTickets) {
|
||||||
|
for (RenderTicket ticket : renderTickets) {
|
||||||
|
tileMap.put(ticket.getMapType(), ticket.getTile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write renderTickets
|
||||||
|
Set<MapType> maps = tileMap.keySet();
|
||||||
|
out.writeInt(maps.size());
|
||||||
|
for (MapType map : maps) {
|
||||||
|
List<Vector2i> tiles = tileMap.get(map);
|
||||||
|
|
||||||
|
out.writeUTF(map.getId());
|
||||||
|
out.writeInt(tiles.size());
|
||||||
|
for (Vector2i tile : tiles) {
|
||||||
|
out.writeInt(tile.getX());
|
||||||
|
out.writeInt(tile.getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write tasks
|
||||||
|
synchronized (renderTasks) {
|
||||||
|
out.writeInt(renderTasks.size());
|
||||||
|
for (RenderTask task : renderTasks) {
|
||||||
|
task.write(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readState(DataInputStream in) throws IOException {
|
||||||
|
//read renderTickets
|
||||||
|
int mapCount = in.readInt();
|
||||||
|
for (int i = 0; i < mapCount; i++) {
|
||||||
|
String mapId = in.readUTF();
|
||||||
|
|
||||||
|
MapType mapType = null;
|
||||||
|
for (MapType map : SpongePlugin.getInstance().getMapTypes()) {
|
||||||
|
if (map.getId().equals(mapId)) {
|
||||||
|
mapType = map;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mapType == null) {
|
||||||
|
Logger.global.logWarning("Some render-tickets can not be loaded because the map (id: '" + mapId + "') does not exist anymore. They will be discarded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int tileCount = in.readInt();
|
||||||
|
List<Vector2i> tiles = new ArrayList<>();
|
||||||
|
for (int j = 0; j < tileCount; j++) {
|
||||||
|
int x = in.readInt();
|
||||||
|
int y = in.readInt();
|
||||||
|
Vector2i tile = new Vector2i(x, y);
|
||||||
|
tiles.add(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTickets(mapType, tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
//read tasks
|
||||||
|
int taskCount = in.readInt();
|
||||||
|
for (int i = 0; i < taskCount; i++) {
|
||||||
|
try {
|
||||||
|
RenderTask task = RenderTask.read(in);
|
||||||
|
addRenderTask(task);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logWarning("A render-task can not be loaded. It will be discared. (Error message: " + ex.toString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package de.bluecolored.bluemap.sponge;
|
package de.bluecolored.bluemap.sponge;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2d;
|
import com.flowpowered.math.vector.Vector2d;
|
||||||
@ -21,8 +26,6 @@ public class RenderTask {
|
|||||||
private long additionalRunTime;
|
private long additionalRunTime;
|
||||||
private int renderedTiles;
|
private int renderedTiles;
|
||||||
|
|
||||||
private UUID taskOwner;
|
|
||||||
|
|
||||||
public RenderTask(String name, MapType mapType) {
|
public RenderTask(String name, MapType mapType) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -31,7 +34,6 @@ public RenderTask(String name, MapType mapType) {
|
|||||||
this.firstTileTime = -1;
|
this.firstTileTime = -1;
|
||||||
this.additionalRunTime = 0;
|
this.additionalRunTime = 0;
|
||||||
this.renderedTiles = 0;
|
this.renderedTiles = 0;
|
||||||
this.taskOwner = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void optimizeQueue() {
|
public void optimizeQueue() {
|
||||||
@ -132,8 +134,54 @@ public boolean isFinished() {
|
|||||||
return renderTiles.isEmpty();
|
return renderTiles.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getTaskOwner() {
|
public void write(DataOutputStream out) throws IOException {
|
||||||
return taskOwner;
|
synchronized (renderTiles) {
|
||||||
|
pause();
|
||||||
|
|
||||||
|
out.writeUTF(name);
|
||||||
|
out.writeUTF(mapType.getId());
|
||||||
|
|
||||||
|
out.writeLong(additionalRunTime);
|
||||||
|
out.writeInt(renderedTiles);
|
||||||
|
|
||||||
|
out.writeInt(renderTiles.size());
|
||||||
|
for (Vector2i tile : renderTiles) {
|
||||||
|
out.writeInt(tile.getX());
|
||||||
|
out.writeInt(tile.getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RenderTask read(DataInputStream in) throws IOException {
|
||||||
|
String name = in.readUTF();
|
||||||
|
String mapId = in.readUTF();
|
||||||
|
|
||||||
|
MapType mapType = null;
|
||||||
|
for (MapType map : SpongePlugin.getInstance().getMapTypes()) {
|
||||||
|
if (map.getId().equals(mapId)) {
|
||||||
|
mapType = map;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mapType == null) throw new IOException("Map type with id '" + mapId + "' does not exist!");
|
||||||
|
|
||||||
|
RenderTask task = new RenderTask(name, mapType);
|
||||||
|
|
||||||
|
task.additionalRunTime = in.readLong();
|
||||||
|
task.renderedTiles = in.readInt();
|
||||||
|
|
||||||
|
int tileCount = in.readInt();
|
||||||
|
List<Vector2i> tiles = new ArrayList<>();
|
||||||
|
for (int i = 0; i < tileCount; i++) {
|
||||||
|
int x = in.readInt();
|
||||||
|
int y = in.readInt();
|
||||||
|
Vector2i tile = new Vector2i(x, y);
|
||||||
|
tiles.add(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
task.addTiles(tiles);
|
||||||
|
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,21 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.sponge;
|
package de.bluecolored.bluemap.sponge;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -42,15 +50,19 @@
|
|||||||
import org.spongepowered.api.event.game.state.GameStartingServerEvent;
|
import org.spongepowered.api.event.game.state.GameStartingServerEvent;
|
||||||
import org.spongepowered.api.event.game.state.GameStoppingEvent;
|
import org.spongepowered.api.event.game.state.GameStoppingEvent;
|
||||||
import org.spongepowered.api.plugin.Plugin;
|
import org.spongepowered.api.plugin.Plugin;
|
||||||
|
import org.spongepowered.api.plugin.PluginContainer;
|
||||||
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
||||||
|
import org.spongepowered.api.util.Tristate;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.config.ConfigurationFile;
|
import de.bluecolored.bluemap.core.config.ConfigurationFile;
|
||||||
import de.bluecolored.bluemap.core.config.ConfigurationFile.MapConfig;
|
import de.bluecolored.bluemap.core.config.ConfigurationFile.MapConfig;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
||||||
|
import de.bluecolored.bluemap.core.metrics.Metrics;
|
||||||
import de.bluecolored.bluemap.core.render.TileRenderer;
|
import de.bluecolored.bluemap.core.render.TileRenderer;
|
||||||
import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
|
import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
|
||||||
import de.bluecolored.bluemap.core.render.lowres.LowresModelManager;
|
import de.bluecolored.bluemap.core.render.lowres.LowresModelManager;
|
||||||
@ -74,7 +86,7 @@ public class SpongePlugin {
|
|||||||
|
|
||||||
public static final String PLUGIN_ID = "bluemap";
|
public static final String PLUGIN_ID = "bluemap";
|
||||||
public static final String PLUGIN_NAME = "BlueMap";
|
public static final String PLUGIN_NAME = "BlueMap";
|
||||||
public static final String PLUGIN_VERSION = "0.0.0";
|
public static final String PLUGIN_VERSION = BlueMap.VERSION;
|
||||||
|
|
||||||
private static SpongePlugin instance;
|
private static SpongePlugin instance;
|
||||||
|
|
||||||
@ -190,6 +202,20 @@ public synchronized void load() throws IOException, NoSuchResourceException {
|
|||||||
renderManager = new RenderManager(config.getRenderThreadCount());
|
renderManager = new RenderManager(config.getRenderThreadCount());
|
||||||
renderManager.start();
|
renderManager.start();
|
||||||
|
|
||||||
|
//load render-manager state
|
||||||
|
try {
|
||||||
|
File saveFile = configurationDir.resolve("rmstate").toFile();
|
||||||
|
saveFile.getParentFile().mkdirs();
|
||||||
|
if (saveFile.exists()) {
|
||||||
|
try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(saveFile)))) {
|
||||||
|
renderManager.readState(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveFile.delete();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to load render-manager state!", ex);
|
||||||
|
}
|
||||||
|
|
||||||
//start map updater
|
//start map updater
|
||||||
updateHandler = new MapUpdateHandler();
|
updateHandler = new MapUpdateHandler();
|
||||||
|
|
||||||
@ -217,6 +243,21 @@ public synchronized void load() throws IOException, NoSuchResourceException {
|
|||||||
webServer.start();
|
webServer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//metrics
|
||||||
|
Sponge.getScheduler().createTaskBuilder()
|
||||||
|
.async()
|
||||||
|
.delay(0, TimeUnit.MINUTES)
|
||||||
|
.interval(30, TimeUnit.MINUTES)
|
||||||
|
.execute(() -> {
|
||||||
|
Optional<PluginContainer> plugin = Sponge.getPluginManager().fromInstance(this);
|
||||||
|
if (!plugin.isPresent()) return;
|
||||||
|
|
||||||
|
Tristate metricsEnabled = Sponge.getMetricsConfigManager().getCollectionState(plugin.get());
|
||||||
|
if (metricsEnabled == Tristate.UNDEFINED) metricsEnabled = Sponge.getMetricsConfigManager().getGlobalCollectionState();
|
||||||
|
if (metricsEnabled == Tristate.TRUE) Metrics.sendReport("Sponge");
|
||||||
|
})
|
||||||
|
.submit(this);
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +269,6 @@ public synchronized void unload() {
|
|||||||
|
|
||||||
//unregister listeners
|
//unregister listeners
|
||||||
if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler);
|
if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler);
|
||||||
updateHandler = null;
|
|
||||||
|
|
||||||
//unregister commands
|
//unregister commands
|
||||||
Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
|
Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
|
||||||
@ -236,6 +276,23 @@ public synchronized void unload() {
|
|||||||
//stop scheduled tasks
|
//stop scheduled tasks
|
||||||
Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel());
|
Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel());
|
||||||
|
|
||||||
|
//save render-manager state
|
||||||
|
if (updateHandler != null) updateHandler.flushTileBuffer(); //first write all buffered tiles to the render manager to save them too
|
||||||
|
if (renderManager != null) {
|
||||||
|
try {
|
||||||
|
File saveFile = configurationDir.resolve("rmstate").toFile();
|
||||||
|
saveFile.getParentFile().mkdirs();
|
||||||
|
if (saveFile.exists()) saveFile.delete();
|
||||||
|
saveFile.createNewFile();
|
||||||
|
|
||||||
|
try (DataOutputStream out = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(saveFile)))) {
|
||||||
|
renderManager.writeState(out);
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to save render-manager state!", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//save renders
|
//save renders
|
||||||
for (MapType map : maps.values()) {
|
for (MapType map : maps.values()) {
|
||||||
map.getTileRenderer().save();
|
map.getTileRenderer().save();
|
||||||
@ -244,6 +301,7 @@ public synchronized void unload() {
|
|||||||
//clear resources and configs
|
//clear resources and configs
|
||||||
renderManager = null;
|
renderManager = null;
|
||||||
webServer = null;
|
webServer = null;
|
||||||
|
updateHandler = null;
|
||||||
resourcePack = null;
|
resourcePack = null;
|
||||||
config = null;
|
config = null;
|
||||||
maps.clear();
|
maps.clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user