Merge branch 'base'

This commit is contained in:
Blue (Lukas Rieger) 2020-08-19 21:28:53 +02:00
commit dacab3073f
26 changed files with 133 additions and 96 deletions

View File

@ -10,7 +10,8 @@ repositories {
dependencies { dependencies {
shadow "org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT" shadow "org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT"
compile group: 'org.bstats', name: 'bstats-bukkit-lite', version: '1.5'
compile group: 'org.bstats', name: 'bstats-bukkit-lite', version: '1.7'
compile (project(':BlueMapCommon')) { compile (project(':BlueMapCommon')) {
//exclude dependencies provided by bukkit //exclude dependencies provided by bukkit

View File

@ -86,7 +86,9 @@ public void onTabComplete(TabCompleteEvent evt) {
completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
evt.setCompletions(completions); evt.setCompletions(completions);
} }
} catch (InterruptedException | ExecutionException | TimeoutException ignore) {} } catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException ignore) {}
} }
private class CommandProxy extends BukkitCommand { private class CommandProxy extends BukkitCommand {

View File

@ -56,12 +56,13 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
public class BukkitPlugin extends JavaPlugin implements ServerInterface, Listener { public class BukkitPlugin extends JavaPlugin implements ServerInterface, Listener {
private static BukkitPlugin instance; private static BukkitPlugin instance;
private Plugin bluemap; private Plugin pluginInstance;
private EventForwarder eventForwarder; private EventForwarder eventForwarder;
private BukkitCommands commands; private BukkitCommands commands;
@ -76,15 +77,15 @@ public BukkitPlugin() {
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>()); this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
this.eventForwarder = new EventForwarder(); this.eventForwarder = new EventForwarder();
this.bluemap = new Plugin("bukkit", this); this.pluginInstance = new Plugin("bukkit", this);
this.commands = new BukkitCommands(this.bluemap); this.commands = new BukkitCommands(this.pluginInstance);
BukkitPlugin.instance = this; BukkitPlugin.instance = this;
} }
@Override @Override
public void onEnable() { public void onEnable() {
new MetricsLite(this); new MetricsLite(this, 5912);
//save world so the level.dat is present on new worlds //save world so the level.dat is present on new worlds
Logger.global.logInfo("Saving all worlds once, to make sure the level.dat is present..."); Logger.global.logInfo("Saving all worlds once, to make sure the level.dat is present...");
@ -113,6 +114,15 @@ public void onEnable() {
//tab completions //tab completions
getServer().getPluginManager().registerEvents(commands, this); getServer().getPluginManager().registerEvents(commands, this);
//update online-player collections
this.onlinePlayerList.clear();
this.onlinePlayerMap.clear();
for (org.bukkit.entity.Player player : getServer().getOnlinePlayers()) {
BukkitPlayer bukkitPlayer = new BukkitPlayer(player);
onlinePlayerMap.put(player.getUniqueId(), bukkitPlayer);
onlinePlayerList.add(bukkitPlayer);
}
//start updating players //start updating players
getServer().getScheduler().runTaskTimer(this, this::updateSomePlayers, 1, 1); getServer().getScheduler().runTaskTimer(this, this::updateSomePlayers, 1, 1);
@ -120,10 +130,11 @@ public void onEnable() {
getServer().getScheduler().runTaskAsynchronously(this, () -> { getServer().getScheduler().runTaskAsynchronously(this, () -> {
try { try {
Logger.global.logInfo("Loading..."); Logger.global.logInfo("Loading...");
this.bluemap.load(); this.pluginInstance.load();
if (bluemap.isLoaded()) Logger.global.logInfo("Loaded!"); if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
} catch (Throwable t) { } catch (IOException | ParseResourceException | RuntimeException e) {
Logger.global.logError("Failed to load!", t); Logger.global.logError("Failed to load!", e);
this.pluginInstance.unload();
} }
}); });
} }
@ -132,7 +143,7 @@ public void onEnable() {
public void onDisable() { public void onDisable() {
Logger.global.logInfo("Stopping..."); Logger.global.logInfo("Stopping...");
getServer().getScheduler().cancelTasks(this); getServer().getScheduler().cancelTasks(this);
bluemap.unload(); pluginInstance.unload();
Logger.global.logInfo("Saved and stopped!"); Logger.global.logInfo("Saved and stopped!");
} }
@ -165,6 +176,7 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException {
try { try {
return futureUUID.get(); return futureUUID.get();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException(e); throw new IOException(e);
} catch (ExecutionException e) { } catch (ExecutionException e) {
if (e.getCause() instanceof IOException) { if (e.getCause() instanceof IOException) {
@ -197,7 +209,7 @@ public File getConfigFolder() {
} }
public Plugin getBlueMap() { public Plugin getBlueMap() {
return bluemap; return pluginInstance;
} }
public static BukkitPlugin getInstance() { public static BukkitPlugin getInstance() {

View File

@ -222,7 +222,7 @@ public void renderMaps() throws IOException {
while(renderManager.getRenderTaskCount() != 0) { while(renderManager.getRenderTaskCount() != 0) {
try { try {
Thread.sleep(200); Thread.sleep(200);
} catch (InterruptedException e) {} } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -390,7 +390,7 @@ public static void main(String[] args) throws IOException, ParseResourceExceptio
//wait a second to let the webserver start, looks nicer in the log //wait a second to let the webserver start, looks nicer in the log
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ignore) {} } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
} }
@ -452,7 +452,7 @@ private static void printHelp() {
filename = file.getAbsolutePath(); filename = file.getAbsolutePath();
} }
} }
} catch (Exception ex) {} } catch (IOException ex) {}
String command = "java -jar " + filename; String command = "java -jar " + filename;

View File

@ -75,7 +75,6 @@ public synchronized void stop() {
for (int i = 0; i < renderThreads.length; i++) { for (int i = 0; i < renderThreads.length; i++) {
if (renderThreads[i] != null) { if (renderThreads[i] != null) {
renderThreads[i].interrupt(); renderThreads[i].interrupt();
renderThreads[i] = null;
} }
} }
@ -141,7 +140,7 @@ public boolean removeRenderTask(RenderTask renderTask) {
private void renderThread() { private void renderThread() {
RenderTicket ticket = null; RenderTicket ticket = null;
while (!Thread.interrupted() && running) { while (running) {
synchronized (renderTickets) { synchronized (renderTickets) {
ticket = renderTickets.poll(); ticket = renderTickets.poll();
if (ticket != null) renderTicketMap.remove(ticket); if (ticket != null) renderTicketMap.remove(ticket);
@ -163,17 +162,22 @@ private void renderThread() {
if (ticket != null) { if (ticket != null) {
try { try {
ticket.render(); ticket.render();
} catch (Exception e) { } catch (RuntimeException e) {
//catch possible runtime exceptions, display them, and wait a while .. then resurrect this render-thread //catch possible runtime exceptions, display them, and wait a while .. then resurrect this render-thread
Logger.global.logError("Unexpected exception in render-thread!", e); Logger.global.logError("Unexpected exception in render-thread!", e);
try { try {
Thread.sleep(10000); Thread.sleep(10000);
} catch (InterruptedException interrupt) { break; } } catch (InterruptedException interrupt) { Thread.currentThread().interrupt(); break; }
} }
} else { } else {
try { try {
Thread.sleep(1000); // we don't need a super fast response time, so waiting a second is totally fine Thread.sleep(1000); // we don't need a super fast response time, so waiting a second is totally fine
} catch (InterruptedException interrupt) { break; } } catch (InterruptedException interrupt) { Thread.currentThread().interrupt(); break; }
}
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
break;
} }
} }
} }

View File

@ -66,7 +66,7 @@ public void onWorldSaveToDisk(final UUID world) {
} }
} }
} catch (InterruptedException ignore) {} } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
}).start(); }).start();
} }

