From d975b51b77d26ae1ee56a064945d084bc7573596 Mon Sep 17 00:00:00 2001 From: Mysticdrew Date: Fri, 8 Mar 2024 16:14:06 -0600 Subject: [PATCH] migrated the new webmap --- dependencies.gradle | 7 + gradle.properties | 4 +- repositories.gradle | 14 + .../java/journeymap/client/Constants.java | 9 +- .../journeymap/client/JourneymapClient.java | 8 +- .../journeymap/client/io/FileHandler.java | 21 +- .../java/journeymap/client/log/ChatLog.java | 4 +- .../journeymap/client/model/EntityDTO.java | 6 +- .../client/ui/dialog/OptionsManager.java | 10 +- .../journeymap/client/webmap/Resources.java | 15 + .../java/journeymap/client/webmap/WebMap.java | 193 ++ .../client/webmap/enums/WebmapStatus.java | 22 + .../journeymap/client/webmap/routes/Data.java | 89 + .../journeymap/client/webmap/routes/Logs.java | 38 + .../client/webmap/routes/Polygons.java | 21 + .../client/webmap/routes/Properties.java | 48 + .../client/webmap/routes/Resource.java | 108 ++ .../journeymap/client/webmap/routes/Skin.java | 42 + .../client/webmap/routes/Status.java | 52 + .../client/webmap/routes/Tiles.java | 131 ++ .../java/journeymap/common/Journeymap.java | 10 +- .../client/service/webmap/Webmap.kt | 130 -- .../webmap/kotlin/enums/WebmapStatus.kt | 10 - .../client/service/webmap/kotlin/routes.kt | 31 - .../service/webmap/kotlin/routes/action.kt | 147 -- .../service/webmap/kotlin/routes/data.kt | 68 - .../service/webmap/kotlin/routes/log.kt | 32 - .../webmap/kotlin/routes/properties.kt | 45 - .../service/webmap/kotlin/routes/resources.kt | 68 - .../service/webmap/kotlin/routes/skin.kt | 37 - .../service/webmap/kotlin/routes/status.kt | 44 - .../service/webmap/kotlin/routes/tiles.kt | 131 -- .../common/kotlin/extensions/resources.kt | 10 - .../assets/journeymap/web/css/journeymap.css | 285 --- .../assets/journeymap/web/index.html | 94 - .../assets/journeymap/web/js/journeymap.js | 1677 ----------------- .../journeymap/web/js/jquery.rotate.min.js | 22 - .../web/js/markerwithlabel_packed.js | 1 - .../journeymap/web/js/paintbrush.min.js | 4 - .../journeymap/web/js/richmarker-compiled.js | 20 - 40 files changed, 829 insertions(+), 2879 deletions(-) create mode 100644 repositories.gradle create mode 100644 src/main/java/journeymap/client/webmap/Resources.java create mode 100644 src/main/java/journeymap/client/webmap/WebMap.java create mode 100644 src/main/java/journeymap/client/webmap/enums/WebmapStatus.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Data.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Logs.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Polygons.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Properties.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Resource.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Skin.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Status.java create mode 100644 src/main/java/journeymap/client/webmap/routes/Tiles.java delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/Webmap.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/enums/WebmapStatus.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/action.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/data.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/log.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/properties.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/resources.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/skin.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/status.kt delete mode 100644 src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/tiles.kt delete mode 100644 src/main/kotlin/journeymap/common/kotlin/extensions/resources.kt delete mode 100644 src/main/resources/assets/journeymap/web/css/journeymap.css delete mode 100644 src/main/resources/assets/journeymap/web/index.html delete mode 100644 src/main/resources/assets/journeymap/web/js/journeymap.js delete mode 100644 src/main/resources/assets/journeymap/web/js/jquery.rotate.min.js delete mode 100644 src/main/resources/assets/journeymap/web/js/markerwithlabel_packed.js delete mode 100644 src/main/resources/assets/journeymap/web/js/paintbrush.min.js delete mode 100644 src/main/resources/assets/journeymap/web/js/richmarker-compiled.js diff --git a/dependencies.gradle b/dependencies.gradle index 624c487..4b56a01 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,4 +34,11 @@ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { +// shadowImplementation("ar.com.hjg:pngj:2.1.0") //TODO: remove the code and use the dependency instead + shadowImplementation("javax.servlet:javax.servlet-api:4.0.1") + shadowImplementation("info.journeymap:webmap-client:0.8.5-SNAPSHOT") + shadowImplementation("io.javalin:javalin:4.6.8") + + implementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.8.0-beta4' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.8.0-beta4' } diff --git a/gradle.properties b/gradle.properties index ad6243a..b53f5f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -102,11 +102,11 @@ forceEnableMixins = false # If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your # responsibility to check the license and request permission for distribution if required. -usesShadowedDependencies = false +usesShadowedDependencies = true # If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access # their own classes, making the minimization unreliable. -minimizeShadowedDependencies = true +minimizeShadowedDependencies = false # If disabled, won't rename the shadowed classes. relocateShadowedDependencies = true diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 0000000..6b1d621 --- /dev/null +++ b/repositories.gradle @@ -0,0 +1,14 @@ +// Add any additional repositories for your dependencies here + +repositories { + mavenCentral() + + maven { + name = "JourneyMap" + url = "https://jm.gserv.me/repository/maven-snapshots/" + } + maven { + name = "jitpack" + url = "https://jitpack.io" + } +} diff --git a/src/main/java/journeymap/client/Constants.java b/src/main/java/journeymap/client/Constants.java index 232f8f8..dccc1f9 100644 --- a/src/main/java/journeymap/client/Constants.java +++ b/src/main/java/journeymap/client/Constants.java @@ -19,7 +19,12 @@ import org.lwjgl.input.Keyboard; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; // 1.8 //import net.minecraftforge.fml.common.Loader; @@ -59,6 +64,8 @@ public class Constants public static String WAYPOINT_ICON_DIR = path.join(ICON_DIR, "waypoint", END); public static String THEME_ICON_DIR = path.join(ICON_DIR, "theme", END); + public static String WEB_DIR = path.join(JOURNEYMAP_DIR, "web", END); + // Network Channel IDs /** diff --git a/src/main/java/journeymap/client/JourneymapClient.java b/src/main/java/journeymap/client/JourneymapClient.java index 9c0bf2e..01261fa 100644 --- a/src/main/java/journeymap/client/JourneymapClient.java +++ b/src/main/java/journeymap/client/JourneymapClient.java @@ -29,7 +29,6 @@ import journeymap.client.network.WorldInfoHandler; import journeymap.client.properties.*; import journeymap.client.render.map.TileDrawStepCache; -import journeymap.client.service.webmap.Webmap; import journeymap.client.task.main.IMainThreadTask; import journeymap.client.task.main.MainTaskController; import journeymap.client.task.main.MappingMonitorTask; @@ -38,6 +37,7 @@ import journeymap.client.ui.UIManager; import journeymap.client.ui.fullscreen.Fullscreen; import journeymap.client.waypoint.WaypointStore; +import journeymap.client.webmap.WebMap; import journeymap.common.CommonProxy; import journeymap.common.Journeymap; import journeymap.common.version.VersionCheck; @@ -309,7 +309,7 @@ public void postInitialize(FMLPostInitializationEvent event) // Webserver if (webMapProperties.enabled.get()) { - Webmap.INSTANCE.start(); + WebMap.getInstance().start(); } initialized = true; @@ -387,9 +387,9 @@ public Boolean isThreadLogging() * * @return */ - public Webmap getJmServer() + public WebMap getJmServer() { - return Webmap.INSTANCE; + return WebMap.getInstance(); } /** diff --git a/src/main/java/journeymap/client/io/FileHandler.java b/src/main/java/journeymap/client/io/FileHandler.java index af0c830..2e20967 100644 --- a/src/main/java/journeymap/client/io/FileHandler.java +++ b/src/main/java/journeymap/client/io/FileHandler.java @@ -11,6 +11,7 @@ import com.google.common.io.ByteSource; import com.google.common.io.Files; import com.google.gson.GsonBuilder; +import cpw.mods.fml.client.FMLClientHandler; import journeymap.client.Constants; import journeymap.client.JourneymapClient; import journeymap.client.data.WorldData; @@ -39,15 +40,29 @@ public class FileHandler { + public static final String DEV_MINECRAFT_DIR = "run/"; public static final String ASSETS_JOURNEYMAP = "/assets/journeymap"; public static final String ASSETS_WEBMAP = "/assets/journeymap/web"; - public static final String ASSETS_JOURNEYMAP_UI = "/assets/journeymap/web/img/ico"; + public static final String ASSETS_JOURNEYMAP_UI = "/assets/journeymap/web/img/"; public static final File MinecraftDirectory = ForgeHelper.INSTANCE.getClient().mcDataDir; public static final File JourneyMapDirectory = new File(MinecraftDirectory, Constants.JOURNEYMAP_DIR); public static final File StandardConfigDirectory = new File(MinecraftDirectory, Constants.CONFIG_DIR); private static WorldClient theLastWorld; + public static File getMinecraftDirectory() + { + Minecraft minecraft = FMLClientHandler.instance().getClient(); + if (minecraft != null) + { + return minecraft.mcDataDir; + } + else + { + return new File(DEV_MINECRAFT_DIR); + } + } + public static File getMCWorldDir(Minecraft minecraft) { if (minecraft.isIntegratedServerRunning()) @@ -551,7 +566,7 @@ public static void open(File file) } } - public static void copyResources(File targetDirectory, String assetsPath, String setName, boolean overwrite) + public static boolean copyResources(File targetDirectory, String assetsPath, String setName, boolean overwrite) { String fromPath = null; File toDir = null; @@ -574,11 +589,13 @@ public static void copyResources(File targetDirectory, String assetsPath, String fromPath = fromDir.getPath(); FileHandler.copyFromDirectory(fromDir, toDir, overwrite); } + return true; } catch (Throwable t) { Journeymap.getLogger().error(String.format("Couldn't unzip resource set from %s to %s: %s", fromPath, toDir, t)); } + return false; } /** diff --git a/src/main/java/journeymap/client/log/ChatLog.java b/src/main/java/journeymap/client/log/ChatLog.java index 40d16c3..89ee1d5 100644 --- a/src/main/java/journeymap/client/log/ChatLog.java +++ b/src/main/java/journeymap/client/log/ChatLog.java @@ -7,7 +7,7 @@ import journeymap.client.Constants; import journeymap.client.JourneymapClient; -import journeymap.client.service.webmap.Webmap; +import journeymap.client.webmap.WebMap; import journeymap.common.Journeymap; import journeymap.common.version.VersionCheck; import net.minecraft.client.Minecraft; @@ -156,7 +156,7 @@ public static void announceMod(boolean forced) { try { - Webmap webServer = JourneymapClient.getInstance().getJmServer(); + WebMap webServer = JourneymapClient.getInstance().getJmServer(); String keyName = Constants.getKeyName(Constants.KB_MAP); String port = webServer.getPort() == 80 ? "" : ":" + webServer.getPort(); String message = Constants.getString("jm.common.webserver_and_mapgui_ready", keyName, port); //$NON-NLS-1$ diff --git a/src/main/java/journeymap/client/model/EntityDTO.java b/src/main/java/journeymap/client/model/EntityDTO.java index ef040e3..c3a98d9 100644 --- a/src/main/java/journeymap/client/model/EntityDTO.java +++ b/src/main/java/journeymap/client/model/EntityDTO.java @@ -49,6 +49,7 @@ public class EntityDTO implements Serializable public boolean sneaking; public boolean passiveAnimal; + private EntityDTO(EntityLivingBase entity) { this.entityLivingRef = new WeakReference(entity); @@ -109,11 +110,8 @@ else if (entity instanceof IEntityOwnable) } else if (entity instanceof EntityHorse) { - // TODO: Test this with and without owners - // 1.8 String ownerUuidString = ((EntityHorse) entity).func_152119_ch(); - // 1.8.8 - // String ownerUuidString = ((EntityHorse) entity).getOwnerId(); + if (!Strings.isNullOrEmpty(ownerUuidString)) { try diff --git a/src/main/java/journeymap/client/ui/dialog/OptionsManager.java b/src/main/java/journeymap/client/ui/dialog/OptionsManager.java index 77ba68f..a999cf2 100644 --- a/src/main/java/journeymap/client/ui/dialog/OptionsManager.java +++ b/src/main/java/journeymap/client/ui/dialog/OptionsManager.java @@ -17,7 +17,6 @@ import journeymap.client.properties.config.Config; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.TileDrawStepCache; -import journeymap.client.service.webmap.Webmap; import journeymap.client.task.main.SoftResetTask; import journeymap.client.task.multi.MapPlayerTask; import journeymap.client.task.multi.RenderSpec; @@ -29,6 +28,7 @@ import journeymap.client.ui.option.OptionSlotFactory; import journeymap.client.ui.option.SlotMetadata; import journeymap.client.waypoint.WaypointStore; +import journeymap.client.webmap.WebMap; import journeymap.common.Journeymap; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -677,11 +677,11 @@ protected void closeAndReturn() DataCache.instance().resetRadarCaches(); if (JourneymapClient.getWebMapProperties().enabled.get()) { - Webmap.INSTANCE.start(); + WebMap.getInstance().start(); } else { - Webmap.INSTANCE.stop(); + WebMap.getInstance().stop(); } ChatLog.announceMod(true); @@ -709,11 +709,11 @@ protected void closeAndReturn() SoftResetTask.queue(); if (JourneymapClient.getWebMapProperties().enabled.get()) { - Webmap.INSTANCE.start(); + WebMap.getInstance().start(); } else { - Webmap.INSTANCE.stop(); + WebMap.getInstance().stop(); } break; } diff --git a/src/main/java/journeymap/client/webmap/Resources.java b/src/main/java/journeymap/client/webmap/Resources.java new file mode 100644 index 0000000..25e0c5d --- /dev/null +++ b/src/main/java/journeymap/client/webmap/Resources.java @@ -0,0 +1,15 @@ +package journeymap.client.webmap; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +import java.io.IOException; +import java.io.InputStream; + +public class Resources +{ + public static InputStream getResourceAsStream(ResourceLocation resourceLocation) throws IOException + { + return Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(); + } +} diff --git a/src/main/java/journeymap/client/webmap/WebMap.java b/src/main/java/journeymap/client/webmap/WebMap.java new file mode 100644 index 0000000..fcfb960 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/WebMap.java @@ -0,0 +1,193 @@ +package journeymap.client.webmap; + +import io.javalin.Javalin; +import io.javalin.http.ContentType; +import io.javalin.http.staticfiles.Location; +import journeymap.client.Constants; +import journeymap.client.JourneymapClient; +import journeymap.client.io.FileHandler; +import journeymap.client.webmap.routes.Data; +import journeymap.client.webmap.routes.Logs; +import journeymap.client.webmap.routes.Polygons; +import journeymap.client.webmap.routes.Properties; +import journeymap.client.webmap.routes.Resource; +import journeymap.client.webmap.routes.Skin; +import journeymap.client.webmap.routes.Status; +import journeymap.client.webmap.routes.Tiles; +import journeymap.common.Journeymap; +import net.minecraft.util.ResourceLocation; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; + +public class WebMap +{ + public static final Logger logger = Journeymap.getLogger(); + private int port = 0; + private boolean started = false; + private Javalin app; + + private static WebMap instance; + + + public static WebMap getInstance() + { + if (instance == null) + { + instance = new WebMap(); + } + return instance; + } + + public void start() + { + if (!started) + { + findPort(true); + initialise(); + started = true; + logger.info("Webmap is now listening on port: {}.", port); + } + } + + private void initialise() + { + try + { + app = Javalin.create(config -> { + String assetsRootProperty = System.getProperty("journeymap.webmap.assets_root", null); + File testFile = new File("../src/main/resources" + FileHandler.ASSETS_WEBMAP); + + if (assetsRootProperty != null) + { + logger.info("Detected 'journeymap.webmap.assets_root' property, serving static files from: {}", assetsRootProperty); + config.addStaticFiles(assetsRootProperty, Location.EXTERNAL); + if (testFile.exists()) + { + try + { + String assets = testFile.getCanonicalPath(); + logger.info("Development environment detected, serving static files from the filesystem.: {}", assets); + config.addStaticFiles(testFile.getCanonicalPath(), Location.EXTERNAL); + } + catch (IOException e) + { + logger.error("Webmap error finding local assets path", e); + } + } + } + else + { + File dir = new File(FileHandler.getMinecraftDirectory(), Constants.WEB_DIR); + if (!dir.exists()) + { + ResourceLocation location = new ResourceLocation(Journeymap.MOD_ID, "web"); + String assetPath = String.format("/assets/%s/%s", location.getResourceDomain(), location.getResourcePath()); + logger.info("Attempting to copy web content to {}", dir); + boolean created = FileHandler.copyResources(dir, assetPath, "", false); + logger.info("Web content copied successfully: {}", created); + } + + if (dir.exists()) + { + logger.info("Loading web content from local: {}", dir.getPath()); + config.addStaticFiles(dir.getPath(), Location.EXTERNAL); + } + else + { + logger.info("Loading web content from jar: {}", FileHandler.ASSETS_WEBMAP); + config.addStaticFiles(FileHandler.ASSETS_WEBMAP, Location.CLASSPATH); + } + } + + }).before(ctx -> { + ctx.header("Access-Control-Allow-Origin", "*"); + ctx.header("Cache-Control", "no-cache"); + }) + .get("/data/{type}", Data::get) + .get("/logs", Logs::get) + .get("/properties", Properties::get) + .get("/resources", Resource::get) + .get("/skin/{uuid}", Skin::get) + .get("/status", Status::get) + .get("/tiles/tile.png", Tiles::get) + .get("/polygons", Polygons::get) + .post("/properties", Properties::post) + .start(); + + } + catch (Exception e) + { + logger.error("Failed to start server:", e); + stop(); + } + } + + public void stop() + { + if (started) + { + app.stop(); + started = false; + logger.info("Webmap stopped."); + } + } + + private void findPort(boolean tryCurrentPort) + { + if (port == 0) + { + // the client may be null due to class loading issues in dev + // this just suppresses the exception in dev. it does not fix the class loading issue or the webmap + if (JourneymapClient.getInstance() == null || JourneymapClient.getWebMapProperties() == null) + { + port = 8080; + } + else + { + // We set this here because we need to get it again if the user changes the setting + port = JourneymapClient.getWebMapProperties().port.get(); + logger.info("port found, set to {}", port); + } + } + + if (tryCurrentPort) + { + try + { + ServerSocket socket = new ServerSocket(port); + port = socket.getLocalPort(); + socket.close(); + } + catch (IOException e) + { + logger.warn("Configured port {} could not be bound: ", port, e); + findPort(false); + } + + logger.info("Configured port {} is available.", port); + } + else + { + try + { + ServerSocket socket = new ServerSocket(0); + port = socket.getLocalPort(); + socket.close(); + logger.info("New port {} assigned by ServerSocket.", port); + } + catch (IOException e) + { + logger.error("Configured port {} could not be bound on second attempt, failing: ", port, e); + stop(); + } + } + } + + public int getPort() + { + return port; + } +} diff --git a/src/main/java/journeymap/client/webmap/enums/WebmapStatus.java b/src/main/java/journeymap/client/webmap/enums/WebmapStatus.java new file mode 100644 index 0000000..ce5d8ba --- /dev/null +++ b/src/main/java/journeymap/client/webmap/enums/WebmapStatus.java @@ -0,0 +1,22 @@ +package journeymap.client.webmap.enums; + +public enum WebmapStatus +{ + READY("ready"), + DISABLED("disabled"), + + NO_WORLD("no_world"), + STARTING("starting"); + + private final String status; + + WebmapStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Data.java b/src/main/java/journeymap/client/webmap/routes/Data.java new file mode 100644 index 0000000..bf6ab70 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Data.java @@ -0,0 +1,89 @@ +package journeymap.client.webmap.routes; + +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.data.DataCache; +import journeymap.client.data.ImagesData; +import journeymap.client.model.Waypoint; +import journeymap.common.Journeymap; +import org.apache.logging.log4j.Logger; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Data +{ + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private static final Logger logger = Journeymap.getLogger(); + private static final List dataTypesRequiringSince = Lists.newArrayList("all", "images"); + + public static void get(Context ctx) + { + String since = ctx.queryParam("images.since"); + String type = ctx.pathParam("type"); + if (dataTypesRequiringSince.contains(type) && since == null) + { + logger.warn("Data type '" + type + "' requested without 'images.since' parameter"); + ctx.status(400); + ctx.result("Data type '" + type + "' requires 'images.since' parameter."); + return; + } + + long sinceTime = since == null ? 0 : Long.parseLong(since); + Object data = null; + switch (type) + { + case "all": + data = DataCache.instance().getAll(sinceTime); + break; + case "animals": + data = DataCache.instance().getAnimals(false); + break; + case "mobs": + data = DataCache.instance().getMobs(false); + break; + case "images": + data = new ImagesData(sinceTime); + break; + case "messages": + data = DataCache.instance().getMessages(false); + break; + case "player": + data = DataCache.instance().getPlayer(false); + break; + case "players": + data = DataCache.instance().getPlayers(false); + break; + case "world": + data = DataCache.instance().getWorld(false); + break; + case "villagers": + data = DataCache.instance().getVillagers(false); + break; + case "waypoints": + Collection waypoints = DataCache.instance().getWaypoints(false); + Map wpMap = new HashMap<>(); + for (Waypoint waypoint : waypoints) + { + wpMap.put(waypoint.getId(), waypoint); + } + data = wpMap; + break; + default: + break; + } + if (data == null) + { + logger.warn("Unknown data type '" + type + "'"); + ctx.status(400); + ctx.result("Unknown data type '" + type + "'"); + } + ctx.contentType(ContentType.APPLICATION_JSON); + ctx.result(GSON.toJson(data)); + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Logs.java b/src/main/java/journeymap/client/webmap/routes/Logs.java new file mode 100644 index 0000000..d113064 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Logs.java @@ -0,0 +1,38 @@ +package journeymap.client.webmap.routes; + +import io.javalin.http.Context; +import journeymap.client.log.JMLogger; +import journeymap.client.webmap.WebMap; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class Logs +{ + public static void get(Context ctx) + { + File file = JMLogger.getLogFile(); + + if (file.exists()) + { + try + { + ctx.res.addHeader("Content-Disposition", "inline; filename=\"journeymap.log\""); + ctx.res.getOutputStream().write(Files.readAllBytes(file.toPath())); + ctx.res.getOutputStream().flush(); + } + catch (IOException e) + { + WebMap.logger.error("Failed to read log file: ", e); + } + + } + else + { + WebMap.logger.warn("Unable to find JourneyMap logfile"); + ctx.status(404); + ctx.result("Not found:" + file.getPath()); + } + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Polygons.java b/src/main/java/journeymap/client/webmap/routes/Polygons.java new file mode 100644 index 0000000..f94c4f2 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Polygons.java @@ -0,0 +1,21 @@ +package journeymap.client.webmap.routes; + +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.javalin.http.ContentType; +import io.javalin.http.Context; + +import java.util.List; + +public class Polygons +{ + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + public static void get(Context ctx) + { + List data = Lists.newArrayList(); + ctx.contentType(ContentType.JSON); + ctx.result(GSON.toJson(data)); + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Properties.java b/src/main/java/journeymap/client/webmap/routes/Properties.java new file mode 100644 index 0000000..2cd3192 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Properties.java @@ -0,0 +1,48 @@ +package journeymap.client.webmap.routes; + +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.JourneymapClient; +import journeymap.client.properties.WebMapProperties; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +public class Properties +{ + private static WebMapProperties webMapProperties = JourneymapClient.getWebMapProperties(); + private static Map propertiesMap = null; + + public static void get(Context ctx) + { + ctx.contentType(ContentType.APPLICATION_JSON); + ctx.result(JourneymapClient.getWebMapProperties().toJsonString()); + } + + public static void post(Context ctx) + { + if (propertiesMap == null || propertiesMap.isEmpty()) + { + WebMapProperties properties = JourneymapClient.getWebMapProperties(); + Map propMap = new HashMap<>(); + propMap.put("showGrid", properties.showGrid); + propMap.put("showSelf", properties.showSelf); + propMap.put("showWaypoints", properties.showWaypoints); + propertiesMap = propMap; + } + for (String key : ctx.queryParamMap().keySet()) + { + if (propertiesMap.containsKey(key)) + { + AtomicBoolean property = propertiesMap.get(key); + if (property == null) + { + throw new NullPointerException("Properties value for " + key + " is null"); + } + property.set(Boolean.parseBoolean(ctx.queryParam(key))); + } + } + webMapProperties.save(); + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Resource.java b/src/main/java/journeymap/client/webmap/routes/Resource.java new file mode 100644 index 0000000..a597691 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Resource.java @@ -0,0 +1,108 @@ +package journeymap.client.webmap.routes; + +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.JourneymapClient; +import journeymap.client.io.FileHandler; +import journeymap.client.io.IconSetFileHandler; +import journeymap.client.render.texture.TextureCache; +import journeymap.client.webmap.Resources; +import journeymap.client.webmap.WebMap; +import journeymap.common.Journeymap; +import net.minecraft.util.ResourceLocation; +import org.apache.logging.log4j.Logger; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import static journeymap.client.io.FileHandler.ASSETS_JOURNEYMAP_UI; + +public class Resource +{ + public static final Logger logger = Journeymap.getLogger(); + + public static void get(Context ctx) + { + BufferedImage img; + String resource = ctx.queryParam("resource"); + if (resource == null || resource.equals("undefined")) + { + return; + } + + ResourceLocation resourceLocation = new ResourceLocation(resource); + String extension = resource.split("\\.").length > 1 ? resource.split("\\.")[resource.split("\\.").length - 1] : ""; + if (extension.contains(":")) + { + // So we can actually get the filetype from extension + extension = extension.split(":")[0]; + } + try + { + if (!resourceLocation.getResourceDomain().contains("journeymap")) + { + img = TextureCache.instance().getEntityIconTexture(JourneymapClient.getWebMapProperties().getEntityIconSetName().get(), resource).getImage(); + + InputStream is = FileHandler.getIconStream(IconSetFileHandler.ASSETS_JOURNEYMAP_ICON_ENTITY, JourneymapClient.getWebMapProperties().getEntityIconSetName().get(), resource); + if (img == null && is != null) + { + + ctx.contentType(ContentType.IMAGE_PNG); + ctx.result(is); + return; + } + } + else + { + img = ImageIO.read(Resources.getResourceAsStream(resourceLocation)); + } + } + catch (FileNotFoundException e) + { + logger.warn("File at resource location not found: " + resource); + ctx.status(404); + try + { + img = ImageIO.read(WebMap.class.getResource(ASSETS_JOURNEYMAP_UI + "marker-dot-32.png")); + } + catch (Exception ex) + { + logger.warn("image not found {}", ASSETS_JOURNEYMAP_UI + "marker-dot-32.png"); + return; + } + } + catch (IOException e) + { + logger.info("Connection closed while writing image response. Webmap probably reloaded."); + return; + } + catch (Exception e) + { + logger.error("Exception thrown while retrieving resource at location: " + resource, e); + ctx.status(500); + try + { + img = ImageIO.read(WebMap.class.getResource(ASSETS_JOURNEYMAP_UI + "marker-dot-32.png")); + } + catch (Exception ex) + { + logger.warn("image not found {}", ASSETS_JOURNEYMAP_UI + "marker-dot-32.png"); + return; + } + } + ctx.contentType("image/" + extension); + try + { + ImageIO.write(img, extension, ctx.res.getOutputStream()); + ctx.res.getOutputStream().flush(); + } + catch (Exception e) + { + logger.warn("image not found {}", resource); + } + + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Skin.java b/src/main/java/journeymap/client/webmap/routes/Skin.java new file mode 100644 index 0000000..29fd544 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Skin.java @@ -0,0 +1,42 @@ +package journeymap.client.webmap.routes; + +import cpw.mods.fml.relauncher.ReflectionHelper; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.render.texture.TextureCache; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiPlayerInfo; +import net.minecraft.client.network.NetHandlerPlayClient; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.util.Map; + +public class Skin +{ + public static void get(Context ctx) + { + + Map netHandlerGui = ReflectionHelper.getPrivateValue(NetHandlerPlayClient.class, Minecraft.getMinecraft().getNetHandler(), "field_147310_i", "playerInfoMap"); + String username = netHandlerGui.get(ctx.queryParam("uuid")).name; + BufferedImage img; + if (username == null) + { + img = new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB); + } + else + { + img = TextureCache.instance().getPlayerSkin(username).getImage(); + } + try + { + ctx.contentType(ContentType.IMAGE_PNG); + ImageIO.write(img, "png", ctx.res.getOutputStream()); + ctx.res.getOutputStream().flush(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Status.java b/src/main/java/journeymap/client/webmap/routes/Status.java new file mode 100644 index 0000000..3c99051 --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Status.java @@ -0,0 +1,52 @@ +package journeymap.client.webmap.routes; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.JourneymapClient; +import journeymap.client.model.MapState; +import journeymap.client.ui.minimap.MiniMap; +import journeymap.client.webmap.enums.WebmapStatus; +import net.minecraft.client.Minecraft; + +import java.util.HashMap; +import java.util.Map; + +public class Status +{ + private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + public static void get(Context ctx) + { + Map data = new HashMap<>(); + WebmapStatus status; + if (Minecraft.getMinecraft().theWorld == null) + { + status = WebmapStatus.NO_WORLD; + } + else if (!JourneymapClient.getInstance().isMapping()) + { + status = WebmapStatus.STARTING; + } + else + { + status = WebmapStatus.READY; + } + if (status == WebmapStatus.READY) + { + MapState mapState = MiniMap.state(); + data.put("mapType", mapState.getCurrentMapType().name()); + Map allowedMapTypes = new HashMap<>(); + allowedMapTypes.put("cave", mapState.isCaveMappingAllowed()); + if (allowedMapTypes.values().stream().noneMatch(Boolean::booleanValue)) + { + status = WebmapStatus.DISABLED; + } + data.put("allowedMapTypes", allowedMapTypes); + } + ctx.contentType(ContentType.APPLICATION_JSON); + data.put("status", status.getStatus()); + ctx.result(gson.toJson(data)); + } +} diff --git a/src/main/java/journeymap/client/webmap/routes/Tiles.java b/src/main/java/journeymap/client/webmap/routes/Tiles.java new file mode 100644 index 0000000..99300df --- /dev/null +++ b/src/main/java/journeymap/client/webmap/routes/Tiles.java @@ -0,0 +1,131 @@ +package journeymap.client.webmap.routes; + +import cpw.mods.fml.client.FMLClientHandler; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import journeymap.client.JourneymapClient; +import journeymap.client.data.WorldData; +import journeymap.client.io.FileHandler; +import journeymap.client.io.RegionImageHandler; +import journeymap.client.model.MapType; +import journeymap.client.render.map.Tile; +import journeymap.common.Journeymap; +import net.minecraft.client.Minecraft; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import org.apache.logging.log4j.Logger; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; + +public class Tiles +{ + private static final Logger logger = Journeymap.getLogger(); + + public static void get(Context ctx) + { + int x = ctx.queryParam("x") == null ? 0 : Integer.parseInt(ctx.queryParam("x")); + Integer y = ctx.queryParam("y") == null ? null : Integer.parseInt(ctx.queryParam("y")); + int z = ctx.queryParam("z") == null ? 0 : Integer.parseInt(ctx.queryParam("z")); + int dimension = ctx.queryParam("dimension") == null ? 0 : Integer.parseInt(ctx.queryParam("dimension")); + String mapTypeString = ctx.queryParam("mapTypeString") == null ? MapType.Name.day.name() : ctx.queryParam("mapTypeString"); + int zoom = ctx.queryParam("zoom") == null ? 0 : Integer.parseInt(ctx.queryParam("zoom")); + + Minecraft minecraft = FMLClientHandler.instance().getClient(); + + World world = minecraft.theWorld; + if (world == null) + { + logger.warn("Tiles requested before world loaded"); + ctx.status(400); + ctx.result("World not loaded"); + } + if (!JourneymapClient.getInstance().isMapping()) + { + logger.warn("Tiles requested before JourneyMap started"); + ctx.status(400); + ctx.result("JourneyMap is still starting"); + } + File worldDir = FileHandler.getJMWorldDir(minecraft); + try + { + if (!worldDir.exists() || !worldDir.isDirectory()) + { + logger.warn("JM world directory not found"); + ctx.status(404); + ctx.result("World not found"); + } + } + catch (NullPointerException e) + { + logger.warn("NPE occurred while locating JM world directory"); + ctx.status(404); + ctx.result("World not found"); + } + MapType.Name mapTypeName = null; + try + { + mapTypeName = MapType.Name.valueOf(mapTypeString); + } + catch (IllegalArgumentException e) + { + logger.warn("Invalid map type supplied during tiles request: " + mapTypeString); + ctx.status(400); + ctx.result("Invalid map type: " + mapTypeString); + } + if (mapTypeName != MapType.Name.underground) + { + y = null; // Only underground maps have elevation + } + if (mapTypeName == MapType.Name.underground && WorldData.isHardcoreAndMultiplayer()) + { + logger.debug("Blank tile returned for underground view on a hardcore server"); + + try + { + OutputStream output = ctx.res.getOutputStream(); + ctx.contentType(ContentType.IMAGE_PNG); + output.write(Files.readAllBytes(RegionImageHandler.getBlank512x512ImageFile().toPath())); + output.flush(); + } + catch (IOException e) + { + logger.info("Connection closed while writing image response. Webmap probably reloaded."); + ctx.result("Connection closed while writing image response. Webmap probably reloaded."); + } + return; + } + int scale = (int) Math.pow(2, zoom); + int distance = 32 / scale; + int minChunkX = x * distance; + int minChunkY = z * distance; + int maxChunkX = minChunkX + distance - 1; + int maxChunkY = minChunkY + distance - 1; + ChunkCoordIntPair startCoord = new ChunkCoordIntPair(minChunkX, minChunkY); + ChunkCoordIntPair endCoord = new ChunkCoordIntPair(maxChunkX, maxChunkY); + boolean showGrid = JourneymapClient.getWebMapProperties().showGrid.get(); + MapType mapType = new MapType(mapTypeName, y, dimension); + BufferedImage img = RegionImageHandler.getMergedChunks( + worldDir, startCoord, endCoord, mapType, true, null, + Tile.TILESIZE, Tile.TILESIZE, false, showGrid + ); + + try + { + OutputStream output = ctx.res.getOutputStream(); + ctx.contentType(ContentType.IMAGE_PNG); + ImageIO.write(img, "png", output); + output.flush(); + } + catch (IOException e) + { + logger.info("Connection closed while writing image response. Webmap probably reloaded."); + ctx.result("Connection closed while writing image response. Webmap probably reloaded."); + } + + } +} diff --git a/src/main/java/journeymap/common/Journeymap.java b/src/main/java/journeymap/common/Journeymap.java index 5ab71e5..b376b9c 100644 --- a/src/main/java/journeymap/common/Journeymap.java +++ b/src/main/java/journeymap/common/Journeymap.java @@ -7,7 +7,11 @@ import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.SidedProxy; -import cpw.mods.fml.common.event.*; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.network.NetworkCheckHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -29,8 +33,8 @@ name = Journeymap.SHORT_MOD_NAME, version = BuildInfo.JM_VERSION, canBeDeactivated = true, - modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter", -dependencies = "required-after:Forge@[" + BuildInfo.FORGE_VERSION + ",)") +// modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter", + dependencies = "required-after:Forge@[" + BuildInfo.FORGE_VERSION + ",)") public class Journeymap { public static final String MOD_ID = "journeymap"; diff --git a/src/main/kotlin/journeymap/client/service/webmap/Webmap.kt b/src/main/kotlin/journeymap/client/service/webmap/Webmap.kt deleted file mode 100644 index 32b3e51..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/Webmap.kt +++ /dev/null @@ -1,130 +0,0 @@ -package journeymap.client.service.webmap - -import journeymap.client.JourneymapClient -import journeymap.client.io.FileHandler -import journeymap.client.service.webmap.kotlin.routes.* -import journeymap.client.service.webmap.kotlin.wrapForError -import journeymap.common.Journeymap -import org.apache.logging.log4j.Logger -import spark.Filter -import spark.Spark.init -import spark.Spark.initExceptionHandler -import spark.kotlin.* -import java.io.File -import java.io.IOException -import java.net.ServerSocket - -object Webmap -{ - val logger: Logger = Journeymap.getLogger() - - var port: Int = 0 - var started: Boolean = false - - fun start() - { - if (!this.started) - { - this.findPort() - port(this.port) - - this.initialise() - - this.started = true - this.logger.info("Webmap is now listening on port ${this.port}.") - } - } - - private fun initialise() - { - initExceptionHandler { - this.logger.error("Failed to start server: $it") - this.stop() - } - - val assetsRootProperty: String? = System.getProperty("journeymap.webmap.assets_root", null) - val testFile = File("../src/main/resources" + FileHandler.ASSETS_WEBMAP) - - when - { - assetsRootProperty != null -> - { - logger.info("Detected 'journeymap.webmap.assets_root' property, serving static files from: $assetsRootProperty") - staticFiles.externalLocation(assetsRootProperty) - } - testFile.exists() -> - { - logger.info("Development environment detected, serving static files from the filesystem.") - staticFiles.externalLocation(testFile.canonicalPath) - } - else -> - { - staticFiles.location(FileHandler.ASSETS_WEBMAP) - } - } - - before(Filter { _, response -> - // Allow access from all origins (eg for Apiary access) - response.header("Access-Control-Allow-Origin", "*") - - // Prevent caching of all routes - response.header("Cache-Control", "no-cache") - }) - - get("/data/:type", function = wrapForError(::dataGet)) - get("/logs", function = wrapForError(::logGet)) - get("/properties", function = wrapForError(::propertiesGet)) - get("/resources", function = wrapForError(::resourcesGet)) - get("/skin/:uuid", function = wrapForError(::skinGet)) - get("/status", function = wrapForError(::statusGet)) - get("/tiles/tile.png", function = wrapForError(::tilesGet)) - - post("/properties", function = wrapForError(::propertiesPost)) - - init() - } - - fun stop() - { - if (this.started) - { - spark.kotlin.stop() - this.started = false - this.logger.info("Webmap stopped.") - } - } - - private fun findPort(tryCurrentPort: Boolean = true) - { - if (this.port == 0) - { - // We set this here because we need to get it again if the user changes the setting - this.port = JourneymapClient.getWebMapProperties().port.get() - } - - if (tryCurrentPort) - { - try - { - val socket = ServerSocket(this.port) - this.port = socket.localPort - socket.close() - } - catch (e: IOException) - { - this.logger.warn("Configured port ${this.port} could not be bound: $e") - findPort(false) - } - - this.logger.info("Configured port ${this.port} is available.") - } - else - { - val socket = ServerSocket(0) - this.port = socket.localPort - socket.close() - - this.logger.info("New port ${this.port} assigned by ServerSocket.") - } - } -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/enums/WebmapStatus.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/enums/WebmapStatus.kt deleted file mode 100644 index 43c860f..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/enums/WebmapStatus.kt +++ /dev/null @@ -1,10 +0,0 @@ -package journeymap.client.service.webmap.kotlin.enums - -enum class WebmapStatus(val status: String) -{ - READY("ready"), - DISABLED("disabled"), - - NO_WORLD("no_world"), - STARTING("starting"), -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes.kt deleted file mode 100644 index df114f4..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes.kt +++ /dev/null @@ -1,31 +0,0 @@ -package journeymap.client.service.webmap.kotlin - -import journeymap.client.log.LogFormatter -import journeymap.common.Journeymap -import org.apache.logging.log4j.Logger -import spark.kotlin.RouteHandler - - -// Variable/value declarations -private val logger: Logger = Journeymap.getLogger() - - -internal fun wrapForError(function: (RouteHandler) -> Any): (RouteHandler) -> Any -{ - fun wrapper(handler: RouteHandler): Any - { - return try - { - function(handler) - } - catch (t: Throwable) - { - logger.error(LogFormatter.toString(t)) - handler.response.status(500) - - t.localizedMessage - } - } - - return ::wrapper -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/action.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/action.kt deleted file mode 100644 index a0b46e9..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/action.kt +++ /dev/null @@ -1,147 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import cpw.mods.fml.client.FMLClientHandler -import journeymap.client.JourneymapClient -import journeymap.client.io.FileHandler -import journeymap.client.io.MapSaver -import journeymap.client.model.MapType -import journeymap.client.task.multi.MapRegionTask -import journeymap.client.task.multi.SaveMapTask -import journeymap.common.Journeymap -import net.minecraft.client.Minecraft -import net.minecraft.world.World -import org.apache.logging.log4j.Logger -import spark.kotlin.RouteHandler -import java.io.File - - -private val GSON: Gson = GsonBuilder().setPrettyPrinting().create() -private val logger: Logger = Journeymap.getLogger() - - -internal fun actionGet(handler: RouteHandler): Any -{ - val minecraft: Minecraft = FMLClientHandler.instance().client - val world: World? = minecraft.theWorld - - if (world == null) - { - logger.warn("Action requested before world loaded") - handler.status(400) - return "World not loaded" // TODO: Handle world being unloaded - } - - if (!JourneymapClient.getInstance().isMapping) - { - logger.warn("Action requested before Journeymap started") - handler.status(400) - return "JourneyMap is still starting" // TODO: Handle JM not being started - } - - val type = handler.params("type") - - return when (type) - { - "automap" -> autoMap(handler, minecraft, world) - "savemap" -> saveMap(handler, minecraft, world) - - else -> - { - logger.warn("Unknown action type '$type'") - handler.status(400) - - "Unknown action type '$type'" - } - } -} - -internal fun saveMap(handler: RouteHandler, minecraft: Minecraft, world: World): Any -{ - val worldDir: File = FileHandler.getJMWorldDir(minecraft) - - if (!worldDir.exists() || !worldDir.isDirectory) - { - logger.warn("JM world directory not found") - handler.status(500) - return "Unable to find JourneyMap world directory" - } - - val dimension: Int = handler.request.queryParamOrDefault("dim", "0").toInt() - val mapTypeString: String = handler.request.queryParamOrDefault("mapType", MapType.Name.day.name) - - var vSlice: Int? = handler.queryMap("depth").integerValue() - val mapTypeName: MapType.Name - - try - { - mapTypeName = MapType.Name.valueOf(mapTypeString) - } - catch (e: IllegalArgumentException) - { - logger.warn("Invalid map type '$mapTypeString'") - handler.status(400) - return "Invalid map type '$mapTypeString'" - } - - if (mapTypeName != MapType.Name.underground) - { - vSlice = null - } - - val hardcore: Boolean = world.worldInfo.isHardcoreModeEnabled - val mapType: MapType = MapType.from(mapTypeName, vSlice, dimension) - - if (mapType.isUnderground && hardcore) - { - logger.warn("Cave mapping is not allowed on hardcore servers") - handler.status(400) - return "Cave mapping is not allowed on hardcore servers" - } - - val mapSaver = MapSaver(worldDir, mapType) - - if (!mapSaver.isValid) - { - logger.info("No image files to save") - handler.status(400) - return "No image files to save" - } - - JourneymapClient.getInstance().toggleTask(SaveMapTask.Manager::class.java, true, mapSaver) - - val data = mutableMapOf() - - data["filename"] = mapSaver.saveFileName - handler.response.raw().contentType = "application/json" - - return GSON.toJson(data) -} - -internal fun autoMap(handler: RouteHandler, minecraft: Minecraft, world: World): Any -{ - val data = mutableMapOf() - val enabled: Boolean = JourneymapClient.getInstance().isTaskManagerEnabled(MapRegionTask.Manager::class.java) - val scope: String = handler.request.queryParamOrDefault("scope", "stop") - - if (scope == "stop" && enabled) - { - JourneymapClient.getInstance().toggleTask(MapRegionTask.Manager::class.java, false, false) - data["message"] = "automap_complete" - } - else if (!enabled) - { - val doAll: Boolean = scope == "all" - JourneymapClient.getInstance().toggleTask(MapRegionTask.Manager::class.java, true, doAll) - data["message"] = "automap_started" - } - else - { - data["message"] = "automap_already_started" - } - - handler.response.raw().contentType = "application/json" - - return GSON.toJson(data) -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/data.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/data.kt deleted file mode 100644 index 3d77657..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/data.kt +++ /dev/null @@ -1,68 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import journeymap.client.data.DataCache -import journeymap.client.data.ImagesData -import journeymap.client.model.Waypoint -import journeymap.common.Journeymap -import org.apache.logging.log4j.Logger -import spark.kotlin.RouteHandler - - -private val GSON: Gson = GsonBuilder().setPrettyPrinting().create() -private val logger: Logger = Journeymap.getLogger() - - -val dataTypesRequiringSince = listOf("all", "images") - - -internal fun dataGet(handler: RouteHandler): Any -{ - val since: Long? = handler.queryMap("images.since").longValue() - val type = handler.params("type") - - if (type in dataTypesRequiringSince && since == null) - { - logger.warn("Data type '$type' requested without 'images.since' parameter") - handler.status(400) - return "Data type '$type' requires 'images.since' parameter." - } - - val data: Any? = when (type) - { - "all" -> DataCache.instance().getAll(since!!) - "animals" -> DataCache.instance().getAnimals(false) - "mobs" -> DataCache.instance().getMobs(false) - "images" -> ImagesData(since!!) - "messages" -> DataCache.instance().getMessages(false) - "player" -> DataCache.instance().getPlayer(false) - "players" -> DataCache.instance().getPlayers(false) - "world" -> DataCache.instance().getWorld(false) - "villagers" -> DataCache.instance().getVillagers(false) - "waypoints" -> - { - val waypoints: Collection = DataCache.instance().getWaypoints(false) - val wpMap = mutableMapOf() - - for (waypoint in waypoints) - { - wpMap[waypoint.id] = waypoint - } - - wpMap.toMap() - } - - else -> null - } - - if (data == null) - { - logger.warn("Unknown data type '$type'") - handler.status(400) - return "Unknown data type '$type'" - } - - handler.response.raw().contentType = "application/json" - return GSON.toJson(data) -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/log.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/log.kt deleted file mode 100644 index 737a86d..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/log.kt +++ /dev/null @@ -1,32 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import journeymap.client.log.JMLogger -import journeymap.common.Journeymap -import org.apache.logging.log4j.Logger -import spark.kotlin.RouteHandler -import java.io.File - - -private val logger: Logger = Journeymap.getLogger() - - -internal fun logGet(handler: RouteHandler): Any -{ - val logFile: File = JMLogger.getLogFile() - - return if (logFile.exists()) - { - handler.response.raw().addHeader("Content-Disposition", "inline; filename=\"journeymap.log\"") - handler.response.raw().outputStream.write(logFile.readBytes()) - handler.response.raw().outputStream.flush() - - handler.response - } - else - { - logger.warn("Unable to find JourneyMap logfile") - handler.status(404) - - "Not found: ${logFile.path}" - } -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/properties.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/properties.kt deleted file mode 100644 index d2423da..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/properties.kt +++ /dev/null @@ -1,45 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import journeymap.client.JourneymapClient -import journeymap.client.properties.WebMapProperties -import spark.kotlin.RouteHandler -import java.util.concurrent.atomic.AtomicBoolean - - -val webMapProperties: WebMapProperties = JourneymapClient.getWebMapProperties() -var propertiesMap: Map? = null - - -internal fun propertiesGet(handler: RouteHandler): Any -{ - handler.response.raw().contentType = "application/json" - return JourneymapClient.getWebMapProperties().toJsonString() -} - - -internal fun propertiesPost(handler: RouteHandler): Any -{ - if (propertiesMap == null || propertiesMap!!.isEmpty()) - { - val properties: WebMapProperties = JourneymapClient.getWebMapProperties() - val propMap = mutableMapOf() - - propMap["showGrid"] = properties.showGrid - propMap["showSelf"] = properties.showSelf - propMap["showWaypoints"] = properties.showWaypoints - - propertiesMap = propMap.toMap() - } - - for (key in handler.queryMap().toMap().keys) - { - if (key in propertiesMap!!) - { - ( - propertiesMap!![key] ?: error("Properties value for $key is null") - ).set(handler.queryMap(key).booleanValue()) - } - } - - return webMapProperties.save() -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/resources.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/resources.kt deleted file mode 100644 index 86ee58b..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/resources.kt +++ /dev/null @@ -1,68 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import journeymap.client.io.FileHandler.ASSETS_JOURNEYMAP_UI -import journeymap.client.service.webmap.Webmap -import journeymap.common.Journeymap -import journeymap.common.kotlin.extensions.getResourceAsStream -import net.minecraft.util.ResourceLocation -import org.apache.logging.log4j.Logger -import org.eclipse.jetty.io.EofException -import spark.kotlin.RouteHandler -import java.awt.image.BufferedImage -import java.io.FileNotFoundException -import javax.imageio.IIOException -import javax.imageio.ImageIO - - -private val logger: Logger = Journeymap.getLogger() - - -internal fun resourcesGet(handler: RouteHandler): Any -{ - val img: BufferedImage - val resource = handler.request.queryParams("resource") - val resourceLocation = ResourceLocation(resource) - - var extension = resource.split('.').last() - - if (":" in extension) - { - // So we can actually get the filetype from extension - extension = extension.split(":").first() - } - - img = try - { - ImageIO.read(resourceLocation.getResourceAsStream()) - } - catch (e: FileNotFoundException) - { - logger.warn("File at resource location not found: $resource") - handler.status(404) - - ImageIO.read(Webmap.javaClass.getResource("$ASSETS_JOURNEYMAP_UI/img/marker-dot-32.png")) - } - catch (e: EofException) - { - logger.info("Connection closed while writing image response. Webmap probably reloaded.") - return "" - } - catch (e: IIOException) - { - logger.info("Connection closed while writing image response. Webmap probably reloaded.") - return "" - } - catch (e: Exception) - { - logger.error("Exception thrown while retrieving resource at location: $resource", e) - handler.status(500) - - ImageIO.read(Webmap.javaClass.getResource("$ASSETS_JOURNEYMAP_UI/img/marker-dot-32.png")) - } - - handler.response.raw().contentType = "image/${extension}" - ImageIO.write(img, extension, handler.response.raw().outputStream) - handler.response.raw().outputStream.flush() - - return handler.response -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/skin.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/skin.kt deleted file mode 100644 index 06fe796..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/skin.kt +++ /dev/null @@ -1,37 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - - -import cpw.mods.fml.relauncher.ReflectionHelper -import journeymap.client.render.texture.TextureCache -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.GuiPlayerInfo -import net.minecraft.client.network.NetHandlerPlayClient -import spark.kotlin.RouteHandler -import java.awt.image.BufferedImage -import javax.imageio.ImageIO - - -internal fun skinGet(handler: RouteHandler): Any -{ - val netHandlerGui = ReflectionHelper.getPrivateValue, NetHandlerPlayClient>( - NetHandlerPlayClient::class.java, Minecraft.getMinecraft().netHandler, "field_147310_i", "playerInfoMap" - ) - val username = netHandlerGui[handler.params("uuid")]?.name - val img: BufferedImage - - img = if (username == null) - { - BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB) - } - else - { - TextureCache.instance().getPlayerSkin(username).image - - } - - handler.response.raw().contentType = "image/png" - ImageIO.write(img, "png", handler.response.raw().outputStream) - handler.response.raw().outputStream.flush() - - return handler.response -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/status.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/status.kt deleted file mode 100644 index 2d9ae91..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/status.kt +++ /dev/null @@ -1,44 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import journeymap.client.JourneymapClient -import journeymap.client.service.webmap.kotlin.enums.WebmapStatus -import journeymap.client.ui.minimap.MiniMap -import net.minecraft.client.Minecraft -import spark.kotlin.RouteHandler - - -private val GSON: Gson = GsonBuilder().setPrettyPrinting().create() - - -internal fun statusGet(handler: RouteHandler): Any { - val data: MutableMap = mutableMapOf() - - var status = when { - Minecraft.getMinecraft().theWorld == null -> WebmapStatus.NO_WORLD - !JourneymapClient.getInstance().isMapping -> WebmapStatus.STARTING - - else -> WebmapStatus.READY - } - - if (status == WebmapStatus.READY) { - val mapState = MiniMap.state() - - data["mapType"] = mapState.getCurrentMapType().name() - - val allowedMapTypes: Map = mapOf( - "cave" to (mapState.isCaveMappingAllowed) - ) - - if (allowedMapTypes.filterValues { it }.isEmpty()) { - status = WebmapStatus.DISABLED - } - - data["allowedMapTypes"] = allowedMapTypes - } - - data["status"] = status.status - - return GSON.toJson(data) -} diff --git a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/tiles.kt b/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/tiles.kt deleted file mode 100644 index 5d8e10b..0000000 --- a/src/main/kotlin/journeymap/client/service/webmap/kotlin/routes/tiles.kt +++ /dev/null @@ -1,131 +0,0 @@ -package journeymap.client.service.webmap.kotlin.routes - -import cpw.mods.fml.client.FMLClientHandler -import journeymap.client.JourneymapClient -import journeymap.client.data.WorldData -import journeymap.client.io.FileHandler -import journeymap.client.io.RegionImageHandler -import journeymap.client.model.MapType -import journeymap.client.render.map.Tile -import journeymap.common.Journeymap -import net.minecraft.client.Minecraft -import net.minecraft.world.ChunkCoordIntPair -import net.minecraft.world.World -import org.apache.logging.log4j.Logger -import org.eclipse.jetty.io.EofException -import spark.kotlin.RouteHandler -import java.awt.image.BufferedImage -import java.io.File -import java.io.OutputStream -import javax.imageio.IIOException -import javax.imageio.ImageIO -import kotlin.math.pow -import kotlin.math.roundToInt - - -private val logger: Logger = Journeymap.getLogger() - - -internal fun tilesGet(handler: RouteHandler): Any { - val x: Int = handler.request.queryParamOrDefault("x", "0").toInt() - var y: Int? = handler.request.queryParamOrDefault("y", "0").toInt() - val z: Int = handler.request.queryParamOrDefault("z", "0").toInt() - - val dimension: Int = handler.request.queryParamOrDefault("dimension", "0").toInt() - val mapTypeString: String = handler.request.queryParamOrDefault("mapTypeString", MapType.Name.day.name) - val zoom: Int = handler.request.queryParamOrDefault("zoom", "0").toInt() - - val minecraft: Minecraft = FMLClientHandler.instance().client - val world: World? = minecraft.theWorld - - if (world == null) { - logger.warn("Tiles requested before world loaded") - handler.status(400) - return "World not loaded" - } - - if (!JourneymapClient.getInstance().isMapping) { - logger.warn("Tiles requested before JourneyMap started") - handler.status(400) - return "JourneyMap is still starting" - } - - val worldDir: File = FileHandler.getJMWorldDir(minecraft) - - try { - if (!worldDir.exists() || !worldDir.isDirectory) { - logger.warn("JM world directory not found") - handler.status(404) - return "World not found" - } - } catch (e: NullPointerException) { - logger.warn("NPE occurred while locating JM world directory") - handler.status(404) - return "World not found" - } - - val mapTypeName: MapType.Name? - - try { - mapTypeName = MapType.Name.valueOf(mapTypeString) - } catch (e: IllegalArgumentException) { - logger.warn("Invalid map type supplied during tiles request: $mapTypeString") - handler.status(400) - return "Invalid map type: $mapTypeString" - } - - if (mapTypeName != MapType.Name.underground) { - y = null // Only underground maps have elevation - } - - if (mapTypeName == MapType.Name.underground && WorldData.isHardcoreAndMultiplayer()) { - logger.debug("Blank tile returned for underground view on a hardcore server") - val output: OutputStream = handler.response.raw().outputStream - - handler.response.raw().contentType = "image/png" - output.write(RegionImageHandler.getBlank512x512ImageFile().readBytes()) - output.flush() - - return handler.response - } - - // TODO: Test out this math with Leaflet - - val scale: Int = 2.0.pow(zoom).roundToInt() - val distance: Int = 32 / scale - - val minChunkX: Int = x * distance - val minChunkY: Int = z * distance - - val maxChunkX = minChunkX + distance - 1 - val maxChunkY = minChunkY + distance - 1 - - val startCoord = ChunkCoordIntPair(minChunkX, minChunkY) - val endCoord = ChunkCoordIntPair(maxChunkX, maxChunkY) - - val showGrid: Boolean = JourneymapClient.getWebMapProperties().showGrid.get() - val mapType = MapType(mapTypeName, y, dimension) - - val img: BufferedImage = RegionImageHandler.getMergedChunks( - worldDir, startCoord, endCoord, mapType, true, null, - Tile.TILESIZE, Tile.TILESIZE, false, showGrid - ) - - val output: OutputStream = handler.response.raw().outputStream - - try { - handler.response.raw().contentType = "image/png" - ImageIO.write(img, "png", output) - output.flush() - } catch (e: EofException) { - logger.info("Connection closed while writing image response. Webmap probably reloaded.") - return "" - } catch (e: IIOException) { - logger.info("Connection closed while writing image response. Webmap probably reloaded.") - return "" - } - - // TODO: Profiling, as in the original TileService - - return handler.response -} diff --git a/src/main/kotlin/journeymap/common/kotlin/extensions/resources.kt b/src/main/kotlin/journeymap/common/kotlin/extensions/resources.kt deleted file mode 100644 index c7d761d..0000000 --- a/src/main/kotlin/journeymap/common/kotlin/extensions/resources.kt +++ /dev/null @@ -1,10 +0,0 @@ -package journeymap.common.kotlin.extensions - -import net.minecraft.client.Minecraft -import net.minecraft.util.ResourceLocation -import java.io.InputStream - -fun ResourceLocation.getResourceAsStream(): InputStream -{ - return Minecraft.getMinecraft().resourceManager.getResource(this).inputStream -} diff --git a/src/main/resources/assets/journeymap/web/css/journeymap.css b/src/main/resources/assets/journeymap/web/css/journeymap.css deleted file mode 100644 index b94811b..0000000 --- a/src/main/resources/assets/journeymap/web/css/journeymap.css +++ /dev/null @@ -1,285 +0,0 @@ -html,body{height:100%;margin:0;padding:0} -/*! - JourneyMap Mod for Minecraft - Copyright (c) 2011-2018 Techbrew Interactive, LLC . All Rights Reserved. */ - -#map-canvas { - height: 100%; - width: 100%; - background-color: #111 !important; -} - -#jm-logo{ - padding: 2px 10px 0px 15px; -} - -#jm-button { - height: 40px; - margin-top: 2px; -} - -#jm-button div { - - font-size: 14px !important; -} - -#jm-menu img { - margin-right:10px; -} - -.ui-menu-item { - padding-left: 5px; -} - -.ui-menu-item a img { - vertical-align: middle; -} - -li label { - display: inline; - height: 30px; - line-height: 30px; - padding: 5px 20px; - clear: both; - white-space: nowrap; - font-weight: normal; - cursor: pointer; -} - -li label input { - vertical-align: text-bottom; -} - -label span { - margin: 5px 0px 5px 5px; -} - -.nav { - padding: 10px 10px 0px 0px; -} - -.nav-button button { - height: 38px; - margin: 0px; -} - - -#jm-rt-menus { - display: inline; - position: relative; -} - -#jm-rt-menus div { - display: inline; -} - -#jm-menu { - padding: 5px; -} - -#jm-menu li { - padding: 5px; -} - -#jm-actions-menu { - padding: 5px; -} - -#jm-actions-menu li { - padding: 5px; -} - -#worldInfo { - padding:6px; - display:inline-block; - font-weight: bold; -} - -#worldInfo .infoTitle { - font-style:italic; - font-weight:normal; - text-align:right; - padding-left:4px; - padding-right:4px; - -} - -.playerMarker { - height:32px; - width:32px; - border: none; -} - -.entityMarker, .mpMarker { - height:64px; - width:64px; - border: none; -} - -.entityName { - font:bold 11px Arial; - text-align:center; - white-space: nowrap; - color:#ffffff; - padding:2px; - background-color:#000000; - visibility:hidden; - position:absolute; - margin-top:-2em; -} - -.mpName { - font:bold 11px Arial; - text-align:center; - white-space: nowrap; - color:#ffffff; - padding:3px; - - position:absolute; - margin-top:-12px; - - background-color:rgba(34,34,34,0.7); - display:inline-block; - - border-width:1px; - border-style:solid; - border-color:#c5c5c5; - - -webkit-border-radius: 6px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - border-radius: 6px; -} - -.waypoint { - font-size: 10px; - font-weight: bold; - text-align:center; - white-space: nowrap; - - height: 15px; - padding:5px; - color: #fff; - background-color:rgba(34,34,34,0.9); - - border-width:1px; - border-style:solid; - border-color:#c5c5c5; - - -webkit-border-radius: 6px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - border-radius: 6px; -} - -.waypoint.death { - background-color:rgba(255,0,0,0.7); -} - -.playerImages, .entityImages, .mpImages { - position:relative; -} - -.entityIcon { - position:absolute; - width: 16px; - height: 16px; - top: 24px; - left: 24px; -} - -.entityIcon.entity_3D { - position:absolute; - width: 32px; - height: 32px; - top: 6px; - left: 16px; -} - -.entityLocator, .mpLocator { - position:absolute; - width: 64px; - height: 64px; -} - -.playerLocator { - position:absolute; - width: 32px; - height: 32px; -} - -.mpIcon { - position:absolute; - top: 20px; - left: 20px; - width: 24px; - height: 24px; -} - -.playerInfo { - - font-size: 10px; - font-weight: bold; - - margin-bottom:32px; - padding:5px; - color: #fff; - background-color:rgba(34,34,34,0.7); - display:inline-block; - - border-width:1px; - border-style:solid; - border-color:#c5c5c5; - - -webkit-border-radius: 6px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - border-radius: 6px; - -} - -.message { - font-size: 14px !important; - text-align: center; - cursor: pointer; -} - -.dialog { - text-align: center; -} - -.ui-widget { - font-size: 14px !important; -} - -.ui-dialog .ui-dialog-buttonpane { - text-align: center; - padding:5px !important; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: none; -} - -.ui-button-text img { - width: 24px; - height: 24px; -} - -/* Fix Google Maps canvas */ -.google-map-canvas, -.google-map-canvas * { - .box-sizing(content-box); -} - -/* Optional responsive image setFrom */ -img { max-width: none; } - -/* Debug page */ -.entry{width:300px;display:inline-block;} -.rgb{display:inline-block;height:32px;width:32px} diff --git a/src/main/resources/assets/journeymap/web/index.html b/src/main/resources/assets/journeymap/web/index.html deleted file mode 100644 index 02682b2..0000000 --- a/src/main/resources/assets/journeymap/web/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - JourneyMap - - - - - - - - - - - - - - -
- - - - - - - - - - - - diff --git a/src/main/resources/assets/journeymap/web/js/journeymap.js b/src/main/resources/assets/journeymap/web/js/journeymap.js deleted file mode 100644 index 5c12625..0000000 --- a/src/main/resources/assets/journeymap/web/js/journeymap.js +++ /dev/null @@ -1,1677 +0,0 @@ -"use strict"; -/** - * JourneyMap web client - http://journeymap.info - * Copyright (C) 2011-2015. Mark Woodman (journeymap.info) All rights reserved. - * May not be modified or distributed without express written consent. - */ -var JourneyMap = (function() { - var map; - var mapOverlay; - - var isNightMap = false; - var centerOnPlayer = true; - var showCaves = true; - var showAnimals = true; - var showPets = true; - var showMobs = true; - var showVillagers = true; - var showPlayers = true; - var showWaypoints = true; - var showGrid = true; - - var lastImageCheck = 0; - var skipImageCheck = false; - - var JmIcon; - var halted = false; - var uiInitialized = false; - var versionChecked = false; - var updatingMap = false; - var drawingMap = false; - - var playerOverrideMap = false; - var playerUnderground = false; - - var queryServerPending = 0; - var timerId = null; - - var JM = { - debug : false, - messages : null, - properties : null, - mobs : null, - animals : null, - players : null, - villagers : null, - waypoints : null, - images : null - }; - var markers = {}; - - var entityTemplate = [ - '
', - '
', - '
', - '', - '', - '
', - '
' - ].join(''); - - var mpTemplate = [ - '
', - '
', - '
', - '', - '', - '
', - '
' - ].join(''); - - var dialogTemplate = [ - '
', - '', - '
', - '
' - ].join(''); - - var messageTemplate = '
'; - - - var errorDialog = null; - var splashDialog = null; - var debug = false; - - // Preload images - $('').attr('src','/img/pixel.png'); - - /** Delay helper * */ - var delay = (function() { - - var timer = 0; - return function(callback, ms) { - - clearTimeout(timer); - timer = setTimeout(callback, ms); - }; - })(); - - /** - * Load I18N messages once. - * - * @returns - */ - var initMessages = function() { - - if (debug) - console.log(">>> " + "initMessages"); - - $.ajax({ - - url : "/properties", - dataType : "jsonp", - contentType : "application/javascript; charset=utf-8", - async : false - - }).fail(handleError).done(function(data, textStatus, jqXHR) { - JM.properties = data; - - // Set global vars of prefs - showCaves = JM.properties.showCaves.value==1; - showGrid = JM.properties.showGrid.value==1; - showMobs = JM.properties.showMobs.value==1; - showAnimals = JM.properties.showAnimals.value==1; - showVillagers = JM.properties.showVillagers.value==1; - showPets = JM.properties.showPets.value==1; - showPlayers = JM.properties.showPlayers.value==1; - showWaypoints = JM.properties.showWaypoints.value==1; - - // Get L10N messages - $.ajax({ - url : "/data/messages", - dataType : "jsonp", - contentType : "application/javascript; charset=utf-8", - async : false - }).fail(handleError).done(function(data, textStatus, jqXHR) { - JM.messages = data; - initGame(); - }); - - }); - - } - - /** - * Load Game info once. - * - * @returns - */ - var initGame = function() { - - if (debug) - console.log(">>> " + "initGame"); - - $.ajax({ - url : "/data/world", - dataType : "jsonp", - contentType : "application/javascript; charset=utf-8", - async : false - }).fail(handleError).done( - function(data, textStatus, jqXHR) { - - JM.world = data; - _gaq.push(['_setCustomVar', 1, 'jm_version', JM.world.jm_version, 2]); - _gaq.push(['_setCustomVar', 2, 'mc_version', JM.world.mc_version, 2]); - - // Update UI with game info - $("#version").html("JourneyMap " + JM.world.jm_version); - - // Splash - if(!errorDialog) { - splashDialog = createDialog(JM.world.mod_name + "
by techbrew"); - } - - // Init UI - initUI(); - } - ); - } - - /** - * Initialize UI once. - * - * @returns - */ - var initUI = function() { - - if (debug) - console.log(">>> " + "initUI"); - - // Ensure messages are loaded first. - if (!JM.messages) { - throw ("initUI called without JM.messages"); // shouldn't happen - } - - // Set page language - $('html').attr('lang', JM.messages.locale.split('_')[0]); - - // Set RSS feed title - $("link #rssfeed").attr("title", getMessage('rss_feed_title')); - - // Main menu - $("#jm-menu").menu().hide().find('a').click(function(){ - _gaq.push(['_trackEvent', 'menu', 'link', this.href]); - return true; - }); - - $("#jm-button").button({ - icons: { - secondary: "ui-icon-triangle-1-s" - } - }).click(function(){ - var menu = $("#jm-menu"); - if ( $(menu).is(':visible') ) { - menu.hide(); - } else { - var button = $("#jm-button"); - menu.show().position({ my: "left top", at: "left bottom", of: button }); - $( document ).one( "click", function() { menu.hide(); }); - } - return false; - }); - - // JourneyMap menu / homepage link - $("#webLink").attr("title", getMessage('web_link_title')); - $("#webLinkText").html(getMessage('web_link_text')); - - // JourneyMap menu / forums link - $("#forumLink").attr("title", getMessage('forum_link_title')); - $("#forumLinkText").html(getMessage('forum_link_text')); - - // JourneyMap menu / RSS feed link - $("#rssLink").attr("title", getMessage('rss_feed_title')); - $("#rssLinkText").html(getMessage('rss_feed_text')); - - // JourneyMap menu / Email subscription link - $("#emailLink").attr("title", getMessage('email_sub_title')); - $("#emailLinkText").html(getMessage('email_sub_text')); - - // JourneyMap menu / Follow on Twitter link - $("#twitterLink").attr("title", getMessage('follow_twitter_title')); - $("#twitterLinkText").html(getMessage('follow_twitter_text')); - - // JourneyMap menu / Donate link - $("#donateLink").attr("title", getMessage('donate_title')); - $("#donateLinkText").html(getMessage('donate_text')); - - // Toggles / Day/Night button - $("#dayNightButton") - .attr("title", getMessage('day_button_title')) - .click(function() { - playerOverrideMap = true; - if(isNightMap===true) { - setMapType('day'); - } else { - setMapType('night'); - } - }); - - $("#dayNightButton").parent().buttonset(); - - // Toggles / Follow button - $("#followButton") - .attr("title", getMessage('follow_button_title')) - .click(function() { - setCenterOnPlayer(!centerOnPlayer); - }); - $("#jm-toggles").buttonset(); - - // Options Menu and Button - $("#jm-options-menu").menu().hide(); - $("#jm-options-button").attr("title", getMessage('show_menu_text')); - $("#jm-options-button").button({ - icons: { - secondary: "ui-icon-triangle-1-s" - } - }).click(function(){ - $("#jm-actions-menu").hide(); - var menu = $("#jm-options-menu"); - if ( $(menu).is(':visible') ) { - menu.hide(); - } else { - - enforceFeature("#checkShowCaves", JM.world.features.MapCaves); - enforceFeature("#checkShowAnimals", JM.world.features.RadarAnimals); - enforceFeature("#checkShowPets", JM.world.features.RadarAnimals); - enforceFeature("#checkShowMobs", JM.world.features.RadarMobs); - enforceFeature("#checkShowVillagers", JM.world.features.RadarVillagers); - enforceFeature("#checkShowPlayers", JM.world.features.RadarPlayers); - - menu.show(); - $( document ).one( "click", function() { menu.hide(); }); - } - return false; - }); - - $("#jm-options-menu").click( function(event){ - event.stopPropagation(); - }); - - - // Options Menu items - setTextAndTitle("#cavesMenuItem", "caves_menu_item_text", "caves_menu_item_title"); - setTextAndTitle("#animalsMenuItem", "animals_menu_item_text", "animals_menu_item_title"); - setTextAndTitle("#petsMenuItem", "pets_menu_item_text", "pets_menu_item_title"); - setTextAndTitle("#mobsMenuItem", "mobs_menu_item_text", "mobs_menu_item_title"); - setTextAndTitle("#villagersMenuItem", "villagers_menu_item_text", "villagers_menu_item_title"); - setTextAndTitle("#playersMenuItem", "players_menu_item_text", "players_menu_item_title"); - setTextAndTitle("#waypointsMenuItem", "waypoints_menu_item_text", "waypoints_menu_item_title"); - setTextAndTitle("#gridMenuItem", "grid_menu_item_text", "grid_menu_item_title"); - - // Options Menu checkboxes - $("#checkShowCaves").prop('checked', showCaves) - $("#checkShowCaves").click(function(event) { - showCaves = (this.checked === true); - postPreference("showCaves", showCaves); - if(playerUnderground) { - refreshMap(); - } - }); - - $("#checkShowGrid").prop('checked', showGrid) - $("#checkShowGrid").click(function(event) { - showGrid = (this.checked === true); - postPreference("showGrid", showGrid); - setTimeout(function() { - window.location = window.location; - }, 1500); - }); - - $("#checkShowWaypoints").prop('checked', showWaypoints) - $("#checkShowWaypoints").click(function(event) { - showWaypoints = (this.checked === true); - postPreference("showWaypoints", showWaypoints); - if(!showWaypoints) { - JM.waypoints = null; - } - }); - - $("#checkShowAnimals").prop('checked', showAnimals) - $("#checkShowAnimals").click(function(event) { - showAnimals = (this.checked === true); - postPreference("showAnimals", showAnimals); - drawMobs(); - }); - - $("#checkShowPets").prop('checked', showPets) - $("#checkShowPets").click(function(event) { - showPets = (this.checked === true); - postPreference("showPets", showPets); - drawMobs(); - }); - - $("#checkShowMobs").prop('checked', showMobs) - $("#checkShowMobs").click(function() { - showMobs = (this.checked === true); - postPreference("showMobs", showMobs); - drawMobs(); - }); - - $("#checkShowVillagers").prop('checked', showVillagers) - $("#checkShowVillagers").click(function() { - showVillagers = (this.checked === true); - postPreference("showVillagers", showVillagers); - drawMobs(); - }); - - $("#checkShowPlayers").prop('checked', showPlayers) - $("#checkShowPlayers").click(function() { - showPlayers = (this.checked === true); - postPreference("showPlayers", showPlayers); - drawMultiplayers(); - }); - - // Actions Menu Button - $("#jm-actions-menu").menu().hide(); - $("#jm-actions-button").attr("title", getMessage('actions_title')); - $("#jm-actions-button").button({ - icons: { - secondary: "ui-icon-triangle-1-s" - } - }).click(function(){ - $("#jm-options-menu").hide(); - var menu = $("#jm-actions-menu"); - if ( $(menu).is(':visible') ) { - menu.hide(); - } else { - if(JM.world.singlePlayer===true) { - $("#autoMapButton").removeClass('ui-state-disabled'); - } else { - $("#autoMapButton").addClass('ui-state-disabled'); - } - menu.show(); - $( document ).one( "click", function() { menu.hide(); }); - } - return false; - }); - - // Save map button - $("#saveButton").attr("title", getMessage('save_button_title')).click(function() { - saveMapImage(); - }); - $("#saveButtonText").html(getMessage('save_button_text')); - - // Automap button - $("#autoMapButton").attr("title", getMessage('automap_title')).click(function() { - if(JM.world.singlePlayer===true) { - autoMapDialog(); - } else { - return false; - } - }); - $("#autoMapButtonText").html(getMessage('automap_text')); - - // World info - $("#worldInfo").hide(); - $("#worldNameLabel").html(getMessage('worldname_text')); - $("#worldTimeLabel").html(getMessage('worldtime_text')); - $("#playerBiomeLabel").html(getMessage('biome_text')); - $("#playerLocationLabel").html(getMessage('location_text')); - $("#playerElevationLabel").html(getMessage('elevation_text')); - - // Disable selection on nav elements - $(".nav").disableSelection(); - - // Set flag so this function doesn't get called twice - uiInitialized = true; - - // Continue - initWorld(); - - } - - var enforceFeature = function(buttonId, feature) { - if(feature!==true) { - $(buttonId).attr('disabled', true).parent().find('span').addClass('ui-state-disabled'); - $(buttonId).parent().children().css('cursor','not-allowed'); - } else { - $(buttonId).removeAttr('disabled').parent().find('span').removeClass('ui-state-disabled'); - $(buttonId).parent().children().css('cursor','pointer'); - } - } - - /** - * Post preference to server - */ - var postPreference = function(prefName, prefValue) { - - $.ajax({ - type: "POST", - url: "/properties", - data: prefName +"="+ prefValue - }).fail(function(data, error, jqXHR){ - if (debug) - console.log(">>> postPreference failed: " + data.status, error); - }).done(function(){ - if (debug) - console.log(">>> postPreference done: " + prefName); - }); - } - - /** - * Set text and title on same object - */ - var setTextAndTitle = function(selector, text, title) { - $(selector).html(getMessage(text)).prop('title', getMessage(title)); - } - - /** - * Initialize World. - * - * @returns - */ - var initWorld = function() { - - if (debug) - console.log(">>> " + "initWorld"); - - // Reset state - halted = false; - updatingMap = false; - playerUnderground = false; - queryServerPending = 0; - clearTimer(); - - JM.mobs = {}; - JM.animals = {}; - JM.players = {}; - JM.villagers = {}; - JM.waypoints = {}; - JM.images = {}; - - markers = { - mobs : {}, - animals : {}, - players : {}, - villagers : {}, - waypoints : {}, - player: {} - } - - queryServer(setupMap); - - } - - var setupMap = function() { - - // Google Map - map = initMap($('#map-canvas')[0]); - - map.controls[google.maps.ControlPosition.TOP_LEFT].push($('#jm-logo-span')[0]); - map.controls[google.maps.ControlPosition.TOP_CENTER].push($('#jm-toolbar')[0]); - map.controls[google.maps.ControlPosition.TOP_CENTER].push($('#jm-toggles')[0]); - map.controls[google.maps.ControlPosition.TOP_CENTER].push($('#jm-rt-menus')[0]); - map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push($('#worldInfo')[0]); - - google.maps.event.addListener(map, 'click', function(event) { - var projection = map.getProjection(); - var coords = projection.fromPointToLatLng(event.pixel); - // console.log(coords); TODO show coords with mouseover - }); - - // Close error - if(errorDialog) { - $('.ui-dialog').remove(); - errorDialog = null; - } - - // Close splash - if(splashDialog) { - $(splashDialog).parent().delay(1000).fadeOut(1000, function(){ - $('.ui-dialog').remove(); - splashDialog = null; - }); - } - - setCenterOnPlayer(true); - - // Show update button - if (JM.world.latest_journeymap_version > JM.world.jm_version) { - window.setTimeout(function(){ - var text = getMessage('update_button_title'); - text = text.replace("%1$s", JM.world.latest_journeymap_version); - text = text.replace("%2$s", JM.world.mc_version); - var onClickFn = function(e){ - var url = $('#webLink')[0].href; - window.open(url, '_new', ''); - }; - $("#jm-update-button").button() - .attr("title", text) - .click(onClickFn); - - map.controls[google.maps.ControlPosition.TOP_CENTER].push($('#jm-alerts')[0]); - - showInfoMessage(text, 2500, onClickFn); - - }, 3000); - } - - } - - /** - * Invoke saving map file - */ - var saveMapImage = function() { - _gaq.push(['_trackEvent', 'saveMapImage', null, 0, true]); - - $.ajax({ - type: 'POST', - url: '/action?type=savemap' + getMapStateUrl(), - dataType : 'jsonp' - }).fail(function(data, error, jqXHR){ - //if (debug) - console.log(">>> saveMapImage failed: " + JSON.stringify(data)); - var msg = 'Error: ' + JSON.stringify(data); - showInfoMessage(msg, 2000); - }).success(function(data){ - console.log('automap result: ', data); - var msg = getMessage('save_filename', data.filename); - showInfoMessage(msg, 2000); - }); - } - - /** - * Prompt automap - */ - var autoMapDialog = function() { - - var dialog = $(messageTemplate) - .html(getMessage('automap_dialog_text')) - .css('z-index', google.maps.Marker.MAX_ZINDEX + 1) - .css('min-height', '20px') - .dialog({ - modal: true, - buttons: [ - { width:'80px', text: getMessage('automap_dialog_all'), click: function() { toggleAutoMap('all'); $( this ).dialog( "close" ); } }, - { width:'80px', text: getMessage('automap_dialog_missing'), click: function() { toggleAutoMap('missing'); $( this ).dialog( "close" ); } }, - { width:'80px', text: getMessage('automap_dialog_none'), click: function() { toggleAutoMap('stop'); $( this ).dialog( "close" ); } }, - { width:'80px', text: getMessage('automap_dialog_close'), click: function() { $( this ).dialog( "close" ); } } - ] - }).parent().find('.ui-dialog-titlebar').remove(); - $(dialog).find('.ui-dialog-buttonset').css('width','100%'); - - } - - /** - * Invoke starting auto-map - */ - var toggleAutoMap = function(scope) { - _gaq.push(['_trackEvent', 'toggleAutoMap', null, 0, true]); - $.ajax({ - type: "POST", - url: "/action?type=automap&scope=" + scope, - dataType : "jsonp" - }).fail(function(data, error, jqXHR){ - //if (debug) - console.log(">>> toggleAutoMap failed: " + JSON.stringify(data)); - var msg = 'Error: ' + JSON.stringify(data); - showInfoMessage(msg, 2000); - }).success(function(data){ - console.log('automap result: ', data); - var msg = getMessage(data.message); - showInfoMessage(msg, 2000); - }); - } - - var showInfoMessage = function(msg, duration, callback) { - - var message = $(messageTemplate).dialog({ modal: false }); - - var closeFn = function(){ - $(message).remove(); - message = null; - } - - $(message).css('z-index', google.maps.Marker.MAX_ZINDEX + 1) - .css('min-height', '20px') - .html(msg) - .click(function(){ - if(callback) callback(); - closeFn(); - }) - .parent().find('.ui-dialog-titlebar').remove(); - - $(message).parent().delay(2000).fadeOut(1500, closeFn); - } - - function setMapType(mapType) { - - var typeChanged = false; - if (mapType === "day") { - if (isNightMap === false) return; - isNightMap = false; - typeChanged = true; - - $("#dayNightText").html(getMessage('day_button_text')); - $("#dayNightButton").attr("title", getMessage('day_button_title')); - $("#dayNightButtonImg").attr('src', '/theme/icon/day.png') - - } else if (mapType === "night") { - if (isNightMap === true) return; - isNightMap = true; - typeChanged = true; - - $("#dayNightText").html(getMessage('night_button_text')); - $("#dayNightButton").attr("title", getMessage('night_button_title')); - $("#dayNightButtonImg").attr('src', '/theme/icon/night.png'); - - } else { - if (debug) - console.log(">>> " + "Error: Can't set mapType: " + mapType); - } - - if(typeChanged && playerUnderground === false) { - if (debug) console.log("setMapType(" + mapType + ")"); - refreshMap(); - } - - } - - function setCenterOnPlayer(onPlayer) { - centerOnPlayer = onPlayer; - - if(onPlayer) { - $("#followButtonImg").attr('src', '/theme/icon/follow.png'); - if(markers.playerMarker) { - map.panTo(markers.playerMarker.getPosition()); - drawPlayer(); - } else { - refreshMap(); - } - } else { - $("#followButtonImg").attr('src', '/theme/icon/follow.png'); - } - - } - - function setShowCaves(show) { - - if (show === showCaves) { - return; - } - showCaves = show; - - if (playerUnderground === true) { - refreshMap(); - } - - } - - // //////////// DATA //////////////////// - - var queryServer = function(callback) { - - if (halted === true) - return; - - if(queryServerPending>2) { - // time to reset - if(debug) console.log("Too many queries pending, resetting."); - window.location = window.location; - } - - // Params for dirty image check - var params = ""; - if(map) { - if(!lastImageCheck) lastImageCheck = new Date().getTime(); - params = "?images.since=" + lastImageCheck; - } - - // Get all the datas - queryServerPending++; - fetchData("/data/all" + params, function(data) { - queryServerPending--; - - // Apply data - JM.animals = data.animals; - JM.images = data.images; - JM.mobs = data.mobs; - JM.player = data.player; - JM.players = data.players; - JM.villagers = data.villagers; - JM.waypoints = data.waypoints; - JM.world = data.world; - - // Update underground state - var wasUnderground = playerUnderground; - playerUnderground = JM.player.underground; - - // Update UI - $("#playerBiome").html(JM.player.biome); - $("#playerLocation").html(Math.round(JM.player.posX) + "," + Math.round(JM.player.posZ)); - $("#playerElevation").html(Math.round(JM.player.posY) + " (" + (JM.player.posY >> 4) + ")"); - - // 0 is the start of daytime, 12000 is the start of sunset, 13800 is - // the start of nighttime, 22200 is the start of sunrise, and 24000 is - // daytime again. - var allsecs = JM.world.time / 20; - var mins = Math.floor(allsecs / 60); - var secs = Math.ceil(allsecs % 60); - if (mins < 10) - mins = "0" + mins; - if (secs < 10) - secs = "0" + secs; - var currentTime = mins + ":" + secs; - - // Update UI elements - $("#worldName").html(unescape(JM.world.name).replace("\\+", " ")); - $("#worldTime").html(currentTime); - $("#worldInfo").show(); - - // Set map type based on time - if (playerOverrideMap != true) { - if (JM.world.dimension === 0 && playerUnderground === false) { - if (JM.world.time < 13800) { - setMapType('day'); - } else { - setMapType('night'); - } - } - } - - if (halted === true) - return; - - // Draw the map - if(map) { - if(wasUnderground !== playerUnderground) { - refreshMap(); - } else { - mapOverlay.refreshTiles(); - } - drawMap(); - } - - if (timerId === null) { - var dur = (JM.world && JM.world.browser_poll) ? JM.world.browser_poll : 1000; - timerId = setInterval(queryServer, Math.max(1000, dur)); - } - - if (callback) { - callback(); - } - - }); - - } - - /** - * Fetch JsonP data. Generic error handling, callback invoked on success - */ - var fetchData = function(dataUrl, callback) { - - if (debug) - console.log(">>> " + "fetchData " + dataUrl); - - $.ajax({ - url : dataUrl, - dataType : "jsonp" - }).fail(handleError).done(callback); - } - - - /** - * Force immediate update - */ - var refreshMap = function() { - if (debug) console.log(">>> " + "refreshMap"); - - if(!map) return; - - delay(function(){ - if (debug) console.log(">>> " + "delayed refreshMap"); - - lastImageCheck = 1; - var zoom = map.getZoom(); - var delta = (zoom==MapConfig.maxZoom) ? -0.0000001 : 0.0000001 ; - var center = map.getCenter(); - - // This hack forces the tiles to be replaced but doesn't visibly change the map - map.setZoom(zoom + delta); - map.panTo(center); - map.setZoom(zoom); - map.panTo(center); - }, 500 ); - - } - - /** - * Clear the timer - */ - var clearTimer = function() { - if (timerId !== null) { - clearInterval(timerId); - timerId = null; - } - } - - /** - * Get L10N message by key - */ - var getMessage = function(key, params) { - if(!JM.messages || !JM.messages[key]) { - console.log("Missing L10N message: " + key); - return "!" + key + "!"; - } else { - var msg = JM.messages[key]; - if(!params) { - return msg; - } else { - if(!Array.isArray(params)){ - params = [params]; - } - return msg.format.apply(msg, params); - } - } - } - - // Ajax request got an error from the server - var handleError = function(data, error, jqXHR) { - - if (debug) - console.log(">>> " + "handleError"); - - // Secondary errors will be ignored - if (halted === true) - return; - - _gaq.push(['_trackEvent', 'handleError', JSON.stringify(data), 0, true]); - - // Clear the timer - clearTimer(); - queryServerPending = false; - - if(console && console.log) console.log("Server returned error: " + JSON.stringify(data)); - - // Move nav components back to holder - $(".nav").appendTo( $("#nav-holder") ); - - // Destroy Google Map - $("#map-canvas").empty(); - - // Ensure splash destroyed - if(splashDialog) { - $(splashDialog).remove(); - splashDialog = null; - } - - // Display error - var displayError; - if (data.status === 503 || data.status === 0) { - displayError = getMessage('error_world_not_opened'); - } else { - displayError = ""; - } - - if(!errorDialog) { - errorDialog = createDialog(displayError, true); - } - $(errorDialog).find('div').html(displayError); - - // Restart in 5 seconds - if (!halted) { - halted = true; - if (console) - console.log(">>> " + "Will re-check game state in 5 seconds."); - - setTimeout(function() { - document.location = document.location; - }, 5000); - } - } - - var createDialog = function(text, modal) { - if(!modal) modal=false; - var dialog = $(dialogTemplate).dialog({ modal: modal }); - dialog.parent().find('.ui-dialog-titlebar').remove(); - dialog.css('z-index', google.maps.Marker.MAX_ZINDEX + 1); - if(text) { - dialog.find('div').html(text); - } - return dialog; - } - - // ////////////DRAW //////////////////// - - // Draw the map - var drawMap = function() { - - if (debug) - console.log(">>> " + "drawMap"); - - if (drawingMap === true) { - if (debug) - console.log(">>> " + "Avoided concurrent drawMap()"); - return false; - } - - drawingMap = true; - - // mobs - drawMobs(); - - // other players - drawMultiplayers(); - - // waypoints - drawWaypoints(); - - // player - drawPlayer(); - - drawingMap = false; - - } - - // Draw the player icon - var drawPlayer = function() { - - if (debug) - console.log(">>> " + "drawPlayer"); - - // Get current player position - var pos = blockPosToLatLng(JM.player.posX, JM.player.posZ); - var heading = JM.player.heading; - var imgId = 'player'+JM.player.entityId; - - // Ensure marker - if(!markers.playerMarker) { - - var img = new Image(); - $(img).attr('id', imgId) - .attr('src','/img/locator-player.png') - .css('width','64px') - .css('height','64px') - .rotate(heading); - - markers.playerMarker = new RichMarker({ - position: pos, - map: map, - draggable: false, - flat: true, - anchor: RichMarkerPosition.MIDDLE, - content: img, - zIndex: google.maps.Marker.MAX_ZINDEX + 1, - tooltip : new RichMarker({ - position: null, - map: null, - draggable: false, - flat: true, - anchor: RichMarkerPosition.BOTTOM, - content: '
' + JM.player.username + '
', - }) - }); - - google.maps.event.addListener(markers.playerMarker, 'mouseover', function(args) { - var tooltip = markers.playerMarker.tooltip; - if(tooltip.timeout) { - window.clearTimeout(tooltip.timeout); - } - if(!tooltip.getMap()) { - tooltip.setPosition(markers.playerMarker.position); - tooltip.setMap(markers.playerMarker.map); - tooltip.setZIndex(google.maps.Marker.MAX_ZINDEX + 1); - } - }); - - google.maps.event.addListener(markers.playerMarker, 'mouseout', function(args) { - - var tooltip = markers.playerMarker.tooltip; - if(tooltip.getMap()) { - if(tooltip.timeout) { - window.clearTimeout(tooltip.timeout); - } - tooltip.timeout = window.setTimeout(function(){ - delete tooltip.timeout; - tooltip.setMap(null); - }, 500) - } - }); - - - google.maps.event.addListener(map, 'dragstart', function() { - setCenterOnPlayer(false); - }); - - google.maps.event.addListener(map, 'zoom_changed', function() { - if(centerOnPlayer===true) { - if(markers.playerMarker) { - map.panTo(markers.playerMarker.getPosition()); - } - } - - if(markers.waypoints) { - drawWaypoints(); - } - - if(map.getZoom()==0) { - $('img.entityLocator').css('visibility','hidden'); - } else { - $('img.entityLocator').css('visibility','visible'); - } - - if(map.getZoom()==0) { - $('img.entityMarker').css('visibility','hidden'); - } else { - $('img.entityMarker').css('visibility','visible'); - } - - }); - - } - - // Update marker position and heading - markers.playerMarker.setPosition(pos); - $('#'+imgId).rotate(heading); - - // Keep on top - if(markers.playerMarker.getZIndex()>> " + "drawMobs"); - - if(map.getZoom()===0) return; - - // Mobs - removeObsoleteMarkers(JM.mobs, markers.mobs); - if (JM.world.features.RadarMobs && showMobs === true && JM.mobs) { - $.each(JM.mobs, function(index, mob) { - updateEntityMarker(mob,markers.mobs); - }); - } - - // Animals - removeObsoleteMarkers(JM.animals, markers.animals); - if (JM.world.features.RadarAnimals && (showAnimals === true || showPets === true) && JM.animals) { - $.each(JM.animals, function(index, mob) { - updateEntityMarker(mob,markers.animals); - }); - } - - // Villagers - removeObsoleteMarkers(JM.villagers, markers.villagers); - if (JM.world.features.RadarVillagers && showVillagers === true && JM.villagers) { - $.each(JM.villagers, function(index, mob) { - updateEntityMarker(mob,markers.villagers); - }); - } - - }; - - // Create or update marker - var updateEntityMarker = function(entity, markerMap) { - - // Check current entity position - var pos = blockPosToLatLng(entity.posX, entity.posZ); - if(!map.getBounds().contains(pos)) { - //return; // Don't bother with marker - } - - var id = 'id' + entity.entityId; - var heading = entity.heading; - - var locatorUrl = null; - var iconSize = 32; - var iconColor = "#cccccc"; - var iconLabel = null; - var marker = markerMap[id]; - - var isPet = (entity.owner!=null && entity.owner!=""); - - if(entity.owner === JM.player.username) { - locatorUrl = "/img/locator-pet.png"; - iconColor = "#0000ff"; - } else if(entity.hostile==true) { - locatorUrl = "/img/locator-hostile.png"; - iconColor = "#ff0000"; - } else { - locatorUrl = "/img/locator-neutral.png"; - } - - if(!showPets && isPet==true) { - locatorUrl = null; - } - - if(!showAnimals && entity.passiveAnimal==true) { - if(!(isPet==true && showPets)) { - locatorUrl = null; - } - } - - // No locator means no marker - if(!locatorUrl) { - if(marker) { - marker.setMap(null); - delete markerMap[id]; - if(debug) console.log("Marker invalid for " + id + " - " + entity.filename); - return; - } else { - //if(debug) console.log("Pending marker invalid for " + id + " - " + entity.filename); - return; - } - } - - // Create marker if needed - if(!marker) { - - var contentDiv = $(entityTemplate).attr('id',id); - - marker = new RichMarker({ - position: pos, - map: map, - draggable: false, - flat: true, - anchor: RichMarkerPosition.MIDDLE, - content: contentDiv[0] - }); - markerMap[id] = marker; - - if(debug) console.log("Marker added for " + id); - } - - // Label if customName exists - var contentDiv = $('#'+id); - - if(entity.customName) { - $(contentDiv).find('.entityName').css('visibility','visible').html(entity.customName); - } else { - $(contentDiv).find('.entityName').css('visibility','hidden').html(); - } - - // Entity icon - $(contentDiv).find('.entityIcon').addClass('entity_' + JM.world.iconSetName).attr('src','/icon/entity/' + JM.world.iconSetName + '/' + entity.filename); - - // Entity locator - $(contentDiv).find('.entityLocator').attr('src', locatorUrl).rotate(heading); - - // Update marker position - marker.setPosition(pos); - }; - - // Draw the location of other players - var drawMultiplayers = function() { - - if (debug) - console.log(">>> " + "drawMultiplayers"); - - // Villagers - removeObsoleteMarkers(JM.players, markers.players); - if (showPlayers === true && JM.players) { - $.each(JM.players, function(index, multiplayer) { - updateMultiplayerMarker(multiplayer,markers.players); - }); - } - - }; - - // Create or update marker - var updateMultiplayerMarker = function(multiplayer, markerMap) { - - // Check current multiplayer position - var pos = blockPosToLatLng(multiplayer.posX, multiplayer.posZ); - - var id = multiplayer.username; - var heading = multiplayer.heading; - var marker = markerMap[id]; - - // Create marker if needed - if(!marker) { - var contentDiv = $(mpTemplate).attr('id',id); - $(contentDiv).find('.mpName').html(id); - $(contentDiv).find('.mpIcon') - .attr('src', multiplayer.filename) - .on('error', function(event){ - if(debug) console.log("Skin not found for " + id); - $(event.target).attr('src', '/img/entity/unknown.png'); - }); - $(contentDiv).find('.mpLocator').rotate(heading); - - marker = new RichMarker({ - position: pos, - map: map, - draggable: false, - flat: true, - anchor: RichMarkerPosition.MIDDLE, - content: contentDiv[0] - }); - markerMap[id] = marker; - - if(debug) console.log("Marker added for " + id); - } - - // Label if customName exists - var contentDiv = $('#'+id); - - // multiplayer locator - $(contentDiv).find('.mpLocator').rotate(heading); - - // Update marker position - marker.setPosition(pos); - }; - - // Draw the location of waypoints - var drawWaypoints = function() { - - if (debug) - console.log(">>> " + "drawWaypoints"); - - - removeObsoleteMarkers(JM.waypoints, markers.waypoints); - - if(!showWaypoints==true || !JM.waypoints) { - return; - } - - $.each(JM.waypoints, function(index, waypoint) { - updateWaypointMarker(waypoint,markers.waypoints); - }); - - }; - - // Create or update marker - var updateWaypointMarker = function(waypoint, markerMap) { - - // Get current waypoint position - var x = dimensionalValue(waypoint.x, waypoint.primaryDimension, JM.player.dimension); - var z = dimensionalValue(waypoint.z, waypoint.primaryDimension, JM.player.dimension); - var pos = blockPosToLatLng(x, z); - - if(!map.getBounds().contains(pos)) { - //return; // Don't bother with marker - // TODO: Put on edge of map as an arrow? - } - - var id = waypoint.id; - waypoint.color = rgbToHex(waypoint.r, waypoint.g, waypoint.b); - - var marker = markerMap[id]; - - if(!marker) { - var icon = { - fillOpacity: 0.85, - scale: 1, - fillColor: waypoint.color, - strokeColor: 'white' - }; - var labelClass = "waypoint"; - - if(waypoint.type=="Death") { - // death point: X marks the spot - icon.path = 'M -10,-10 0,-4 10,-10 14,-8 4,0 14,8 10,10 0,4 -10,10 -14,8 -4,0 -14,-8 z'; - icon.strokeWeight = 1.5; - labelClass = labelClass + " death"; - } else { - // diamond - icon.path = 'M 0,-8 8,0 0,8 -8,0 0,-8 z'; - icon.strokeWeight = 1.5; - labelClass = labelClass; - } - - var title = [ - getMessage('location_text'), - waypoint.x + "," + waypoint.z, - getMessage('elevation_text'), - waypoint.y, - "(" + (waypoint.y >> 4) + ")" - ].join(' '); - - var label = waypoint.name; - var titleSpan = $('').addClass(labelClass).html(label).hide().appendTo(document.body); - var titleWidth = 4 + $(titleSpan).innerWidth()/2; - $(titleSpan).remove(); - //console.log("titleWidth " + titleWidth); - - marker = new MarkerWithLabel({ - position: pos, - map: map, - draggable: false, - clickable: false, - icon: icon, - title: title, - labelContent: label, - labelClass: labelClass, - labelAnchor: new google.maps.Point(titleWidth,40) - }); - markerMap[id] = marker; - - if(debug) console.log("Marker added for " + id); - - } else { - - // Update marker color - if(marker.icon.fillColor!==waypoint.color) { - marker.icon.fillColor = waypoint.color; - marker.setIcon(marker.icon); - } - - //console.log("Setting position of waypoint: ", pos); - marker.setPosition(pos); - } - }; - - var dimensionalValue = function(original, primaryDimension, dimension) { - if(primaryDimension==dimension) - { - return original; - } - else if(primaryDimension==-1) - { - return original*8; - } - else if(dimension==-1) - { - return original/8; - } - else - { - return original; - } - }; - - var getMapStateUrl = function() { - var mapType = (JM.world.features.MapCaves === true && playerUnderground === true && showCaves === true) ? "underground" : (isNightMap === true ? "night" : "day"); - var dimension = (JM.player.dimension); - var depth = (JM.player && JM.player.chunkCoordY != undefined) ? JM.player.chunkCoordY : 4; - return "&mapType=" + mapType + "&dim=" + dimension + "&depth=" + depth + "&ts=" + lastImageCheck; - }; - - var rgbToHex = function(r, g, b) { - return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); - } - - var getURLParameter = function(name) { - return decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]); - } - - debug = ('true' === getURLParameter('debug')); - - /** Google Maps Code **/ - - google.maps.visualRefresh = true; - - var MapConfig = { - tileSize : 512, - defaultZoom : 0, - minZoom : 0, - maxZoom : 5 - } - MapConfig.perPixel = 1.0 / MapConfig.tileSize; - - var blockPosToLatLng = function (x, y) { - var me = this; - var center = .5 * MapConfig.perPixel; - var lat = (y * MapConfig.perPixel) + center; - var lng = (x * MapConfig.perPixel) + center; - return new google.maps.LatLng(lat, lng); - } - - var initMap = function (container) { - - var pos; - if(JM.player && JM.player.posX) { - pos = blockPosToLatLng(JM.player.posX, JM.player.posZ); - } else { - pos = new google.maps.LatLng(0,0); - } - - map = new google.maps.Map(container, { - zoom: MapConfig.defaultZoom, - center: pos, - mapTypeControl: false, - streetViewControl: false, - panControl: true, - panControlOptions: { - position: google.maps.ControlPosition.LEFT_TOP - }, - zoomControl: true, - zoomControlOptions: { - style: google.maps.ZoomControlStyle.AUTO, - position: google.maps.ControlPosition.LEFT_TOP - } - }); - - mapOverlay = new MCMapType(); - map.mapTypes.set('jm', mapOverlay); - map.setMapTypeId('jm'); - - return map; - } - - var MCMapType = function () { - this.loadedTiles = {}; - this.projection = new MCMapProjection(MapConfig.tileSize); - this.tileSize = new google.maps.Size(MapConfig.tileSize,MapConfig.tileSize); - this.minZoom = MapConfig.minZoom; - this.maxZoom = MapConfig.maxZoom; - //this.isPng = true; - }; - - // Adapted from http://code.martinpearman.co.uk/deleteme/MyOverlayMap.js - MCMapType.prototype.getTile = function (coord, zoom, ownerDocument) { - var me = this; - - zoom = Math.floor(zoom); - - while (coord.x > 200) - { - coord.x -= 360; - } - var tileUrl = "/tile?zoom=" + zoom + "&x=" + coord.x + "&z=" + coord.y; - var tileId = 'x_' + coord.x + '_y_' + coord.y + '_zoom_' + zoom; - - var tile = ownerDocument.createElement('div'); - $(tile).css('width', this.tileSize.height + 'px') - .css('width', this.tileSize.height + 'px') - .css('height', this.tileSize.height + 'px') - .attr('data-tileid', tileId); - - if (debug) { - var label = ownerDocument.createElement('span'); - $(label).css('color','white') - .css('float','left') - .html(coord.toString() + " zoom " + zoom); - $(tile).append(label); - } - - var img = $('') - .attr('src', tileUrl += getMapStateUrl()); - - if(img.width()>0) { - $(tile).prepend(img); - } else { - $(img).on('load', function() { - $(tile).prepend(img); - }); - } - - me.loadedTiles[tileId] = { - tile: tile, - tileUrl: tileUrl, - coord: coord, - zoom: zoom - } - - return tile; - }; - - MCMapType.prototype.refreshTile = function(tile) { - var me = this; - - if (debug) console.log(">>> " + "refreshTile " + $(tile).data('tileid')); - - var tileData = me.loadedTiles[$(tile).data('tileid')]; - if(tileData) { - var url = tileData.tileUrl + getMapStateUrl(); - $(tile).find('img').attr('src', url); - } - } - - MCMapType.prototype.refreshTiles = function (force) { - var me = this; - - if(!force) force==false; - if (debug) console.log(">>> " + "refreshTiles: " + force); - - if(force) { - for (var tileId in me.loadedTiles) { - var tileData = me.loadedTiles[tileId]; - var tile = tileData.tile; - me.refreshTile(tile); - } - lastImageCheck = JM.images.queryTime; - return; - } - - if(JM.images.regions.length===0) { - if (debug) console.log("No regions have changed: ", JM.images); - lastImageCheck = JM.images.queryTime || new Date().getTime(); - return; - } - - lastImageCheck = JM.images.queryTime || new Date().getTime(); - - if (debug) { - console.log("Regions changed since ", JM.images.since); - JM.images.regions.forEach(function(region) { - console.log("\t", region); - }); - } - - for (var tileId in me.loadedTiles) { - - var tileData = me.loadedTiles[tileId]; - if(!tileData) continue; - - var tile = tileData.tile; - var zoom = tileData.zoom; - var scale = Math.pow(2,zoom); - var coord = tileData.coord; - - while (coord.x > 200) - { - coord.x -= 360; - } - var tileRegion = [parseInt(coord.x / scale), parseInt(coord.y / scale)]; - - JM.images.regions.forEach(function(region) { - if(tileRegion[0]==region[0] && tileRegion[1]==region[1]) { - if (debug) console.log(" tile " + coord + " zoom " + zoom + " in region: ", tileRegion); - me.refreshTile(tile); - return false; - } else { - if (debug) console.log(" tile " + coord + " zoom " + zoom + " not in region: ", tileRegion); - return true; - } - }); - } - - }; - - MCMapType.prototype.releaseTile = function (tile) { - delete this.loadedTiles[tile.tileId]; - tile = null; - }; - - // Public API for JourneyMap - return { - start : initMessages - }; - -})(); - -/** Custom Map Projection **/ -function MCMapProjection(tileSize) { - this.tileSize = tileSize; - this.inverseTileSize = 1.0 / tileSize; -} - -MCMapProjection.prototype.fromLatLngToPoint = function(latLng) { - var me = this; - var x = latLng.lng() * me.tileSize; - var y = latLng.lat() * me.tileSize; - return new google.maps.Point(x, y); -}; - -MCMapProjection.prototype.fromPointToLatLng = function(point) { - var me = this; - var lng = point.x * me.inverseTileSize; - var lat = point.y * me.inverseTileSize; - return new google.maps.LatLng(lat, lng); -}; - -/** Google Analytics **/ -var _gaq = _gaq || []; -_gaq.push(['_setAccount', 'UA-28839029-1']); -_gaq.push(['_setDomainName', 'none']); -_gaq.push(['_setAllowLinker', true]); -_gaq.push(['_trackPageview']); - -(function() { - var ga = document.createElement('script'); - ga.type = 'text/javascript'; - ga.async = true; - ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(ga, s); -})(); - -function ga_heartbeat(){ - _gaq.push(['_trackEvent', 'heartbeat', 'heartbeat', null, 0, true]); - setTimeout(ga_heartbeat, 5*60*1000); -} -ga_heartbeat(); - -/** String format **/ -if (!String.prototype.format) { - String.prototype.format = function() { - var args = arguments; - return this.replace(/{(\d+)}/g, function(match, number) { - return typeof args[number] != 'undefined' - ? args[number] - : match - ; - }); - }; -} - -/** OnLoad **/ -$( document ).ready(function() { - _gaq.push(['_trackEvent', 'document', 'ready', null, 0, true]); - JourneyMap.start(); -}); - -$(window).unload(function(){ - _gaq.push(['_trackEvent', 'document', 'unload', null, 0, true]); -}); diff --git a/src/main/resources/assets/journeymap/web/js/jquery.rotate.min.js b/src/main/resources/assets/journeymap/web/js/jquery.rotate.min.js deleted file mode 100644 index 512a99f..0000000 --- a/src/main/resources/assets/journeymap/web/js/jquery.rotate.min.js +++ /dev/null @@ -1,22 +0,0 @@ -// VERSION: 2.3 LAST UPDATE: 11.07.2013 -/* - * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - * - * Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009 - * Website: http://code.google.com/p/jqueryrotate/ - */ -(function(k){for(var d,f,l=document.getElementsByTagName("head")[0].style,h=["transformProperty","WebkitTransform","OTransform","msTransform","MozTransform"],g=0;gthis._parameters.duration;if(b&&!this._parameters.animatedGif)clearTimeout(this._timer);else{if(this._canvas||this._vimage||this._img)a=this._parameters.easing(0,a-this._animateStartTime,this._animateStartAngle,this._parameters.animateTo-this._animateStartAngle,this._parameters.duration), -this._rotate(~~(10*a)/10);this._parameters.step&&this._parameters.step(this._angle);var c=this;this._timer=setTimeout(function(){c._animate.call(c)},10)}this._parameters.callback&&b&&(this._angle=this._parameters.animateTo,this._rotate(this._angle),this._parameters.callback.call(this._rootObj))},_rotate:function(){var a=Math.PI/180;return IE?function(a){this._angle=a;this._container.style.rotation=a%360+"deg";this._vimage.style.top=-(this._rotationCenterY-this._imgHeight/2)+"px";this._vimage.style.left= --(this._rotationCenterX-this._imgWidth/2)+"px";this._container.style.top=this._rotationCenterY-this._imgHeight/2+"px";this._container.style.left=this._rotationCenterX-this._imgWidth/2+"px"}:d?function(a){this._angle=a;this._img.style[d]="rotate("+a%360+"deg)";this._img.style[f]=this._parameters.center.join(" ")}:function(b){this._angle=b;b=b%360*a;this._canvas.width=this._width;this._canvas.height=this._height;this._cnv.translate(this._imgWidth*this._aspectW,this._imgHeight*this._aspectH);this._cnv.translate(this._rotationCenterX, -this._rotationCenterY);this._cnv.rotate(b);this._cnv.translate(-this._rotationCenterX,-this._rotationCenterY);this._cnv.scale(this._aspectW,this._aspectH);this._cnv.drawImage(this._img,0,0)}}()};IE&&(Wilq32.PhotoEffect.prototype.createVMLNode=function(){document.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{return!document.namespaces.rvml&&document.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),function(a){return document.createElement("')}}catch(a){return function(a){return document.createElement("<"+ -a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}}())})(jQuery); diff --git a/src/main/resources/assets/journeymap/web/js/markerwithlabel_packed.js b/src/main/resources/assets/journeymap/web/js/markerwithlabel_packed.js deleted file mode 100644 index b15eb45..0000000 --- a/src/main/resources/assets/journeymap/web/js/markerwithlabel_packed.js +++ /dev/null @@ -1 +0,0 @@ -eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7 1G(b,a){7 1u(){};1u.v=a.v;b.2B=a.v;b.v=1b 1u();b.v.3h=b}7 u(c,b,a){2.3=c;2.1L=c.2y;2.6=K.1A("2k");2.6.4.S="Z: 1p; 15: 1P;";2.q=K.1A("2k");2.q.4.S=2.6.4.S;2.q.1M("2A","1d A;");2.q.1M("2w","1d A;");2.U=u.P(b)}1G(u,8.5.3g);u.P=7(b){t a;9(C u.P.1j==="B"){a=K.1A("30");a.4.S="Z: 1p; z-2Y: 2W; M: 13;";a.4.1l="-2P";a.4.1x="-2M";a.2I=b;u.P.1j=a}1d u.P.1j};u.v.2D=7(){t g=2;t m=A;t c=A;t f;t j,1e;t p;t d;t h;t o;t n=20;t i="3p("+2.1L+")";t k=7(e){9(e.2q){e.2q()}e.3l=G;9(e.2n){e.2n()}};t l=7(){g.3.2m(3c)};2.1E().1J.X(2.6);2.1E().36.X(2.q);9(C u.P.2e==="B"){2.1E().1J.X(2.U);u.P.2e=G}2.1t=[8.5.r.O(2.q,"2c",7(e){9(g.3.R()||g.3.W()){2.4.19="25";8.5.r.D(g.3,"2c",e)}}),8.5.r.O(2.q,"21",7(e){9((g.3.R()||g.3.W())&&!c){2.4.19=g.3.2V();8.5.r.D(g.3,"21",e)}}),8.5.r.O(2.q,"1X",7(e){c=A;9(g.3.R()){m=G;2.4.19=i}9(g.3.R()||g.3.W()){8.5.r.D(g.3,"1X",e);k(e)}}),8.5.r.O(K,"1s",7(a){t b;9(m){m=A;g.q.4.19="25";8.5.r.D(g.3,"1s",a)}9(c){9(d){b=g.Y().1v(g.3.Q());b.y+=n;g.3.J(g.Y().1S(b));2O{g.3.2m(8.5.2N.2L);2J(l,2H)}2E(e){}}g.U.4.M="13";g.3.11(f);p=G;c=A;a.L=g.3.Q();8.5.r.D(g.3,"1N",a)}}),8.5.r.w(g.3.1g(),"2C",7(a){t b;9(m){9(c){a.L=1b 8.5.2z(a.L.1f()-j,a.L.1i()-1e);b=g.Y().1v(a.L);9(d){g.U.4.14=b.x+"H";g.U.4.T=b.y+"H";g.U.4.M="";b.y-=n}g.3.J(g.Y().1S(b));9(d){g.q.4.T=(b.y+n)+"H"}8.5.r.D(g.3,"1K",a)}V{j=a.L.1f()-g.3.Q().1f();1e=a.L.1i()-g.3.Q().1i();f=g.3.1c();h=g.3.Q();o=g.3.1g().2x();d=g.3.F("16");c=G;g.3.11(1I);a.L=g.3.Q();8.5.r.D(g.3,"1H",a)}}}),8.5.r.O(K,"2v",7(e){9(c){9(e.3r===27){d=A;g.3.J(h);g.3.1g().3q(o);8.5.r.D(K,"1s",e)}}}),8.5.r.O(2.q,"2u",7(e){9(g.3.R()||g.3.W()){9(p){p=A}V{8.5.r.D(g.3,"2u",e);k(e)}}}),8.5.r.O(2.q,"2s",7(e){9(g.3.R()||g.3.W()){8.5.r.D(g.3,"2s",e);k(e)}}),8.5.r.w(2.3,"1H",7(a){9(!c){d=2.F("16")}}),8.5.r.w(2.3,"1K",7(a){9(!c){9(d){g.J(n);g.6.4.N=1I+(2.F("17")?-1:+1)}}}),8.5.r.w(2.3,"1N",7(a){9(!c){9(d){g.J(0)}}}),8.5.r.w(2.3,"3o",7(){g.J()}),8.5.r.w(2.3,"3n",7(){g.11()}),8.5.r.w(2.3,"3m",7(){g.18()}),8.5.r.w(2.3,"3j",7(){g.18()}),8.5.r.w(2.3,"3i",7(){g.1C()}),8.5.r.w(2.3,"3f",7(){g.1y()}),8.5.r.w(2.3,"3e",7(){g.1z()}),8.5.r.w(2.3,"3d",7(){g.1a()}),8.5.r.w(2.3,"3b",7(){g.1a()})]};u.v.3a=7(){t i;2.6.2j.2i(2.6);2.q.2j.2i(2.q);2h(i=0;i<2.1t.39;i++){8.5.r.38(2.1t[i])}};u.v.37=7(){2.1y();2.1C();2.1a()};u.v.1y=7(){t a=2.3.F("1w");9(C a.35==="B"){2.6.12=a;2.q.12=2.6.12}V{2.6.12="";2.6.X(a);a=a.34(G);2.q.X(a)}};u.v.1C=7(){2.q.33=2.3.32()||""};u.v.1a=7(){t i,E;2.6.1r=2.3.F("1q");2.q.1r=2.6.1r;2.6.4.S="";2.q.4.S="";E=2.3.F("E");2h(i 31 E){9(E.2Z(i)){2.6.4[i]=E[i];2.q.4[i]=E[i]}}2.2b()};u.v.2b=7(){2.6.4.Z="1p";2.6.4.15="1P";9(C 2.6.4.I!=="B"&&2.6.4.I!==""){2.6.4.2a="\\"29:28.26.2f(I="+(2.6.4.I*24)+")\\"";2.6.4.23="22(I="+(2.6.4.I*24)+")"}2.q.4.Z=2.6.4.Z;2.q.4.15=2.6.4.15;2.q.4.I=0.2X;2.q.4.2a="\\"29:28.26.2f(I=1)\\"";2.q.4.23="22(I=1)";2.1z();2.J();2.18()};u.v.1z=7(){t a=2.3.F("1o");2.6.4.1l=-a.x+"H";2.6.4.1x=-a.y+"H";2.q.4.1l=-a.x+"H";2.q.4.1x=-a.y+"H"};u.v.J=7(a){t b=2.Y().1v(2.3.Q());9(C a==="B"){a=0}2.6.4.14=1Z.1Y(b.x)+"H";2.6.4.T=1Z.1Y(b.y-a)+"H";2.q.4.14=2.6.4.14;2.q.4.T=2.6.4.T;2.11()};u.v.11=7(){t a=(2.3.F("17")?-1:+1);9(C 2.3.1c()==="B"){2.6.4.N=2U(2.6.4.T,10)+a;2.q.4.N=2.6.4.N}V{2.6.4.N=2.3.1c()+a;2.q.4.N=2.6.4.N}};u.v.18=7(){9(2.3.F("1n")){2.6.4.M=2.3.2T()?"2S":"13"}V{2.6.4.M="13"}2.q.4.M=2.6.4.M};7 1m(a){a=a||{};a.1w=a.1w||"";a.1o=a.1o||1b 8.5.2R(0,0);a.1q=a.1q||"2Q";a.E=a.E||{};a.17=a.17||A;9(C a.1n==="B"){a.1n=G}9(C a.16==="B"){a.16=G}9(C a.2d==="B"){a.2d=G}9(C a.1W==="B"){a.1W=A}9(C a.1B==="B"){a.1B=A}a.1k=a.1k||"1V"+(K.1U.1T==="2g:"?"s":"")+"://5.1R.1Q/2t/2l/2o/2K.3k";a.1F=a.1F||"1V"+(K.1U.1T==="2g:"?"s":"")+"://5.1R.1Q/2t/2l/2o/2G.2F";a.1B=A;2.2p=1b u(2,a.1k,a.1F);8.5.1D.1O(2,2r)}1G(1m,8.5.1D);1m.v.1h=7(a){8.5.1D.v.1h.1O(2,2r);2.2p.1h(a)};',62,214,'||this|marker_|style|maps|labelDiv_|function|google|if|||||||||||||||||eventDiv_|event||var|MarkerLabel_|prototype|addListener||||false|undefined|typeof|trigger|labelStyle|get|true|px|opacity|setPosition|document|latLng|display|zIndex|addDomListener|getSharedCross|getPosition|getDraggable|cssText|top|crossDiv_|else|getClickable|appendChild|getProjection|position||setZIndex|innerHTML|none|left|overflow|raiseOnDrag|labelInBackground|setVisible|cursor|setStyles|new|getZIndex|return|cLngOffset|lat|getMap|setMap|lng|crossDiv|crossImage|marginLeft|MarkerWithLabel|labelVisible|labelAnchor|absolute|labelClass|className|mouseup|listeners_|tempCtor|fromLatLngToDivPixel|labelContent|marginTop|setContent|setAnchor|createElement|optimized|setTitle|Marker|getPanes|handCursor|inherits|dragstart|1000000|overlayImage|drag|handCursorURL_|setAttribute|dragend|apply|hidden|com|gstatic|fromDivPixelToLatLng|protocol|location|http|draggable|mousedown|round|Math||mouseout|alpha|filter|100|pointer|Microsoft||DXImageTransform|progid|MsFilter|setMandatoryStyles|mouseover|clickable|processed|Alpha|https|for|removeChild|parentNode|div|en_us|setAnimation|stopPropagation|mapfiles|label|preventDefault|arguments|dblclick|intl|click|keydown|ondragstart|getCenter|handCursorURL|LatLng|onselectstart|superClass_|mousemove|onAdd|catch|cur|closedhand_8_8|1406|src|setTimeout|drag_cross_67_16|BOUNCE|9px|Animation|try|8px|markerLabels|Point|block|getVisible|parseInt|getCursor|1000002|01|index|hasOwnProperty|img|in|getTitle|title|cloneNode|nodeType|overlayMouseTarget|draw|removeListener|length|onRemove|labelstyle_changed|null|labelclass_changed|labelanchor_changed|labelcontent_changed|OverlayView|constructor|title_changed|labelvisible_changed|png|cancelBubble|visible_changed|zindex_changed|position_changed|url|setCenter|keyCode'.split('|'),0,{})) \ No newline at end of file diff --git a/src/main/resources/assets/journeymap/web/js/paintbrush.min.js b/src/main/resources/assets/journeymap/web/js/paintbrush.min.js deleted file mode 100644 index 2194a3a..0000000 --- a/src/main/resources/assets/journeymap/web/js/paintbrush.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/* common */ -function addLoadEvent(a){var b=window.onload;"function"!=typeof window.onload?window.onload=a:window.onload=function(){b&&b(),a()}}function supports_canvas(){return!!document.createElement("canvas").getContext}function gaussianBlur(a,b,c){var d=a.width,e=d<<2,f=a.height;if(b){var h,g=b.data;c<0&&(c=0),h=c>=2.5?.98711*c-.9633:c>=.5?3.97156-4.14554*Math.sqrt(1-.26891*c):2*c*(3.97156-4.14554*Math.sqrt(.865545));for(var i=h*h,j=i*h,k=1.57825+2.44413*h+1.4281*i+.422205*j,l=(2.44413*h+2.85619*i+1.26661*j)/k,m=-(1.4281*i+1.26661*j)/k,n=.422205*j/k,o=1-(l+m+n),p=0;p<3;p++)for(var q=0;q=s;r-=4)t=o*g[r]+l*u+m*v+n*w,g[r]=t,w=v,v=u,u=t}for(var p=0;p<3;p++)for(var x=0;x=s;r-=e)t=o*g[r]+l*u+m*v+n*w,g[r]=t,w=v,v=u,u=t}return b}}function removeClass(a,b){if(hasClass(a,b)){var c=new RegExp("(\\s|^)"+b+"(\\s|$)");a.className=a.className.replace(c," ")}}function addClass(a,b){this.hasClass(a,b)||(a.className+=" "+b)}function hasClass(a,b){return a.className.match(new RegExp("(\\s|^)"+b+"(\\s|$)"))}var getElementsByClassName=function(a,b,c){return(getElementsByClassName=document.getElementsByClassName?function(a,b,c){c=c||document;for(var g,d=c.getElementsByClassName(a),e=b?new RegExp("\\b"+b+"\\b","i"):null,f=[],h=0,i=d.length;h>16,g:(65280&n)>>8,b:255&n};if("filter-blur"!=a&&"filter-emboss"!=a&&"filter-matrix"!=a&&"filter-sharpen"!=a)for(var p=0,q=l.data,r=q.length;p>2;p++){var s=p<<2,t={r:q[s],g:q[s+1],b:q[s+2]};l=i(a,c,b,l,s,t,o)}g.putImageData(l,0,0),stashOriginal(b,k,h,f)}}}function i(a,b,c,d,e,f,g){var i,h=d.data,j=c.width;switch(a){case"filter-greyscale":i=.21*f.r+.71*f.g+.07*f.b,h=setRGB(h,e,findColorDifference(b.greyscaleOpacity,i,f.r),findColorDifference(b.greyscaleOpacity,i,f.g),findColorDifference(b.greyscaleOpacity,i,f.b));break;case"filter-mosaic":var k=e>>2,l=Math.floor(k/j),o=l%b.mosaicSize,p=k-l*j,q=p%b.mosaicSize;o&&(k-=o*j),q&&(k-=q),k<<=2,h=setRGB(h,e,findColorDifference(b.mosaicOpacity,h[k],f.r),findColorDifference(b.mosaicOpacity,h[k+1],f.g),findColorDifference(b.mosaicOpacity,h[k+2],f.b));break;case"filter-noise":i=m(b.noiseAmount),h="mono"==b.noiseType||"monochrome"==b.noiseType?setRGB(h,e,n(f.r+i),n(f.g+i),n(f.b+i)):setRGB(h,e,n(f.r+m(b.noiseAmount)),n(f.g+m(b.noiseAmount)),n(f.b+m(b.noiseAmount)));break;case"filter-posterize":h=setRGB(h,e,findColorDifference(b.posterizeOpacity,parseInt(b.posterizeValues*parseInt(f.r/b.posterizeAreas)),f.r),findColorDifference(b.posterizeOpacity,parseInt(b.posterizeValues*parseInt(f.g/b.posterizeAreas)),f.g),findColorDifference(b.posterizeOpacity,parseInt(b.posterizeValues*parseInt(f.b/b.posterizeAreas)),f.b));break;case"filter-sepia":h=setRGB(h,e,findColorDifference(b.sepiaOpacity,.393*f.r+.769*f.g+.189*f.b,f.r),findColorDifference(b.sepiaOpacity,.349*f.r+.686*f.g+.168*f.b,f.g),findColorDifference(b.sepiaOpacity,.272*f.r+.534*f.g+.131*f.b,f.b));break;case"filter-tint":h=setRGB(h,e,findColorDifference(b.tintOpacity,g.r,f.r),findColorDifference(b.tintOpacity,g.g,f.g),findColorDifference(b.tintOpacity,g.b,f.b))}return d}function j(a,b,d,e){var f=document.createElement("canvas"),g=f.getContext("2d");g.width=f.width=a.width,g.height=f.height=a.height,g.drawImage(a,0,0,a.width,a.height);for(var h=g.getImageData(0,0,c.width,c.height),i=b.data,j=h.data,k=a.width,m=Math.sqrt(d.length),n=Math.floor(m/2),o=1;o>1)-Math.random()*a)}function n(a){return a<0?0:a>255?255:a}var d=getElementsByClassName(a.toLowerCase());for(var e in d){var f=getFilterParameters(d[e]),g=getReferenceImage(d[e]);g.onLoad=h(a,g,f,d,e,b,c)}}function getFilterParameters(a){var b={blurAmount:1,edgesAmount:1,embossAmount:.25,greyscaleOpacity:1,matrixAmount:1,mosaicOpacity:1,mosaicSize:5,noiseAmount:30,noiseType:"mono",posterizeAmount:5,posterizeOpacity:1,sepiaOpacity:1,sharpenAmount:.25,tintColor:"#FFF",tintOpacity:.3};for(var c in b){var d=c.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}),e=a.getAttribute("data-pb-"+d);e&&(b[c]=e)}return b.tintColor=a.getAttribute("data-pb-tint-colour")||b.tintColor,b.posterizeAreas=256/b.posterizeAmount,b.posterizeValues=255/(b.posterizeAmount-1),b}function initializeBuffer(a,b){if(a.clearRect(0,0,a.width,a.height),b.width>0&&b.height>0)try{return a.drawImage(b,0,0,b.width,b.height),a.getImageData(0,0,a.width,a.height)}catch(a){}}function createColor(a){return a=a.replace(/^#/,""),3==a.length&&(a=a.replace(/(.)/g,"$1$1")),a}function findColorDifference(a,b,c){return a*b+(1-a)*c}function setRGB(a,b,c,d,e){return a[b]=c,a[b+1]=d,a[b+2]=e,a}function getReferenceImage(a){if("IMG"==a.nodeName)return a;var b=window.getComputedStyle(a,null).backgroundImage;if(b){var c=new Image;return c.src=b.replace(/['"]/g,"").slice(4,-1),c}return!1}function placeReferenceImage(a,b,c){"IMG"==a.nodeName?c.src=b:a.style.backgroundImage="url("+b+")"}function addAttribute(a,b,c){var d=document.createAttribute(b);return d.nodeValue=c,a.setAttributeNode(d)}function flushDataAttributes(a){for(var b=0;b