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 class MapUpdateHandler {
|
|||
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;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
@ -7,9 +9,13 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -151,4 +157,77 @@ public class RenderManager {
|
|||
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;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2d;
|
||||
|
@ -21,8 +26,6 @@ public class RenderTask {
|
|||
private long additionalRunTime;
|
||||
private int renderedTiles;
|
||||
|
||||
private UUID taskOwner;
|
||||
|
||||
public RenderTask(String name, MapType mapType) {
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.name = name;
|
||||
|
@ -31,7 +34,6 @@ public class RenderTask {
|
|||
this.firstTileTime = -1;
|
||||
this.additionalRunTime = 0;
|
||||
this.renderedTiles = 0;
|
||||
this.taskOwner = null;
|
||||
}
|
||||
|
||||
public void optimizeQueue() {
|
||||
|
@ -132,8 +134,54 @@ public class RenderTask {
|
|||
return renderTiles.isEmpty();
|
||||
}
|
||||
|
||||
public UUID getTaskOwner() {
|
||||
return taskOwner;
|
||||
public void write(DataOutputStream out) throws IOException {
|
||||
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;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -42,15 +50,19 @@ import org.spongepowered.api.event.game.GameReloadEvent;
|
|||
import org.spongepowered.api.event.game.state.GameStartingServerEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStoppingEvent;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
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.MapConfig;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
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.hires.HiresModelManager;
|
||||
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_NAME = "BlueMap";
|
||||
public static final String PLUGIN_VERSION = "0.0.0";
|
||||
public static final String PLUGIN_VERSION = BlueMap.VERSION;
|
||||
|
||||
private static SpongePlugin instance;
|
||||
|
||||
|
@ -190,6 +202,20 @@ public class SpongePlugin {
|
|||
renderManager = new RenderManager(config.getRenderThreadCount());
|
||||
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
|
||||
updateHandler = new MapUpdateHandler();
|
||||
|
||||
|
@ -217,6 +243,21 @@ public class SpongePlugin {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -228,7 +269,6 @@ public class SpongePlugin {
|
|||
|
||||
//unregister listeners
|
||||
if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler);
|
||||
updateHandler = null;
|
||||
|
||||
//unregister commands
|
||||
Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
|
||||
|
@ -236,6 +276,23 @@ public class SpongePlugin {
|
|||
//stop scheduled tasks
|
||||
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
|
||||
for (MapType map : maps.values()) {
|
||||
map.getTileRenderer().save();
|
||||
|
@ -244,13 +301,14 @@ public class SpongePlugin {
|
|||
//clear resources and configs
|
||||
renderManager = null;
|
||||
webServer = null;
|
||||
updateHandler = null;
|
||||
resourcePack = null;
|
||||
config = null;
|
||||
maps.clear();
|
||||
worlds.clear();
|
||||
|
||||
loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void reload() throws IOException, NoSuchResourceException {
|
||||
unload();
|
||||
|
|
Loading…
Reference in New Issue