View File

@ -262,6 +262,7 @@ public synchronized void load() throws IOException, ParseResourceException {
} }
} }
} catch (InterruptedException ex){ } catch (InterruptedException ex){
Thread.currentThread().interrupt();
return; return;
} }
}); });
@ -316,6 +317,7 @@ public synchronized void load() throws IOException, ParseResourceException {
Thread.sleep(TimeUnit.MINUTES.toMillis(30)); Thread.sleep(TimeUnit.MINUTES.toMillis(30));
} }
} catch (InterruptedException ex){ } catch (InterruptedException ex){
Thread.currentThread().interrupt();
return; return;
} }
}); });
@ -339,9 +341,13 @@ public synchronized void unload() {
//stop scheduled threads //stop scheduled threads
if (metricsThread != null) metricsThread.interrupt(); if (metricsThread != null) metricsThread.interrupt();
try {metricsThread.join(1000);} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
if (metricsThread.isAlive()) Logger.global.logWarning("The metricsThread did not terminate correctly in time!");
metricsThread = null; metricsThread = null;
if (periodicalSaveThread != null) periodicalSaveThread.interrupt(); if (periodicalSaveThread != null) periodicalSaveThread.interrupt();
try {periodicalSaveThread.join(1000);} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
if (periodicalSaveThread.isAlive()) Logger.global.logWarning("The periodicalSaveThread did not terminate correctly in time!");
periodicalSaveThread = null; periodicalSaveThread = null;
//stop services //stop services

View File

@ -60,6 +60,7 @@
import de.bluecolored.bluemap.core.mca.Chunk; import de.bluecolored.bluemap.core.mca.Chunk;
import de.bluecolored.bluemap.core.mca.ChunkAnvil112; import de.bluecolored.bluemap.core.mca.ChunkAnvil112;
import de.bluecolored.bluemap.core.mca.MCAWorld; import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
import de.bluecolored.bluemap.core.world.Block; import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.World; import de.bluecolored.bluemap.core.world.World;
@ -307,7 +308,7 @@ public int reloadCommand(CommandContext<S> context) {
source.sendMessage(Text.of(TextColor.RED, "Could not load BlueMap! See the console for details!")); source.sendMessage(Text.of(TextColor.RED, "Could not load BlueMap! See the console for details!"));
} }
} catch (Exception ex) { } catch (IOException | ParseResourceException | RuntimeException ex) {
Logger.global.logError("Failed to reload BlueMap!", ex); Logger.global.logError("Failed to reload BlueMap!", ex);
source.sendMessage(Text.of(TextColor.RED, "There was an error reloading BlueMap! See the console for details!")); source.sendMessage(Text.of(TextColor.RED, "There was an error reloading BlueMap! See the console for details!"));

View File

@ -73,7 +73,7 @@ public void update(File storageFolder) {
Logger.global.logDebug("Failed to load player-skin from mojang-servers: " + e); Logger.global.logDebug("Failed to load player-skin from mojang-servers: " + e);
} catch (IOException e) { } catch (IOException e) {
Logger.global.logError("Failed to write player-head image!", e); Logger.global.logError("Failed to write player-head image!", e);
} catch (InterruptedException ignore) {} } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
}).start(); }).start();
} }
@ -87,7 +87,7 @@ public BufferedImage createHead(BufferedImage skinTexture) {
Graphics2D g = head.createGraphics(); Graphics2D g = head.createGraphics();
g.drawImage(layer1, 0, 0, null); g.drawImage(layer1, 0, 0, null);
g.drawImage(layer2, 0, 0, null); g.drawImage(layer2, 0, 0, null);
} catch (Throwable t) { // There might be problems with headless servers when loading the graphics class } catch (Throwable t) { // There might be problems with headless servers when loading the graphics class, so we catch every exception and error on purpose here
Logger.global.noFloodWarning("headless-graphics-fail", Logger.global.noFloodWarning("headless-graphics-fail",
"Could not access Graphics2D to render player-skin texture. Try adding '-Djava.awt.headless=true' to your startup flags or ignore this warning."); "Could not access Graphics2D to render player-skin texture. Try adding '-Djava.awt.headless=true' to your startup flags or ignore this warning.");

View File

@ -142,15 +142,9 @@ private MCAWorld(
} }
public BlockState getBlockState(Vector3i pos) { public BlockState getBlockState(Vector3i pos) {
try { Vector2i chunkPos = blockToChunk(pos);
Chunk chunk = getChunk(chunkPos);
Vector2i chunkPos = blockToChunk(pos); return chunk.getBlockState(pos);
Chunk chunk = getChunk(chunkPos);
return chunk.getBlockState(pos);
} catch (Exception ex) {
return BlockState.MISSING;
}
} }
@Override @Override
@ -200,22 +194,22 @@ public Chunk getChunk(Vector2i chunkPos) {
Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunkOrEmpty(chunkPos, 2, 1000)); Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunkOrEmpty(chunkPos, 2, 1000));
return chunk; return chunk;
} catch (UncheckedExecutionException | ExecutionException e) { } catch (UncheckedExecutionException | ExecutionException e) {
if (e.getCause() instanceof InterruptedException) Thread.currentThread().interrupt();
throw new RuntimeException(e.getCause()); throw new RuntimeException(e.getCause());
} }
} }
private Chunk loadChunkOrEmpty(Vector2i chunkPos, int tries, long tryInterval) { private Chunk loadChunkOrEmpty(Vector2i chunkPos, int tries, long tryInterval) throws InterruptedException {
Exception loadException = null; Exception loadException = null;
for (int i = 0; i < tries; i++) { for (int i = 0; i < tries; i++) {
try { try {
return loadChunk(chunkPos); return loadChunk(chunkPos);
} catch (Exception e) { } catch (IOException | RuntimeException e) {
if (loadException != null) e.addSuppressed(loadException);
loadException = e; loadException = e;
if (tryInterval > 0 && i+1 < tries) { if (tryInterval > 0 && i+1 < tries) {
try { Thread.sleep(tryInterval);
Thread.sleep(tryInterval);
} catch (InterruptedException interrupt) {}
} }
} }
} }
@ -261,7 +255,7 @@ private Chunk loadChunk(Vector2i chunkPos) throws IOException {
} else { } else {
throw new IOException("Invalid data tag: " + (tag == null ? "null" : tag.getClass().getName())); throw new IOException("Invalid data tag: " + (tag == null ? "null" : tag.getClass().getName()));
} }
} catch (Exception e) { } catch (RuntimeException | IOException e) {
throw new IOException("Exception trying to load chunk (" + chunkPos + ")", e); throw new IOException("Exception trying to load chunk (" + chunkPos + ")", e);
} }
} }
@ -312,7 +306,7 @@ public Collection<Vector2i> getChunkList(long modifiedSinceMillis, Predicate<Vec
} }
} }
} }
} catch (Exception ex) { } catch (RuntimeException | IOException ex) {
Logger.global.logWarning("Failed to read .mca file: " + file.getAbsolutePath() + " (" + ex.toString() + ")"); Logger.global.logWarning("Failed to read .mca file: " + file.getAbsolutePath() + " (" + ex.toString() + ")");
} }
} }

View File

@ -37,6 +37,7 @@
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import de.bluecolored.bluemap.core.BlueMap; import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.logger.Logger;
public class Metrics { public class Metrics {
@ -53,7 +54,9 @@ public static void sendReport(String implementation) {
try { try {
sendData(data.toString()); sendData(data.toString());
} catch (Exception ex) {} } catch (IOException | RuntimeException ex) {
Logger.global.logDebug("Failed to send Metrics-Report: " + ex);
}
} }
private static String sendData(String data) throws MalformedURLException, IOException { private static String sendData(String data) throws MalformedURLException, IOException {

View File

@ -37,6 +37,7 @@
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector2i;
@ -116,6 +117,9 @@ public void save(File file, boolean force, boolean useGzip) throws IOException {
try { try {
FileUtils.waitForFile(file, 10, TimeUnit.SECONDS); FileUtils.waitForFile(file, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Failed to get write-access to file: " + file, e);
} catch (TimeoutException e) {
throw new IOException("Failed to get write-access to file: " + file, e); throw new IOException("Failed to get write-access to file: " + file, e);
} }

View File

@ -189,8 +189,8 @@ public BlockStateResource build(String blockstateFile) throws IOException {
variant.checkValid(); variant.checkValid();
blockState.variants.add(variant); blockState.variants.add(variant);
} catch (Throwable t) { } catch (ParseResourceException | RuntimeException e) {
Logger.global.logWarning("Failed to parse a variant of " + blockstateFile + ": " + t); Logger.global.logWarning("Failed to parse a variant of " + blockstateFile + ": " + e);
} }
} }
@ -208,8 +208,8 @@ public BlockStateResource build(String blockstateFile) throws IOException {
variant.checkValid(); variant.checkValid();
blockState.multipart.add(variant); blockState.multipart.add(variant);
} catch (Throwable t) { } catch (ParseResourceException | RuntimeException e) {
Logger.global.logWarning("Failed to parse a multipart-part of " + blockstateFile + ": " + t); Logger.global.logWarning("Failed to parse a multipart-part of " + blockstateFile + ": " + e);
} }
} }

View File

@ -167,13 +167,13 @@ public synchronized void loadTextureFile(File file) throws IOException, ParseRes
boolean transparent = texture.get("transparent").getAsBoolean(); boolean transparent = texture.get("transparent").getAsBoolean();
Vector4f color = readVector4f(texture.get("color").getAsJsonArray()); Vector4f color = readVector4f(texture.get("color").getAsJsonArray());
textureList.set(i, new Texture(i, path, color, transparent, EMPTY_BASE64)); textureList.set(i, new Texture(i, path, color, transparent, EMPTY_BASE64));
} catch (Exception ex) { } catch (ParseResourceException | RuntimeException ex) {
Logger.global.logWarning("Failed to load texture with id " + i + " from texture file " + file + "!"); Logger.global.logWarning("Failed to load texture with id " + i + " from texture file " + file + "!");
} }
} }
} catch (IOException ex) { } catch (IOException ex) {
throw ex; throw ex;
} catch (Exception ex) { } catch (RuntimeException ex) {
throw new ParseResourceException("Invalid texture file format!", ex); throw new ParseResourceException("Invalid texture file format!", ex);
} finally { } finally {
regenerateMap(); regenerateMap();

View File

@ -29,6 +29,7 @@
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector2i;
@ -63,14 +64,14 @@ public static File coordsToFile(Path root, Vector2i coords, String fileType){
* Blocks until a file can be read and written.<br> * Blocks until a file can be read and written.<br>
* <i>(Do not use this method to sync file-access from different threads!)</i> * <i>(Do not use this method to sync file-access from different threads!)</i>
*/ */
public static void waitForFile(File file, long time, TimeUnit unit) throws InterruptedException { public static void waitForFile(File file, long time, TimeUnit unit) throws InterruptedException, TimeoutException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
long timeout = start + TimeUnit.MILLISECONDS.convert(time, unit); long timeout = start + TimeUnit.MILLISECONDS.convert(time, unit);
long sleepTime = 1; long sleepTime = 1;
while(!file.canWrite() || !file.canRead()){ while(!file.canWrite() || !file.canRead()){
Thread.sleep(sleepTime); Thread.sleep(sleepTime);
sleepTime = (long) Math.min(Math.ceil(sleepTime * 1.5), 1000); sleepTime = (long) Math.min(Math.ceil(sleepTime * 1.5), 1000);
if (System.currentTimeMillis() > timeout) throw new InterruptedException(); if (System.currentTimeMillis() > timeout) throw new TimeoutException();
} }
} }

View File

@ -183,7 +183,7 @@ public static BlockState fromString(String serializedBlockState) throws IllegalA
String blockId = m.group(1).trim(); String blockId = m.group(1).trim();
return new BlockState(blockId, pt); return new BlockState(blockId, pt);
} catch (Exception ex) { } catch (RuntimeException ex) {
throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!"); throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!");
} }
} }

View File

@ -206,18 +206,16 @@ export default class BlueMap {
this.controls.direction = this.controls.targetDirection; this.controls.direction = this.controls.targetDirection;
this.controls.distance = this.controls.targetDistance; this.controls.distance = this.controls.targetDistance;
this.controls.angle = this.controls.targetAngle; this.controls.angle = this.controls.targetAngle;
this.controls.targetPosition.y = this.controls.minHeight;
this.controls.position.copy(this.controls.targetPosition); this.controls.position.copy(this.controls.targetPosition);
} }
} }
if (hashVars.length >= 7){ if (hashVars.length >= 7){
let height = parseInt(hashVars[6]); let height = parseInt(hashVars[6]);
if (!isNaN(height)){ if (!isNaN(height)){
this.controls.minHeight = height; this.controls.terrainHeight = height;
this.controls.targetPosition.y = height;
if (!smooth) { if (!smooth) {
this.controls.position.copy(this.controls.targetPosition); if (this.controls.position.y < this.controls.terrainHeight) this.controls.position.y = this.controls.terrainHeight;
} }
} }
} }
@ -257,7 +255,7 @@ export default class BlueMap {
+ ':' + Math.round(this.controls.targetDirection * 100) / 100 + ':' + Math.round(this.controls.targetDirection * 100) / 100
+ ':' + Math.round(this.controls.targetDistance * 100) / 100 + ':' + Math.round(this.controls.targetDistance * 100) / 100
+ ':' + Math.ceil(this.controls.targetAngle * 100) / 100 + ':' + Math.ceil(this.controls.targetAngle * 100) / 100
+ ':' + Math.floor(this.controls.targetPosition.y); + ':' + Math.floor(this.controls.terrainHeight);
// only update hash when changed // only update hash when changed
if (window.location.hash !== this.locationHash) { if (window.location.hash !== this.locationHash) {
history.replaceState(undefined, undefined, this.locationHash); history.replaceState(undefined, undefined, this.locationHash);

View File

@ -79,7 +79,7 @@ export default class Controls {
this.camera = camera; this.camera = camera;
this.element = element; this.element = element;
this.heightScene = heightScene; this.heightScene = heightScene;
this.minHeight = 0; this.terrainHeight = 70;
this.raycaster = new Raycaster(); this.raycaster = new Raycaster();
this.rayDirection = new Vector3(0, -1, 0); this.rayDirection = new Vector3(0, -1, 0);
@ -159,8 +159,8 @@ export default class Controls {
} }
resetPosition() { resetPosition() {
this.position = new Vector3(0, 70, 0); this.position = new Vector3(0, 0, 0);
this.targetPosition = new Vector3(0, 70, 0); this.targetPosition = new Vector3(0, 0, 0);
this.distance = 5000; this.distance = 5000;
this.targetDistance = 1000; this.targetDistance = 1000;
@ -177,13 +177,10 @@ export default class Controls {
let changed = false; let changed = false;
let zoomLerp = (this.distance - 100) / 200; let targetY = Math.max(this.targetPosition.y, this.terrainHeight);
if (zoomLerp < 0) zoomLerp = 0;
if (zoomLerp > 1) zoomLerp = 1;
this.targetPosition.y = 300 * zoomLerp + this.minHeight * (1 - zoomLerp);
this.position.x += (this.targetPosition.x - this.position.x) * this.settings.move.smooth; this.position.x += (this.targetPosition.x - this.position.x) * this.settings.move.smooth;
this.position.y += (this.targetPosition.y - this.position.y) * this.settings.move.smoothY; this.position.y += (targetY - this.position.y) * this.settings.move.smoothY;
this.position.z += (this.targetPosition.z - this.position.z) * this.settings.move.smooth; this.position.z += (this.targetPosition.z - this.position.z) * this.settings.move.smooth;
this.distance += (this.targetDistance - this.distance) * this.settings.zoom.smooth; this.distance += (this.targetDistance - this.distance) * this.settings.zoom.smooth;
@ -241,7 +238,7 @@ export default class Controls {
let intersects = this.raycaster.intersectObjects(tileChildren(this.targetPosition)); let intersects = this.raycaster.intersectObjects(tileChildren(this.targetPosition));
if (intersects.length > 0) { if (intersects.length > 0) {
this.minHeight = intersects[0].point.y; this.terrainHeight = intersects[0].point.y;
} }
} catch (ignore){} } catch (ignore){}
@ -251,8 +248,8 @@ export default class Controls {
this.raycaster.set(rayStart, this.rayDirection); this.raycaster.set(rayStart, this.rayDirection);
let intersects = this.raycaster.intersectObjects(tileChildren(this.camera.position)); let intersects = this.raycaster.intersectObjects(tileChildren(this.camera.position));
if (intersects.length > 0) { if (intersects.length > 0) {
if (intersects[0].point.y > this.minHeight) { if (intersects[0].point.y > this.terrainHeight) {
this.minHeight = intersects[0].point.y; this.terrainHeight = intersects[0].point.y;
} }
} }
} catch (ignore){} } catch (ignore){}

View File

@ -27,7 +27,7 @@ export default class PlayerMarker extends Marker {
if (!this.renderObject){ if (!this.renderObject){
this.iconElement = $(`<div class="marker-player"><img src="assets/playerheads/${this.player}.png" onerror="this.onerror=null;this.src='${STEVE}';"><div class="nameplate">${this.label}</div></div>`); this.iconElement = $(`<div class="marker-player"><img src="assets/playerheads/${this.player}.png" onerror="this.onerror=null;this.src='${STEVE}';"><div class="nameplate">${this.label}</div></div>`);
this.iconElement.find("img").click(this.onClick); this.iconElement.find("img").click(this.onClick);
$(window).on('mousedown touchstart', this.onStopFollowing); $(window).on('mousedown touchstart', this.onUserInput);
this.renderObject = new CSS2DObject(this.iconElement[0]); this.renderObject = new CSS2DObject(this.iconElement[0]);
this.renderObject.position.copy(this.position); this.renderObject.position.copy(this.position);
@ -47,6 +47,12 @@ export default class PlayerMarker extends Marker {
this.blueMap.hudScene.add(this.renderObject); this.blueMap.hudScene.add(this.renderObject);
} else { } else {
this.blueMap.hudScene.remove(this.renderObject); this.blueMap.hudScene.remove(this.renderObject);
if (this.follow) {
this.follow = false;
this.iconElement.removeClass("following");
this.blueMap.controls.targetPosition.y = 0;
}
} }
} }
@ -62,8 +68,7 @@ export default class PlayerMarker extends Marker {
} }
if (this.follow){ if (this.follow){
this.blueMap.controls.targetPosition.x = this.position.x; this.blueMap.controls.targetPosition.copy(this.position);
this.blueMap.controls.targetPosition.z = this.position.z;
} }
} }
}; };
@ -97,14 +102,14 @@ export default class PlayerMarker extends Marker {
this.follow = true; this.follow = true;
this.iconElement.addClass("following"); this.iconElement.addClass("following");
this.blueMap.controls.targetPosition.x = this.position.x; this.blueMap.controls.targetPosition.copy(this.position);
this.blueMap.controls.targetPosition.z = this.position.z;
}; };
onStopFollowing = event => { onUserInput = e => {
if(this.follow) { if ((e.type !== "mousedown" || e.button === 0) && this.follow) {
this.follow = true; this.follow = false;
this.iconElement.removeClass("following"); this.iconElement.removeClass("following");
this.blueMap.controls.targetPosition.y = 0;
} }
}; };

View File

@ -42,8 +42,11 @@ export default class PlayerMarkerSet {
); );
}).then((liveData) => { }).then((liveData) => {
this.updateWith(liveData) this.updateWith(liveData)
}).catch((e) => { }).catch(() => {
console.error("Failed to update player-markers!", e); this.marker.forEach(marker => {
marker.online = false;
marker.setVisible(false);
});
}); });
} }

View File

@ -114,6 +114,7 @@ public void onInitialize() {
if (pluginInstance.isLoaded()) Logger.global.logInfo("BlueMap loaded!"); if (pluginInstance.isLoaded()) Logger.global.logInfo("BlueMap loaded!");
} catch (IOException | ParseResourceException e) { } catch (IOException | ParseResourceException e) {
Logger.global.logError("Failed to load bluemap!", e); Logger.global.logError("Failed to load bluemap!", e);
pluginInstance.unload();
} }
}).start(); }).start();
}); });

View File

@ -116,6 +116,7 @@ public void onServerStarting(FMLServerStartingEvent event) {
if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!"); if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
} catch (IOException | ParseResourceException e) { } catch (IOException | ParseResourceException e) {
Logger.global.logError("Failed to load bluemap!", e); Logger.global.logError("Failed to load bluemap!", e);
pluginInstance.unload();
} }
}).start(); }).start();
} }

View File

@ -1,6 +1,7 @@
dependencies { dependencies {
shadow "org.spongepowered:spongeapi:7.2.0" shadow "org.spongepowered:spongeapi:7.2.0"
compile group: 'org.bstats', name: 'bstats-sponge-lite', version: '1.5'
compile group: 'org.bstats', name: 'bstats-sponge-lite', version: '1.7'
compile (project(':BlueMapCommon')) { compile (project(':BlueMapCommon')) {
//exclude dependencies provided by sponge //exclude dependencies provided by sponge

View File

@ -116,7 +116,9 @@ public List<String> getSuggestions(CommandSource source, String arguments, Locat
completions.add(text); completions.add(text);
} }
} }
} catch (InterruptedException | ExecutionException | TimeoutException ignore) {} } catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException ignore) {}
completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
return completions; return completions;

View File

@ -58,6 +58,7 @@
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
import de.bluecolored.bluemap.sponge.SpongeCommands.SpongeCommandProxy; import de.bluecolored.bluemap.sponge.SpongeCommands.SpongeCommandProxy;
import net.querz.nbt.CompoundTag; import net.querz.nbt.CompoundTag;
import net.querz.nbt.NBTUtil; import net.querz.nbt.NBTUtil;
@ -74,11 +75,7 @@ public class SpongePlugin implements ServerInterface {
@ConfigDir(sharedRoot = false) @ConfigDir(sharedRoot = false)
private Path configurationDir; private Path configurationDir;
@SuppressWarnings("unused") private Plugin pluginInstance;
@Inject
private MetricsLite2 metrics;
private Plugin bluemap;
private SpongeCommands commands; private SpongeCommands commands;
private SpongeExecutorService asyncExecutor; private SpongeExecutorService asyncExecutor;
@ -88,14 +85,17 @@ public class SpongePlugin implements ServerInterface {
private List<SpongePlayer> onlinePlayerList; private List<SpongePlayer> onlinePlayerList;
@Inject @Inject
public SpongePlugin(org.slf4j.Logger logger) { public SpongePlugin(org.slf4j.Logger logger, MetricsLite2.Factory bstatsFactory) {
Logger.global = new Slf4jLogger(logger); Logger.global = new Slf4jLogger(logger);
this.onlinePlayerMap = new ConcurrentHashMap<>(); this.onlinePlayerMap = new ConcurrentHashMap<>();
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>()); this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
this.bluemap = new Plugin("sponge", this); this.pluginInstance = new Plugin("sponge", this);
this.commands = new SpongeCommands(bluemap); this.commands = new SpongeCommands(pluginInstance);
//init bstats metrics
bstatsFactory.make(5911);
} }
@Listener @Listener
@ -121,10 +121,11 @@ public void onServerStart(GameStartingServerEvent evt) {
asyncExecutor.execute(() -> { asyncExecutor.execute(() -> {
try { try {
Logger.global.logInfo("Loading..."); Logger.global.logInfo("Loading...");
bluemap.load(); pluginInstance.load();
if (bluemap.isLoaded()) Logger.global.logInfo("Loaded!"); if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
} catch (Throwable t) { } catch (IOException | ParseResourceException | RuntimeException e) {
Logger.global.logError("Failed to load!", t); Logger.global.logError("Failed to load!", e);
pluginInstance.unload();
} }
}); });
} }
@ -133,7 +134,7 @@ public void onServerStart(GameStartingServerEvent evt) {
public void onServerStop(GameStoppingEvent evt) { public void onServerStop(GameStoppingEvent evt) {
Logger.global.logInfo("Stopping..."); Logger.global.logInfo("Stopping...");
Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel()); Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel());
bluemap.unload(); pluginInstance.unload();
Logger.global.logInfo("Saved and stopped!"); Logger.global.logInfo("Saved and stopped!");
} }
@ -142,15 +143,15 @@ public void onServerReload(GameReloadEvent evt) {
asyncExecutor.execute(() -> { asyncExecutor.execute(() -> {
try { try {
Logger.global.logInfo("Reloading..."); Logger.global.logInfo("Reloading...");
bluemap.reload(); pluginInstance.reload();
Logger.global.logInfo("Reloaded!"); Logger.global.logInfo("Reloaded!");
} catch (Exception e) { } catch (IOException | ParseResourceException | RuntimeException e) {
Logger.global.logError("Failed to load!", e); Logger.global.logError("Failed to load!", e);
pluginInstance.unload();
} }
}); });
} }
@Listener @Listener
public void onPlayerJoin(ClientConnectionEvent.Join evt) { public void onPlayerJoin(ClientConnectionEvent.Join evt) {
SpongePlayer player = new SpongePlayer(evt.getTargetEntity()); SpongePlayer player = new SpongePlayer(evt.getTargetEntity());
@ -186,8 +187,8 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException {
long most = spongeData.getLong("UUIDMost"); long most = spongeData.getLong("UUIDMost");
long least = spongeData.getLong("UUIDLeast"); long least = spongeData.getLong("UUIDLeast");
return new UUID(most, least); return new UUID(most, least);
} catch (Throwable t) { } catch (IOException | RuntimeException e) {
throw new IOException("Failed to read level_sponge.dat", t); throw new IOException("Failed to read level_sponge.dat", e);
} }
} }

0
logs/latest.log Normal file
View File