diff --git a/build.gradle.kts b/build.gradle.kts index 1b01060..d1d9606 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - java - `java-library` - id("com.diffplug.spotless") version "6.1.2" + java + `java-library` + id("com.diffplug.spotless") version "6.1.2" } group = "de.bluecolored.bluemap.api" @@ -11,46 +11,47 @@ version = apiVersion val javaTarget = 11 java { - sourceCompatibility = JavaVersion.toVersion(javaTarget) - targetCompatibility = JavaVersion.toVersion(javaTarget) + sourceCompatibility = JavaVersion.toVersion(javaTarget) + targetCompatibility = JavaVersion.toVersion(javaTarget) } repositories { - mavenCentral() + mavenCentral() } dependencies { - api ("com.flowpowered:flow-math:1.0.3") + api ("com.flowpowered:flow-math:1.0.3") + implementation ("com.google.code.gson:gson:2.8.0") + compileOnly ("org.jetbrains:annotations:23.0.0") } spotless { - java { - target ("src/*/java/**/*.java") + java { + target ("src/*/java/**/*.java") - licenseHeaderFile("LICENSE_HEADER") - indentWithSpaces() - trimTrailingWhitespace() - } + licenseHeaderFile("LICENSE_HEADER") + indentWithSpaces() + trimTrailingWhitespace() + } } tasks.withType(JavaCompile::class).configureEach { - options.apply { - encoding = "utf-8" - } + options.apply { + encoding = "utf-8" + } } tasks.withType(AbstractArchiveTask::class).configureEach { - isReproducibleFileOrder = true - isPreserveFileTimestamps = false + isReproducibleFileOrder = true + isPreserveFileTimestamps = false } tasks.javadoc { - options { - (this as? StandardJavadocDocletOptions)?.apply { - links( - "https://docs.oracle.com/javase/8/docs/api/", - "https://javadoc.io/doc/com.flowpowered/flow-math/1.0.3/" - ) - } - } + options { + (this as? StandardJavadocDocletOptions)?.apply { + links( + "https://docs.oracle.com/javase/8/docs/api/" + ) + } + } } diff --git a/gradle.properties b/gradle.properties index baa2ad2..85551c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -apiVersion=1.7.0 +apiVersion=2.0.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e589..41dfb87 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/de/bluecolored/bluemap/api/BlueMapAPI.java b/src/main/java/de/bluecolored/bluemap/api/BlueMapAPI.java index 2df8c85..bb60312 100644 --- a/src/main/java/de/bluecolored/bluemap/api/BlueMapAPI.java +++ b/src/main/java/de/bluecolored/bluemap/api/BlueMapAPI.java @@ -24,13 +24,9 @@ */ package de.bluecolored.bluemap.api; -import com.flowpowered.math.vector.Vector2i; -import de.bluecolored.bluemap.api.marker.Marker; -import de.bluecolored.bluemap.api.marker.MarkerAPI; -import de.bluecolored.bluemap.api.renderer.RenderAPI; - -import java.awt.image.BufferedImage; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ExecutionException; @@ -41,27 +37,48 @@ *

This API is thread-save, so you can use it async, off the main-server-thread, to save performance!

*/ public abstract class BlueMapAPI { - private static BlueMapAPI instance; - @Deprecated - private static final Collection listener = new HashSet<>(2); + @SuppressWarnings("unused") + private static final String VERSION, GIT_HASH, GIT_CLEAN; + static { + String version = "DEV", gitHash = "DEV", gitClean = "DEV"; + URL url = BlueMapAPI.class.getResource("/de/bluecolored/bluemap/api/version"); + if (url != null) { + try (InputStream in = url.openStream(); Scanner scanner = new Scanner(in)) { + version = scanner.nextLine(); + gitHash = scanner.nextLine(); + gitClean = scanner.nextLine(); + } catch (IOException ex) { + System.err.println("Failed to load version from resources!"); + ex.printStackTrace(); + } + } + + if (version.equals("${version}")) version = "DEV"; + if (gitHash.equals("${gitHash}")) version = "DEV"; + if (gitClean.equals("${gitClean}")) version = "DEV"; + + VERSION = version; + GIT_HASH = gitHash; + GIT_CLEAN = gitClean; + } + + private static BlueMapAPI instance; private static final Collection> onEnableConsumers = new HashSet<>(2); private static final Collection> onDisableConsumers = new HashSet<>(2); /** - * Getter for the {@link RenderAPI}. - * @return the {@link RenderAPI} + * Getter for the {@link RenderManager}. + * @return the {@link RenderManager} */ - public abstract RenderAPI getRenderAPI(); + public abstract RenderManager getRenderManager(); /** - * Getter for the {@link MarkerAPI}.
- * Calling this gives you a fresh loaded {@link MarkerAPI}, so you don't have to call {@link MarkerAPI#load()} right away! - * @return the {@link MarkerAPI} - * @throws IOException if there was an IOException loading the marker.json + * Getter for the {@link WebApp}. + * @return the {@link WebApp} */ - public abstract MarkerAPI getMarkerAPI() throws IOException; + public abstract WebApp getWebApp(); /** * Getter for all {@link BlueMapMap}s loaded by BlueMap. @@ -76,17 +93,23 @@ public abstract class BlueMapAPI { public abstract Collection getWorlds(); /** - * Getter for a {@link BlueMapWorld} loaded by BlueMap with the given {@link UUID}. - * - *

See the documentation of {@link BlueMapWorld#getUuid()} for more information about the nature of the worlds {@link UUID}s!

- * - * @see BlueMapWorld#getUuid() - * - * @param uuid the {@link UUID} of the world + * Getter for a {@link BlueMapWorld} loaded by BlueMap. * + * @param world Any object that BlueMap can use to identify a world. + *

+ * This could be: + *

    + *
  • A {@link String} that is the id of the world
  • + *
  • A {@link Path} that is the path to the world-folder
  • + *
  • A Resource-Key object, {@link UUID} or anything that your platform uses to identify worlds
  • + *
  • The actual world-object, any object directly representing the a world on your platform
  • + *
+ * ("Platform" here stands for the mod/plugin-loader or server-implementation you are using, + * e.g. Spigot, Forge, Fabric or Sponge) + *

* @return an {@link Optional} with the {@link BlueMapWorld} if it exists */ - public abstract Optional getWorld(UUID uuid); + public abstract Optional getWorld(Object world); /** * Getter for a {@link BlueMapMap} loaded by BlueMap with the given id. @@ -95,38 +118,6 @@ public abstract class BlueMapAPI { */ public abstract Optional getMap(String id); - /** - * Creates an image-file with the given {@link BufferedImage} somewhere in the web-root, so it can be used in the web-app (e.g. for {@link Marker}-icons). - * - *

The given path is used as file-name and (separated with '/') optional folders to organize the image-files. Do NOT include the file-ending! (e.g. "someFolder/somePOIIcon" will result in a file "somePOIIcon.png" in a folder "someFolder").

- *

If the image file with the given path already exists, it will be replaced.

- * - * @param image the image to create - * @param path the path/name of this image, the separator-char is '/' - * @return the relative address of the image in the web-app, - * which can be used as it is e.g. in the {@link de.bluecolored.bluemap.api.marker.POIMarker#setIcon(String, Vector2i)} method - * @throws IOException If an {@link IOException} is thrown while writing the image - */ - public abstract String createImage(BufferedImage image, String path) throws IOException; - - /** - * Lists all images that are available. This includes all images previously created with the {@link #createImage(BufferedImage, String)} - * function, but might include more. - * @return A map of available images where: - *
    - *
  • the key is the image path how it would be used in the "path" parameter of the {@link #createImage(BufferedImage, String)} method
  • - *
  • and the value is the relative address of the image. The same ones that are returned from the {@link #createImage(BufferedImage, String)} method
  • - *
- * @throws IOException If an {@link IOException} is thrown while reading the images - */ - public abstract Map availableImages() throws IOException; - - /** - * Getter for the configured web-root folder - * @return The {@link Path} of the web-root folder - */ - public abstract Path getWebRoot(); - /** * Getter for the installed BlueMap version * @return the version-string @@ -134,30 +125,11 @@ public abstract class BlueMapAPI { public abstract String getBlueMapVersion(); /** - * Register a listener that will be called when the API enables/disables - * @param listener the {@link BlueMapAPIListener} - * - * @deprecated Implementing {@link BlueMapAPIListener} can cause a ClassNotFoundException when you soft-depend on BlueMap and your plugin/mod gets used without BlueMap. - * Use {@link BlueMapAPI#onEnable(Consumer)} and {@link BlueMapAPI#onDisable(Consumer)} instead. + * Getter for the installed BlueMapAPI version + * @return the version-string */ - @Deprecated - public static synchronized void registerListener(BlueMapAPIListener listener) { - BlueMapAPI.listener.add(listener); - if (BlueMapAPI.instance != null) listener.onEnable(BlueMapAPI.instance); - } - - /** - * Removes/Unregisters a previously registered listener - * @param listener the {@link BlueMapAPIListener} instance that has been registered previously - * - * @return true if a listener was removed as a result of this call - * - * @deprecated Implementing {@link BlueMapAPIListener} can cause a ClassNotFoundException when you soft-depend on BlueMap and your plugin/mod gets used without BlueMap. - * Use {@link BlueMapAPI#onEnable(Consumer)} and {@link BlueMapAPI#onDisable(Consumer)} instead. - */ - @Deprecated - public static synchronized boolean unregisterListener(BlueMapAPIListener listener) { - return BlueMapAPI.listener.remove(listener); + public String getAPIVersion() { + return VERSION; } /** @@ -206,9 +178,8 @@ public static synchronized boolean unregisterListener(Consumer consu * Used by BlueMap to register the API and call the listeners properly. * @param instance the {@link BlueMapAPI}-instance * @return true if the instance has been registered, false if there already was an instance registered - * @throws ExecutionException if a {@link BlueMapAPIListener} threw an exception during the registration + * @throws ExecutionException if a listener threw an exception during the registration */ - @SuppressWarnings("deprecation") protected static synchronized boolean registerInstance(BlueMapAPI instance) throws ExecutionException { if (BlueMapAPI.instance != null) return false; @@ -224,15 +195,6 @@ protected static synchronized boolean registerInstance(BlueMapAPI instance) thro } } - // backwards compatibility - for (BlueMapAPIListener listener : BlueMapAPI.listener) { - try { - listener.onEnable(BlueMapAPI.instance); - } catch (Throwable ex) { - thrownExceptions.add(ex); - } - } - if (!thrownExceptions.isEmpty()) { ExecutionException ex = new ExecutionException(thrownExceptions.get(0)); for (int i = 1; i < thrownExceptions.size(); i++) { @@ -248,9 +210,8 @@ protected static synchronized boolean registerInstance(BlueMapAPI instance) thro * Used by BlueMap to unregister the API and call the listeners properly. * @param instance the {@link BlueMapAPI} instance * @return true if the instance was unregistered, false if there was no or an other instance registered - * @throws ExecutionException if a {@link BlueMapAPIListener} threw an exception during the un-registration + * @throws ExecutionException if a listener threw an exception during the un-registration */ - @SuppressWarnings("deprecation") protected static synchronized boolean unregisterInstance(BlueMapAPI instance) throws ExecutionException { if (BlueMapAPI.instance != instance) return false; @@ -264,15 +225,6 @@ protected static synchronized boolean unregisterInstance(BlueMapAPI instance) th } } - // backwards compatibility - for (BlueMapAPIListener listener : BlueMapAPI.listener) { - try { - listener.onDisable(BlueMapAPI.instance); - } catch (Exception ex) { - thrownExceptions.add(ex); - } - } - BlueMapAPI.instance = null; if (!thrownExceptions.isEmpty()) { diff --git a/src/main/java/de/bluecolored/bluemap/api/BlueMapAPIListener.java b/src/main/java/de/bluecolored/bluemap/api/BlueMapAPIListener.java deleted file mode 100644 index f351c0c..0000000 --- a/src/main/java/de/bluecolored/bluemap/api/BlueMapAPIListener.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package de.bluecolored.bluemap.api; - -import java.util.function.Consumer; - -/** - * @deprecated Implementing {@link BlueMapAPIListener} can cause a ClassNotFoundException when you soft-depend on BlueMap and your plugin/mod gets used without BlueMap. - * Use {@link BlueMapAPI#onEnable(Consumer)} and {@link BlueMapAPI#onDisable(Consumer)} instead. - */ -@Deprecated -public interface BlueMapAPIListener { - - /** - * Called when BlueMap has been loaded and started and the API is ready to use.
- * If {@link BlueMapAPI} is already enabled when this listener is registered this method will be called immediately (on the same thread)! - *

(Note: This method will likely be called asynchronously, not on the server-thread!

- * @param blueMapApi the {@link BlueMapAPI} - */ - default void onEnable(BlueMapAPI blueMapApi) {} - - /** - * Called before BlueMap is being unloaded and stopped, after this method returns the API is no longer usable!
- * Unlike {@link BlueMapAPIListener#onEnable(BlueMapAPI)}, if {@link BlueMapAPI} is not enabled when this listener is registered this method will not be called immediately. - *

(Note: This method will likely be called asynchronously, not on the server-thread!

- * @param blueMapApi the {@link BlueMapAPI} - */ - default void onDisable(BlueMapAPI blueMapApi) {} - -} diff --git a/src/main/java/de/bluecolored/bluemap/api/BlueMapMap.java b/src/main/java/de/bluecolored/bluemap/api/BlueMapMap.java index bd4dd0b..9f9337d 100644 --- a/src/main/java/de/bluecolored/bluemap/api/BlueMapMap.java +++ b/src/main/java/de/bluecolored/bluemap/api/BlueMapMap.java @@ -27,8 +27,9 @@ import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector3d; import com.flowpowered.math.vector.Vector3i; +import de.bluecolored.bluemap.api.marker.MarkerSet; -import java.util.Optional; +import java.util.Map; import java.util.function.Predicate; /** @@ -55,6 +56,13 @@ public interface BlueMapMap { */ BlueMapWorld getWorld(); + /** + * Getter for a (modifiable) {@link Map} of {@link MarkerSet}s with the key being the {@link MarkerSet}'s id. + * Changing this map will change the {@link MarkerSet}s and markers displayed on the web-app for this map. + * @return a {@link Map} of {@link MarkerSet}s. + */ + Map getMarkerSets(); + /** * Getter for the size of all tiles on this map in blocks. * @return the tile-size in blocks @@ -106,7 +114,7 @@ default Vector2i posToTile(double blockX, double blockZ){ Vector2i offset = getTileOffset(); Vector2i size = getTileSize(); - return Vector2i.from( + return new Vector2i( (int) Math.floor((blockX - offset.getX()) / size.getX()), (int) Math.floor((blockZ - offset.getY()) / size.getY()) ); diff --git a/src/main/java/de/bluecolored/bluemap/api/BlueMapWorld.java b/src/main/java/de/bluecolored/bluemap/api/BlueMapWorld.java index 3d9a1b8..a0b002d 100644 --- a/src/main/java/de/bluecolored/bluemap/api/BlueMapWorld.java +++ b/src/main/java/de/bluecolored/bluemap/api/BlueMapWorld.java @@ -26,7 +26,6 @@ import java.nio.file.Path; import java.util.Collection; -import java.util.UUID; /** * This class represents a world loaded by BlueMap. @@ -34,25 +33,10 @@ public interface BlueMapWorld { /** - *

Getter for the {@link UUID} of the world.

- *

- * The {@link UUID}s of this worlds are not guaranteed to be consistent across reloads/restarts! - *

- *

- * Implementation notes:
- * The used UUID highly depends on the implementation - *

- * - * - * - * - * - * - *
Implementations
SpongeThe UUID is equal to the returned UUID by world-instances of the Sponge-API, so you can just use spongeWorld.getUniqueId()
BukkitThe UUID is equal to the returned UUID by world-instances of the Bukkit-API, so you can just use bukkitWorld.getUID()
ForgeThe UUID is randomly generated, and changes on each reload/restart
CLIThe UUID is randomly generated, and changes on each reload/restart
- * - * @return the {@link UUID} of the world + * Getter for the id of this world. + * @return the id of this world */ - UUID getUuid(); + String getId(); /** * Getter for the {@link Path} of this world's save-files (folder). This matches the folder configured in bluemap's config for this map ( world: ). diff --git a/src/main/java/de/bluecolored/bluemap/api/renderer/RenderAPI.java b/src/main/java/de/bluecolored/bluemap/api/RenderManager.java similarity index 51% rename from src/main/java/de/bluecolored/bluemap/api/renderer/RenderAPI.java rename to src/main/java/de/bluecolored/bluemap/api/RenderManager.java index 060b9b1..fb8f6e1 100644 --- a/src/main/java/de/bluecolored/bluemap/api/renderer/RenderAPI.java +++ b/src/main/java/de/bluecolored/bluemap/api/RenderManager.java @@ -22,93 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package de.bluecolored.bluemap.api.renderer; +package de.bluecolored.bluemap.api; import com.flowpowered.math.vector.Vector2i; -import com.flowpowered.math.vector.Vector3i; -import de.bluecolored.bluemap.api.BlueMapMap; -import de.bluecolored.bluemap.api.BlueMapWorld; import java.io.IOException; import java.util.Collection; -import java.util.UUID; /** - * The {@link RenderAPI} is used to schedule tile-renders and process them on a number of different threads. + * The {@link RenderManager} is used to schedule tile-renders and process them on a number of different threads. */ -public interface RenderAPI { - - /** - * Schedules the render of the map-tile at this block position for all maps of this world.
- * If there already is a render scheduled for one of the tiles, a second one will not be created. - * - * @param world the {@link UUID} of the {@link BlueMapWorld} to render - * @param blockPosition a {@link Vector3i} for the block-position to render (the whole map-tiles will be rendered not only that block) - * - * @throws IllegalArgumentException if there is no world loaded with the provided {@link UUID} - */ - @Deprecated - void render(UUID world, Vector3i blockPosition); - - /** - * Schedules the render of the map-tile at this block position for all maps of this world.
- * If there already is a render scheduled for one of the tiles, a second one will not be created. - * - * @param world the {@link BlueMapWorld} to render - * @param blockPosition a {@link Vector3i} for the block-position to render (the whole map-tiles will be rendered not only that block) - */ - @Deprecated - default void render(BlueMapWorld world, Vector3i blockPosition) { - for (BlueMapMap map : world.getMaps()) { - render(map, blockPosition); - } - } - - /** - * Schedules the render of the map-tile at this block position.
- * If there already is a render scheduled for the tile, a second one will not be created. - * - * @param mapId the id of the {@link BlueMapMap} to render - * @param blockPosition a {@link Vector3i} for the block-position to render (the whole map-tile will be rendered not only that block) - * - * @throws IllegalArgumentException if there is no map loaded with the provided mapId - */ - @Deprecated - void render(String mapId, Vector3i blockPosition); - - /** - * Schedules the render of map-tile at this block position and returns the created render-ticket.
- * If there already is a render scheduled for the tile, a second one will not be created. - * - * @param map the {@link BlueMapMap} - * @param blockPosition a {@link Vector3i} for the block-position to render (the whole map-tile will be rendered not only that block) - */ - @Deprecated - default void render(BlueMapMap map, Vector3i blockPosition) { - render(map, map.posToTile(blockPosition)); - } - - /** - * Schedules the render of the map-tile.
- * If there already is a render scheduled for the tile, a second one will not be created. - * - * @param mapId the id of the {@link BlueMapMap} to render - * @param tile a {@link Vector2i} for the tile-position to render - * - * @throws IllegalArgumentException if there is no map loaded with the provided mapId - */ - @Deprecated - void render(String mapId, Vector2i tile); - - /** - * Schedules the render of the map-tile.
- * If there already is a render scheduled for the tile, a second one will not be created. - * - * @param map the {@link BlueMapMap} - * @param tile a {@link Vector2i} for the tile-position to render - */ - @Deprecated - void render(BlueMapMap map, Vector2i tile); +public interface RenderManager { /** * Schedules a task to update the given map. @@ -153,25 +77,34 @@ default boolean scheduleMapUpdateTask(BlueMapMap map) { int renderQueueSize(); /** - * Getter for the count of render threads. + * Getter for the current count of render threads. * @return the count of render threads */ int renderThreadCount(); /** - * Whether this {@link RenderAPI} is currently running or paused. + * Whether this {@link RenderManager} is currently running or stopped. * @return true if this renderer is running */ boolean isRunning(); /** * Starts the renderer if it is not already running. + * The renderer will be started with the configured number of render threads. */ void start(); /** - * Pauses the renderer if it currently is running. + * Starts the renderer if it is not already running. + * The renderer will be started with the given number of render threads. + * @param threadCount the number of render threads to use, + * must be greater than 0 and should be less than or equal to the number of available cpu-cores. */ - void pause(); + void start(int threadCount); + + /** + * Stops the renderer if it currently is running. + */ + void stop(); } diff --git a/src/main/java/de/bluecolored/bluemap/api/WebApp.java b/src/main/java/de/bluecolored/bluemap/api/WebApp.java new file mode 100644 index 0000000..2e86f20 --- /dev/null +++ b/src/main/java/de/bluecolored/bluemap/api/WebApp.java @@ -0,0 +1,55 @@ +package de.bluecolored.bluemap.api; + +import de.bluecolored.bluemap.api.marker.Marker; +import de.bluecolored.bluemap.api.marker.POIMarker; +import com.flowpowered.math.vector.Vector2i; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; +import java.util.UUID; + +public interface WebApp { + + /** + * Getter for the configured web-root folder + * @return The {@link Path} of the web-root folder + */ + Path getWebRoot(); + + /** + * Shows or hides the given player from being shown on the web-app. + * @param player the UUID of the player + * @param visible true if the player-marker should be visible, false if it should be hidden + */ + void setPlayerVisibility(UUID player, boolean visible); + + /** + * Creates an image-file with the given {@link BufferedImage} somewhere in the web-root, so it can be used in the web-app (e.g. for {@link Marker}-icons). + * + *

The given path is used as file-name and (separated with '/') optional folders to organize the image-files. + * Do NOT include the file-ending! (e.g. "someFolder/somePOIIcon" will result in a file "somePOIIcon.png" in a folder "someFolder").

+ *

If the image file with the given path already exists, it will be replaced.

+ * + * @param image the image to create + * @param path the path/name of this image, the separator-char is '/' + * @return the relative address of the image in the web-app, + * which can be used as it is e.g. in the {@link POIMarker#setIcon(String, Vector2i)} method + * @throws IOException If an {@link IOException} is thrown while writing the image + */ + String createImage(BufferedImage image, String path) throws IOException; + + /** + * Lists all images that are available. This includes all images previously created with the {@link #createImage(BufferedImage, String)} + * function, but might include more. + * @return A map of available images where: + *
    + *
  • the key is the image path how it would be used in the "path" parameter of the {@link #createImage(BufferedImage, String)} method
  • + *
  • and the value is the relative address of the image. The same ones that are returned from the {@link #createImage(BufferedImage, String)} method
  • + *
+ * @throws IOException If an {@link IOException} is thrown while reading the images + */ + Map availableImages() throws IOException; + +} diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/DistanceRangedMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/DistanceRangedMarker.java index 5d97660..0a7e145 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/DistanceRangedMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/DistanceRangedMarker.java @@ -24,7 +24,17 @@ */ package de.bluecolored.bluemap.api.marker; -public interface DistanceRangedMarker extends Marker { +import com.flowpowered.math.vector.Vector3d; + +public abstract class DistanceRangedMarker extends Marker { + + private double minDistance, maxDistance; + + public DistanceRangedMarker(String type, String label, Vector3d position) { + super(type, label, position); + this.minDistance = 0.0; + this.maxDistance = 10000000.0; + } /** * Getter for the minimum distance of the camera to the position for this {@link Marker} to be displayed.
@@ -32,7 +42,9 @@ public interface DistanceRangedMarker extends Marker { * * @return the minimum distance for this {@link Marker} to be displayed */ - double getMinDistance(); + public double getMinDistance() { + return minDistance; + } /** * Sets the minimum distance of the camera to the position of the {@link Marker} for it to be displayed.
@@ -40,7 +52,9 @@ public interface DistanceRangedMarker extends Marker { * * @param minDistance the new minimum distance */ - void setMinDistance(double minDistance); + public void setMinDistance(double minDistance) { + this.minDistance = minDistance; + } /** * Getter for the maximum distance of the camera to the position of the {@link Marker} for it to be displayed.
@@ -48,7 +62,9 @@ public interface DistanceRangedMarker extends Marker { * * @return the maximum distance for this {@link Marker} to be displayed */ - double getMaxDistance(); + public double getMaxDistance() { + return maxDistance; + } /** * Sets the maximum distance of the camera to the position of the {@link Marker} for it to be displayed.
@@ -56,6 +72,8 @@ public interface DistanceRangedMarker extends Marker { * * @param maxDistance the new maximum distance */ - void setMaxDistance(double maxDistance); + public void setMaxDistance(double maxDistance) { + this.maxDistance = maxDistance; + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/ExtrudeMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/ExtrudeMarker.java index 549e5f6..793bc90 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/ExtrudeMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/ExtrudeMarker.java @@ -24,30 +24,84 @@ */ package de.bluecolored.bluemap.api.marker; -import java.awt.*; +import com.flowpowered.math.vector.Vector2d; +import com.flowpowered.math.vector.Vector3d; +import de.bluecolored.bluemap.api.math.Color; -public interface ExtrudeMarker extends ObjectMarker, DistanceRangedMarker { +import java.util.Objects; + +public class ExtrudeMarker extends ObjectMarker { + + private Shape shape; + private float shapeMinY, shapeMaxY; + private boolean depthTest = true; + private int lineWidth = 2; + private Color lineColor = new Color(255, 0, 0, 1f); + private Color fillColor = new Color(200, 0, 0, 0.3f); + + /** + * Creates a new {@link ExtrudeMarker}. + *

(The position of the marker will be the center of the shape (it's bounding box))

+ * + * @param label the label of the marker + * @param shape the {@link Shape} of the marker + * @param shapeMinY the minimum y-position of the extruded shape + * @param shapeMaxY the maximum y-position of the extruded shape + * + * @see #setLabel(String) + * @see #setShape(Shape, float, float) + */ + public ExtrudeMarker(String label, Shape shape, float shapeMinY, float shapeMaxY) { + this(label, calculateShapeCenter(Objects.requireNonNull(shape, "shape must not be null"), shapeMinY, shapeMaxY), shape, shapeMinY, shapeMaxY); + } + + /** + * Creates a new {@link ExtrudeMarker}. + *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

+ * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param shape the shape of the marker + * @param shapeMinY the minimum y-position of the extruded shape + * @param shapeMaxY the maximum y-position of the extruded shape + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setShape(Shape, float, float) + */ + public ExtrudeMarker(String label, Vector3d position, Shape shape, float shapeMinY, float shapeMaxY) { + super("extrude", label, position); + this.shape = Objects.requireNonNull(shape, "shape must not be null"); + this.shapeMinY = shapeMinY; + this.shapeMaxY = shapeMaxY; + } /** * Getter for {@link Shape} of this {@link ExtrudeMarker}. *

The shape is placed on the xz-plane of the map, so the y-coordinates of the {@link Shape}'s points are the z-coordinates in the map.

* @return the {@link Shape} */ - Shape getShape(); + public Shape getShape() { + return shape; + } /** * Getter for the minimum height (y-coordinate) of where the shape is displayed on the map.
* (The shape will be extruded from this value to {@link #getShapeMaxY()} on the map) * @return the min-height of the shape on the map */ - float getShapeMinY(); + public float getShapeMinY() { + return shapeMinY; + } /** * Getter for the maximum height (y-coordinate) of where the shape is displayed on the map. * (The shape will be extruded from {@link #getShapeMinY()} to this value on the map) * @return the max-height of the shape on the map */ - float getShapeMaxY(); + public float getShapeMaxY() { + return shapeMaxY; + } /** * Sets the {@link Shape} of this {@link ExtrudeMarker}. @@ -56,56 +110,86 @@ public interface ExtrudeMarker extends ObjectMarker, DistanceRangedMarker { * @param shape the new {@link Shape} * @param minY the new min-height (y-coordinate) of the shape on the map * @param maxY the new max-height (y-coordinate) of the shape on the map + * + * @see #centerPosition() */ - void setShape(Shape shape, float minY, float maxY); + public void setShape(Shape shape, float minY, float maxY) { + this.shape = Objects.requireNonNull(shape, "shape must not be null"); + this.shapeMinY = minY; + this.shapeMaxY = maxY; + } + + /** + * Sets the position of this {@link ExtrudeMarker} to the center of the {@link Shape} (it's bounding box). + *

(Invoke this after changing the {@link Shape} to make sure the markers position gets updated as well)

+ */ + public void centerPosition() { + setPosition(calculateShapeCenter(shape, shapeMinY, shapeMaxY)); + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @return true if the depthTest is enabled */ - boolean isDepthTestEnabled(); + public boolean isDepthTestEnabled() { + return depthTest; + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @param enabled if the depth-test should be enabled for this {@link ExtrudeMarker} */ - void setDepthTestEnabled(boolean enabled); + public void setDepthTestEnabled(boolean enabled) { + this.depthTest = enabled; + } /** * Getter for the width of the lines of this {@link ExtrudeMarker}. * @return the width of the lines in pixels */ - int getLineWidth(); + public int getLineWidth() { + return lineWidth; + } /** * Sets the width of the lines for this {@link ExtrudeMarker}. * @param width the new width in pixels */ - void setLineWidth(int width); + public void setLineWidth(int width) { + this.lineWidth = width; + } /** * Getter for the {@link Color} of the border-line of the shape. * @return the line-color */ - Color getLineColor(); + public Color getLineColor() { + return lineColor; + } /** * Sets the {@link Color} of the border-line of the shape. * @param color the new line-color */ - void setLineColor(Color color); + public void setLineColor(Color color) { + this.lineColor = Objects.requireNonNull(color, "color must not be null"); + } /** * Getter for the fill-{@link Color} of the shape. * @return the fill-color */ - Color getFillColor(); + public Color getFillColor() { + return fillColor; + } /** * Sets the fill-{@link Color} of the shape. * @param color the new fill-color */ - void setFillColor(Color color); + public void setFillColor(Color color) { + this.fillColor = Objects.requireNonNull(color, "color must not be null"); + } /** * Sets the border- and fill- color. @@ -114,9 +198,15 @@ public interface ExtrudeMarker extends ObjectMarker, DistanceRangedMarker { * @see #setLineColor(Color) * @see #setFillColor(Color) */ - default void setColors(Color lineColor, Color fillColor) { + public void setColors(Color lineColor, Color fillColor) { setLineColor(lineColor); setFillColor(fillColor); } + private static Vector3d calculateShapeCenter(Shape shape, float shapeMinY, float shapeMaxY) { + Vector2d center = shape.getMin().add(shape.getMax()).mul(0.5); + float centerY = (shapeMinY + shapeMaxY) * 0.5f; + return new Vector3d(center.getX(), centerY, center.getY()); + } + } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/HtmlMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/HtmlMarker.java index fb111d1..1248b45 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/HtmlMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/HtmlMarker.java @@ -24,29 +24,76 @@ */ package de.bluecolored.bluemap.api.marker; -import com.flowpowered.math.vector.Vector2i; -import de.bluecolored.bluemap.api.BlueMapAPI; -public interface HtmlMarker extends Marker, DistanceRangedMarker { +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3d; + +import java.util.Objects; + +/** + * A marker that is a html-element placed somewhere on the map. + */ +public class HtmlMarker extends DistanceRangedMarker { + + private Vector2i anchor; + private String html; + + /** + * Creates a new {@link HtmlMarker}. + * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param html the html-content of the marker + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setHtml(String) + */ + public HtmlMarker(String label, Vector3d position, String html) { + this(label, position, html, new Vector2i(0, 0)); + } + + /** + * Creates a new {@link HtmlMarker}. + * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param html the html-content of the marker + * @param anchor the anchor-point of the html-content + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setHtml(String) + * @see #setAnchor(Vector2i) + */ + public HtmlMarker(String label, Vector3d position, String html, Vector2i anchor) { + super("html", label, position); + this.html = Objects.requireNonNull(html, "html must not be null"); + this.anchor = Objects.requireNonNull(anchor, "anchor must not be null"); + } /** * Getter for the position (in pixels) where the html-element is anchored to the map. * @return the anchor-position in pixels */ - Vector2i getAnchor(); + public Vector2i getAnchor() { + return anchor; + } /** * Sets the position (in pixels) where the html-element is anchored to the map. * @param anchor the anchor-position in pixels */ - void setAnchor(Vector2i anchor); + public void setAnchor(Vector2i anchor) { + this.anchor = Objects.requireNonNull(anchor, "anchor must not be null"); + } /** * Sets the position (in pixels) where the html-element is anchored to the map. * @param x the anchor-x-position in pixels * @param y the anchor-y-position in pixels */ - default void setAnchor(int x, int y) { + public void setAnchor(int x, int y) { setAnchor(new Vector2i(x, y)); } @@ -54,7 +101,9 @@ default void setAnchor(int x, int y) { * Getter for the html-code of this HTML marker * @return the html-code */ - String getHtml(); + public String getHtml() { + return html; + } /** * Sets the html for this {@link HtmlMarker}. @@ -66,6 +115,8 @@ default void setAnchor(int x, int y) { * * @param html the html that will be inserted as the marker. */ - void setHtml(String html); + public void setHtml(String html) { + this.html = Objects.requireNonNull(html, "html must not be null"); + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/Line.java b/src/main/java/de/bluecolored/bluemap/api/marker/Line.java index 2f336c0..5c65daa 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/Line.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/Line.java @@ -25,6 +25,7 @@ package de.bluecolored.bluemap.api.marker; import com.flowpowered.math.vector.Vector3d; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -34,8 +35,9 @@ public class Line { private final Vector3d[] points; - private Vector3d min = null; - private Vector3d max = null; + + @Nullable + private Vector3d min = null, max = null; public Line(Vector3d... points) { if (points.length < 2) throw new IllegalArgumentException("A line has to have at least 2 points!"); diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/LineMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/LineMarker.java index e3a5cf3..33f2437 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/LineMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/LineMarker.java @@ -24,56 +24,125 @@ */ package de.bluecolored.bluemap.api.marker; -import java.awt.*; +import com.flowpowered.math.vector.Vector3d; +import de.bluecolored.bluemap.api.math.Color; -public interface LineMarker extends ObjectMarker, DistanceRangedMarker { +import java.util.Objects; + +public class LineMarker extends ObjectMarker { + + private Line line; + private boolean depthTest = true; + private int lineWidth = 2; + private Color lineColor = new Color(255, 0, 0, 1f); + + /** + * Creates a new {@link LineMarker}. + *

(The position of the marker will be the center of the line (it's bounding box))

+ * + * @param label the label of the marker + * @param line the {@link Line} of the marker + * + * @see #setLabel(String) + * @see #setLine(Line) + */ + public LineMarker(String label, Line line) { + this(label, calculateLineCenter(Objects.requireNonNull(line, "shape must not be null")), line); + } + + /** + * Creates a new {@link LineMarker}. + *

(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)

+ * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param line the {@link Line} of the marker + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setLine(Line) + */ + public LineMarker(String label, Vector3d position, Line line) { + super("extrude", label, position); + this.line = Objects.requireNonNull(line, "line must not be null"); + } /** * Getter for {@link Line} of this {@link LineMarker}. * @return the {@link Line} */ - Line getLine(); + public Line getLine() { + return line; + } /** * Sets the {@link Line} of this {@link LineMarker}. * @param line the new {@link Line} + * + * @see #centerPosition() */ - void setLine(Line line); + public void setLine(Line line) { + this.line = Objects.requireNonNull(line, "line must not be null"); + } + + /** + * Sets the position of this {@link LineMarker} to the center of the {@link Line} (it's bounding box). + *

(Invoke this after changing the {@link Line} to make sure the markers position gets updated as well)

+ */ + public void centerPosition() { + setPosition(calculateLineCenter(line)); + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @return true if the depthTest is enabled */ - boolean isDepthTestEnabled(); + public boolean isDepthTestEnabled() { + return depthTest; + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @param enabled if the depth-test should be enabled for this {@link LineMarker} */ - void setDepthTestEnabled(boolean enabled); + public void setDepthTestEnabled(boolean enabled) { + this.depthTest = enabled; + } /** * Getter for the width of the lines of this {@link LineMarker}. * @return the width of the lines in pixels */ - int getLineWidth(); + public int getLineWidth() { + return lineWidth; + } /** * Sets the width of the lines for this {@link LineMarker}. * @param width the new width in pixels */ - void setLineWidth(int width); + public void setLineWidth(int width) { + this.lineWidth = width; + } /** * Getter for the {@link Color} of the border-line of the shape. * @return the line-color */ - Color getLineColor(); + public Color getLineColor() { + return lineColor; + } /** * Sets the {@link Color} of the border-line of the shape. * @param color the new line-color */ - void setLineColor(Color color); + public void setLineColor(Color color) { + this.lineColor = Objects.requireNonNull(color, "color must not be null"); + } + + private static Vector3d calculateLineCenter(Line line) { + return line.getMin().add(line.getMax()).mul(0.5); + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/LinkMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/LinkMarker.java deleted file mode 100644 index 9a6604e..0000000 --- a/src/main/java/de/bluecolored/bluemap/api/marker/LinkMarker.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package de.bluecolored.bluemap.api.marker; - -import java.util.Optional; - -public interface LinkMarker extends Marker { - - /** - * Gets the link-address of this {@link Marker}.
- * If a link is present, this link will be followed when the user clicks on the marker in the web-app. - * - * @return the {@link Optional} link - */ - Optional getLink(); - - /** - * If this is true the link ({@link #getLink()}) will be opened in a new tab. - * @return whether the link will be opened in a new tab - * @see #getLink() - */ - boolean isNewTab(); - - /** - * Sets the link-address of this {@link Marker}.
- * If a link is present, this link will be followed when the user clicks on the marker in the web-app. - * - * @param link the link, or null to disable the link - * @param newTab whether the link should be opened in a new tab - */ - void setLink(String link, boolean newTab); - - /** - * Removes the link of this {@link Marker}. - */ - void removeLink(); - -} diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/Marker.java b/src/main/java/de/bluecolored/bluemap/api/marker/Marker.java index 6fb21a6..6205f1f 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/Marker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/Marker.java @@ -25,135 +25,84 @@ package de.bluecolored.bluemap.api.marker; import com.flowpowered.math.vector.Vector3d; -import de.bluecolored.bluemap.api.BlueMapMap; -import java.util.Optional; +import java.util.Objects; /** - * A marker that is displayed on one of the maps in the web-app. - *

Each marker has an id that is unique in the {@link MarkerSet} that it is in.

+ * The Base-Class for all markers that can be displayed in the web-app. + * + * @see HtmlMarker + * @see POIMarker + * @see ShapeMarker + * @see ExtrudeMarker + * @see LineMarker */ -public interface Marker { +public abstract class Marker { + + private final String type; + private String label; + private Vector3d position; + + public Marker(String type, String label, Vector3d position) { + this.type = Objects.requireNonNull(type, "type cannot be null"); + this.label = Objects.requireNonNull(label, "label cannot be null"); + this.position = Objects.requireNonNull(position, "position cannot be null"); + } /** - * Getter for the id of this {@link Marker}. - *

The id is unique in the {@link MarkerSet} that this marker is in.

- * @return the id of this {@link Marker} + * Returns the type of the marker. + * @return the type-id of the marker. */ - String getId(); - - /** - * Getter for the {@link BlueMapMap} this {@link Marker} lives in. - * @return the {@link BlueMapMap} this {@link Marker} lives in - */ - BlueMapMap getMap(); - - /** - * Sets the {@link BlueMapMap} this {@link Marker} lives in - * @param map the new {@link BlueMapMap} - */ - void setMap(BlueMapMap map); - - /** - * Getter for the position of where this {@link Marker} lives on the map. - * @return the position of this {@link Marker} - */ - Vector3d getPosition(); - - /** - * Sets the position of where this {@link Marker} lives on the map. - * @param position the new position - */ - void setPosition(Vector3d position); + public String getType() { + return type; + } /** * Getter for the label of this marker. * @return the label of this {@link Marker} */ - String getLabel(); + public String getLabel() { + return label; + } /** * Sets the label of this {@link Marker}. - *

- * Using html-tags in the label is possible but deprecated! - *

- *

- * Important:
- * Html-tags in the label will not be escaped, so you can use them to style the {@link Marker}-labels.
- * Make sure you escape all html-tags from possible user inputs to prevent possible XSS-Attacks on the web-client! - *

+ *

(HTML-Tags will be escaped.)

* * @param label the new label for this {@link Marker} */ - void setLabel(String label); + public void setLabel(String label) { + //escape html-tags + this.label = label + .replace("&", "&") + .replace("<", "<") + .replace(">", ">"); + } /** - * Getter for the minimum distance of the camera to the position ({@link #getPosition()} of the {@link Marker} for it to be displayed.
- * If the camera is closer to this {@link Marker} than this distance, it will be hidden! - * - * @return the minimum distance for this {@link Marker} to be displayed - * @deprecated Not all marker-types support this + * Getter for the position of where this {@link Marker} lives on the map. + * @return the position of this {@link Marker} */ - double getMinDistance(); + public Vector3d getPosition() { + return position; + } /** - * Sets the minimum distance of the camera to the position ({@link #getPosition()} of the {@link Marker} for it to be displayed.
- * If the camera is closer to this {@link Marker} than this distance, it will be hidden! - * - * @param minDistance the new minimum distance - * @deprecated Not all marker-types support this + * Sets the position of where this {@link Marker} lives on the map. + * @param position the new position */ - void setMinDistance(double minDistance); + public void setPosition(Vector3d position) { + this.position = position; + } /** - * Getter for the maximum distance of the camera to the position ({@link #getPosition()} of the {@link Marker} for it to be displayed.
- * If the camera is further to this {@link Marker} than this distance, it will be hidden! - * - * @return the maximum distance for this {@link Marker} to be displayed - * @deprecated Not all marker-types support this + * Sets the position of where this {@link Marker} lives on the map. + * @param x the x-coordinate of the new position + * @param y the y-coordinate of the new position + * @param z the z-coordinate of the new position */ - double getMaxDistance(); - - /** - * Sets the maximum distance of the camera to the position ({@link #getPosition()} of the {@link Marker} for it to be displayed.
- * If the camera is further to this {@link Marker} than this distance, it will be hidden! - * - * @param maxDistance the new maximum distance - * @deprecated Not all marker-types support this - */ - void setMaxDistance(double maxDistance); - - /** - * Gets the link-address of this {@link Marker}.
- * If a link is present, this link will be followed when the user clicks on the marker in the web-app. - * - * @return the {@link Optional} link - * @deprecated Not all marker-types support this - */ - Optional getLink(); - - /** - * If this is true the link ({@link #getLink()}) will be opened in a new tab. - * @return whether the link will be opened in a new tab - * @see #getLink() - * @deprecated Not all marker-types support this - */ - boolean isNewTab(); - - /** - * Sets the link-address of this {@link Marker}.
- * If a link is present, this link will be followed when the user clicks on the marker in the web-app. - * - * @param link the link, or null to disable the link - * @param newTab whether the link should be opened in a new tab - * @deprecated Not all marker-types support this - */ - void setLink(String link, boolean newTab); - - /** - * Removes the link of this {@link Marker}. - * @deprecated Not all marker-types support this - */ - void removeLink(); + public void setPosition(int x, int y, int z) { + setPosition(new Vector3d(x, y, z)); + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/MarkerAPI.java b/src/main/java/de/bluecolored/bluemap/api/marker/MarkerAPI.java deleted file mode 100644 index aef1f44..0000000 --- a/src/main/java/de/bluecolored/bluemap/api/marker/MarkerAPI.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package de.bluecolored.bluemap.api.marker; - -import java.io.IOException; -import java.util.Collection; -import java.util.Optional; - -import de.bluecolored.bluemap.api.BlueMapAPI; - -/** - * The {@link MarkerAPI} for easy manipulation of the markers.json that is used to display different Markers on the map. - *

- * Important:
- * If you made changes to any {@link MarkerSet} or {@link Marker} including creations and deletions, you need to finally save your changes by calling {@link #save()}!
- *

- *

To avoid any concurrent modifications to the markers.json, make sure your {@link MarkerAPI} is always loaded before making any changes, and saved right after the changes.

- * - * @see BlueMapAPI#getMarkerAPI() - */ -public interface MarkerAPI { - - /** - * Getter for an unmodifiable {@link Collection} containing all {@link MarkerSet}s that are currently loaded with BlueMap. - * - * @return a {@link Collection} with all loaded {@link MarkerSet}s - */ - Collection getMarkerSets(); - - /** - * Getter for a loaded {@link MarkerSet} with the given id.
- * Returns an empty {@link Optional} if no {@link MarkerSet} with that id is loaded. - * - * @param id the id of the {@link MarkerSet} - * @return an {@link Optional}<{@link MarkerSet}> with the given id - */ - Optional getMarkerSet(String id); - - /** - * Created a new {@link MarkerSet} with the given id.
- * If there is already a {@link MarkerSet} with that id loaded, no new {@link MarkerSet} is created and the existing one is returned. - * - * @param id the id of the {@link MarkerSet} - * @return a {@link MarkerSet} with the given id - */ - MarkerSet createMarkerSet(String id); - - /** - * Removes the given {@link MarkerSet}.
- * This is equivalent to calling removeMarkerSet(markerSet.getId()). - * - * @param markerSet the {@link MarkerSet} to be removed - * @return true if the {@link MarkerSet} was removed, false if that {@link MarkerSet} didn't exist - */ - default boolean removeMarkerSet(MarkerSet markerSet) { - return removeMarkerSet(markerSet.getId()); - } - - /** - * Removes the {@link MarkerSet} with the given id. - * - * @param id the id of the {@link MarkerSet} to be removed - * @return true if the {@link MarkerSet} was removed, false if there was no {@link MarkerSet} with that id - */ - boolean removeMarkerSet(String id); - - /** - * Loads changes made by others, changes could be from other plugin's using the API or external changes to the markers.json.
- * Calling this will override all unsaved changes you made with this instance! - * - * @throws IOException if an {@link IOException} occurred while loading the markers.json - */ - void load() throws IOException; - - /** - * Saves all changes made with this instance to the markers.json.
- * - * @throws IOException if an {@link IOException} occurred while saving the markers.json - */ - void save() throws IOException; - -} diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/MarkerSet.java b/src/main/java/de/bluecolored/bluemap/api/marker/MarkerSet.java index d20cfee..c174020 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/MarkerSet.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/MarkerSet.java @@ -24,59 +24,83 @@ */ package de.bluecolored.bluemap.api.marker; -import com.flowpowered.math.vector.Vector2d; -import com.flowpowered.math.vector.Vector3d; -import de.bluecolored.bluemap.api.BlueMapMap; - -import java.util.Collection; -import java.util.Optional; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * A set of {@link Marker}s that are displayed on the maps in the web-app. - * - *

Each {@link MarkerSet} has an unique id.

*/ -public interface MarkerSet { +public class MarkerSet { + + private String label; + private boolean toggleable, defaultHidden; + private final Map markers; /** - * Getter for the id of this {@link MarkerSet}. - * @return the id of this {@link MarkerSet} + * Creates a new {@link MarkerSet}. + * + * @param label the label of the {@link MarkerSet} + * + * @see #setLabel(String) */ - String getId(); + public MarkerSet(String label) { + this.label = label; + this.toggleable = true; + this.defaultHidden = false; + this.markers = new ConcurrentHashMap<>(); + } + + /** + * Creates a new {@link MarkerSet}. + * + * @param label the label of the {@link MarkerSet} + * @param toggleable if the {@link MarkerSet} is toggleable + * @param defaultHidden the default visibility of the {@link MarkerSet} + * + * @see #setLabel(String) + * @see #setToggleable(boolean) + * @see #setDefaultHidden(boolean) + */ + public MarkerSet(String label, boolean toggleable, boolean defaultHidden) { + this.label = label; + this.toggleable = toggleable; + this.defaultHidden = defaultHidden; + this.markers = new ConcurrentHashMap<>(); + } /** * Getter for the label of this {@link MarkerSet}. *

The label is used in the web-app to name the toggle-button of this {@link MarkerSet} if it is toggleable. ({@link #isToggleable()})

* @return the label of this {@link MarkerSet} */ - String getLabel(); - + public String getLabel() { + return label; + } /** * Sets the label of this {@link MarkerSet}. *

The label is used in the web-app to name the toggle-button of this {@link MarkerSet} if it is toggleable. ({@link #isToggleable()})

* @param label the new label */ - void setLabel(String label); + public void setLabel(String label) { + this.label = label; + } /** * Checks if the {@link MarkerSet} is toggleable. *

If this is true, the web-app will display a toggle-button for this {@link MarkerSet} so the user can choose to enable/disable all markers of this set.

* @return whether this {@link MarkerSet} is toggleable */ - boolean isToggleable(); + public boolean isToggleable() { + return toggleable; + } /** * Changes if this {@link MarkerSet} is toggleable. *

If this is true, the web-app will display a toggle-button for this {@link MarkerSet} so the user can choose to enable/disable all markers of this set.

* @param toggleable whether this {@link MarkerSet} should be toggleable */ - void setToggleable(boolean toggleable); - - /** - * @deprecated method name has a typo, use {@link #isDefaultHidden()} instead. - */ - default boolean isDefautHidden() { - return isDefaultHidden(); + public void setToggleable(boolean toggleable) { + this.toggleable = toggleable; } /** @@ -86,7 +110,9 @@ default boolean isDefautHidden() { * @return whether this {@link MarkerSet} is hidden by default * @see #isToggleable() */ - boolean isDefaultHidden(); + public boolean isDefaultHidden() { + return defaultHidden; + } /** * Sets if this {@link MarkerSet} is hidden by default. @@ -95,251 +121,18 @@ default boolean isDefautHidden() { * @param defaultHide whether this {@link MarkerSet} should be hidden by default * @see #isToggleable() */ - void setDefaultHidden(boolean defaultHide); - - /** - * Getter for an unmodifiable {@link Collection} of all {@link Marker}s in this {@link MarkerSet}. - * - * @return a {@link Collection} with all {@link Marker}s of this {@link MarkerSet}. - */ - Collection getMarkers(); - - /** - * Getter for a {@link Marker} with the given id.
- * Returns an empty {@link Optional} if no {@link Marker} exists with the given id. - * - * @param id the id of the {@link Marker} - * @return an {@link Optional}<{@link Marker}> with the given id - */ - Optional getMarker(String id); - - /** - * Creates a {@link POIMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a Marker with that id already exists, it will be replaced by the new {@link POIMarker}! - * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param position the position of the new marker - * @return the created {@link POIMarker} - */ - POIMarker createPOIMarker(String id, BlueMapMap map, Vector3d position); - - /** - * Creates a {@link POIMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link POIMarker}! - * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param posX the x-position of the new marker - * @param posY the y-position of the new marker - * @param posZ the z-position of the new marker - * @return the created {@link POIMarker} - */ - default POIMarker createPOIMarker(String id, BlueMapMap map, double posX, double posY, double posZ) { - return createPOIMarker(id, map, new Vector3d(posX, posY, posZ)); - } - - - - /** - * Creates a {@link HtmlMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a Marker with that id already exists, it will be replaced by the new {@link HtmlMarker}! - * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param position the position of the new marker - * @param html the html-content of the new marker - * @return the created {@link HtmlMarker} - */ - HtmlMarker createHtmlMarker(String id, BlueMapMap map, Vector3d position, String html); - - /** - * Creates a {@link HtmlMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link HtmlMarker}! - * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param posX the x-position of the new marker - * @param posY the y-position of the new marker - * @param posZ the z-position of the new marker - * @param html the html-content of the new marker - * @return the created {@link HtmlMarker} - */ - default HtmlMarker createHtmlMarker(String id, BlueMapMap map, double posX, double posY, double posZ, String html) { - return createHtmlMarker(id, map, new Vector3d(posX, posY, posZ), html); + public void setDefaultHidden(boolean defaultHide) { + this.defaultHidden = defaultHide; } /** - * Creates a {@link ShapeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link ShapeMarker}! + * Getter for a (modifiable) {@link Map} of all {@link Marker}s in this {@link MarkerSet}. + * The keys of the map are the id's of the {@link Marker}s. * - *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param position the position of the new marker - * @param shape the Shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @param y the height (y-position on the map) of shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @return the created {@link ShapeMarker} + * @return a {@link Map} of all {@link Marker}s of this {@link MarkerSet}. */ - ShapeMarker createShapeMarker(String id, BlueMapMap map, Vector3d position, Shape shape, float y); - - /** - * Creates a {@link ShapeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a Marker with that id already exists, it will be replaced by the new {@link ShapeMarker}! - * - *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param posX the x-position of the new marker - * @param posY the y-position of the new marker - * @param posZ the z-position of the new marker - * @param shape the Shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @param y the height (y-position on the map) of shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @return the created {@link ShapeMarker} - */ - default ShapeMarker createShapeMarker(String id, BlueMapMap map, double posX, double posY, double posZ, Shape shape, float y) { - return createShapeMarker(id, map, new Vector3d(posX, posY, posZ), shape, y); + public Map getMarkers() { + return markers; } - /** - * Creates a {@link ShapeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a Marker with that id already exists, it will be replaced by the new {@link ShapeMarker}! - * - *

(The position of the marker will be the center of the shape (it's bounding box))

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param shape the Shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @param y the height of shape of the marker (See: {@link ShapeMarker#setShape(Shape, float)}) - * @return the created {@link ShapeMarker} - */ - default ShapeMarker createShapeMarker(String id, BlueMapMap map, Shape shape, float y) { - Vector2d center = shape.getMin().add(shape.getMax()).div(2); - return createShapeMarker(id, map, new Vector3d(center.getX(), y, center.getY()), shape, y); - } - - /** - * Creates a {@link ExtrudeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}! - * - *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param position the position of the new marker - * @param shape the {@link Shape} of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param minY the min-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param maxY the max-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @return the created {@link ExtrudeMarker} - */ - ExtrudeMarker createExtrudeMarker(String id, BlueMapMap map, Vector3d position, Shape shape, float minY, float maxY); - - /** - * Creates a {@link ExtrudeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}! - * - *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param posX the x-position of the new marker - * @param posY the y-position of the new marker - * @param posZ the z-position of the new marker - * @param shape the {@link Shape} of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param minY the min-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param maxY the max-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @return the created {@link ExtrudeMarker} - */ - default ExtrudeMarker createExtrudeMarker(String id, BlueMapMap map, double posX, double posY, double posZ, Shape shape, float minY, float maxY) { - return createExtrudeMarker(id, map, new Vector3d(posX, posY, posZ), shape, minY, maxY); - } - - /** - * Creates a {@link ExtrudeMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}! - * - *

(The position of the marker will be the center of the shape (it's bounding box))

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param shape the {@link Shape} of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param minY the min-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @param maxY the max-height (y-position on the map) of the shape of the marker (See: {@link ExtrudeMarker#setShape(Shape, float, float)}) - * @return the created {@link ExtrudeMarker} - */ - default ExtrudeMarker createExtrudeMarker(String id, BlueMapMap map, Shape shape, float minY, float maxY) { - Vector2d center = shape.getMin().add(shape.getMax()).div(2f); - float y = (minY + maxY)/2f; - return createExtrudeMarker(id, map, new Vector3d(center.getX(), y, center.getY()), shape, minY, maxY); - } - - /** - * Creates a {@link LineMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}! - * - *

(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param position the position of the new marker - * @param line the {@link Line} of the marker (See: {@link LineMarker#setLine(Line)}) - * @return the created {@link LineMarker} - */ - LineMarker createLineMarker(String id, BlueMapMap map, Vector3d position, Line line); - - /** - * Creates a {@link LineMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}! - * - *

(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param posX the x-position of the new marker - * @param posY the y-position of the new marker - * @param posZ the z-position of the new marker - * @param line the {@link Line} of the marker (See: {@link LineMarker#setLine(Line)}) - * @return the created {@link LineMarker} - */ - default LineMarker createLineMarker(String id, BlueMapMap map, double posX, double posY, double posZ, Line line) { - return createLineMarker(id, map, new Vector3d(posX, posY, posZ), line); - } - - /** - * Creates a {@link LineMarker} with the given id and adds it to this {@link MarkerSet}.
- * If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}! - * - *

(The position of the marker will be the center of the line (it's bounding box))

- * - * @param id the id of the new marker - * @param map the {@link BlueMapMap} of the new marker - * @param line the {@link Line} of the marker (See: {@link LineMarker#setLine(Line)}) - * @return the created {@link LineMarker} - */ - default LineMarker createLineMarker(String id, BlueMapMap map, Line line) { - Vector3d center = line.getMin().add(line.getMax()).div(2f); - return createLineMarker(id, map, center, line); - } - - /** - * Removes the given Marker from this {@link MarkerSet}.
- * This is equivalent to calling removeMarker(marker.getId()). - * - * @param marker the {@link Marker} to be removed - * @return true if the {@link Marker} was removed, false if that {@link Marker} didn't exist - */ - default boolean removeMarker(Marker marker) { - return removeMarker(marker.getId()); - } - - /** - * Removes the {@link Marker} with the given id. - * - * @param id the id of the {@link Marker} to be removed - * @return true if the {@link Marker} was removed, false if there was no {@link Marker} with that id - */ - boolean removeMarker(String id); - } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/ObjectMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/ObjectMarker.java index c58cba3..cea4857 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/ObjectMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/ObjectMarker.java @@ -24,13 +24,34 @@ */ package de.bluecolored.bluemap.api.marker; -public interface ObjectMarker extends Marker, LinkMarker { +import com.flowpowered.math.vector.Vector3d; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.Optional; + +public abstract class ObjectMarker extends DistanceRangedMarker { + + private String detail; + + @Nullable + private String link; + private boolean newTab; + + public ObjectMarker(String type, String label, Vector3d position) { + super(type, label, position); + this.detail = Objects.requireNonNull(label, "label must not be null"); + this.link = null; + this.newTab = false; + } /** * Getter for the detail of this marker. The label can include html-tags. * @return the detail of this {@link ObjectMarker} */ - String getDetail(); + public String getDetail() { + return detail; + } /** * Sets the detail of this {@link ObjectMarker}. The detail can include html-tags.
@@ -43,6 +64,47 @@ public interface ObjectMarker extends Marker, LinkMarker { * * @param detail the new detail for this {@link ObjectMarker} */ - void setDetail(String detail); + public void setDetail(String detail) { + this.detail = Objects.requireNonNull(detail); + } + + /** + * Gets the link-address of this {@link Marker}.
+ * If a link is present, this link will be followed when the user clicks on the marker in the web-app. + * + * @return the {@link Optional} link + */ + public Optional getLink() { + return Optional.ofNullable(link); + } + + /** + * If this is true the link ({@link #getLink()}) will be opened in a new tab. + * @return whether the link will be opened in a new tab + * @see #getLink() + */ + public boolean isNewTab() { + return newTab; + } + + /** + * Sets the link-address of this {@link Marker}.
+ * If a link is present, this link will be followed when the user clicks on the marker in the web-app. + * + * @param link the link, or null to disable the link + * @param newTab whether the link should be opened in a new tab + */ + public void setLink(String link, boolean newTab) { + this.link = Objects.requireNonNull(link, "link must not be null"); + this.newTab = newTab; + } + + /** + * Removes the link of this {@link Marker}. + */ + public void removeLink() { + this.link = null; + this.newTab = false; + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/POIMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/POIMarker.java index f25c9fe..94fe97e 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/POIMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/POIMarker.java @@ -25,47 +25,83 @@ package de.bluecolored.bluemap.api.marker; import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3d; +import de.bluecolored.bluemap.api.WebApp; -import de.bluecolored.bluemap.api.BlueMapAPI; +import java.util.Objects; -public interface POIMarker extends Marker, DistanceRangedMarker { +public class POIMarker extends DistanceRangedMarker { + + private String icon; + private Vector2i anchor; + + /** + * Creates a new {@link POIMarker} with the standard icon. + * + * @param label the label of the marker + * @param position the coordinates of the marker + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + */ + public POIMarker(String label, Vector3d position) { + this(label, position, "assets/poi.svg", new Vector2i(25, 45)); + } + + /** + * Creates a new {@link POIMarker}. + * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param iconAddress the html-content of the marker + * @param anchor the anchor-point of the html-content + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setIcon(String, Vector2i) + */ + public POIMarker(String label, Vector3d position, String iconAddress, Vector2i anchor) { + super("poi", label, position); + this.icon = Objects.requireNonNull(iconAddress, "iconAddress must not be null"); + this.anchor = Objects.requireNonNull(anchor, "anchor must not be null"); + } /** * Getter for the relative address of the icon used to display this {@link POIMarker} * @return the relative web-address of the icon */ - String getIconAddress(); - - /** - * Getter for the position (in pixels) where the icon is anchored to the map. - * @return the anchor-position in pixels - * @deprecated Use {@link #getAnchor()} instead - */ - default Vector2i getIconAnchor() { - return getAnchor(); + public String getIconAddress() { + return icon; } /** * Getter for the position (in pixels) where the icon is anchored to the map. * @return the anchor-position in pixels */ - Vector2i getAnchor(); + public Vector2i getAnchor() { + return anchor; + } /** * Sets the icon for this {@link POIMarker}. - * @param iconAddress the web-address of the icon-image. Can be an absolute or relative. You can also use an address returned by {@link BlueMapAPI#createImage(java.awt.image.BufferedImage, String)}. + * @param iconAddress the web-address of the icon-image. Can be an absolute or relative. + * You can also use an address returned by {@link WebApp#createImage(java.awt.image.BufferedImage, String)}. * @param anchorX the x-position of the position (in pixels) where the icon is anchored to the map * @param anchorY the y-position of the position (in pixels) where the icon is anchored to the map */ - default void setIcon(String iconAddress, int anchorX, int anchorY) { + public void setIcon(String iconAddress, int anchorX, int anchorY) { setIcon(iconAddress, new Vector2i(anchorX, anchorY)); } /** * Sets the icon for this {@link POIMarker}. - * @param iconAddress the web-address of the icon-image. Can be an absolute or relative. You can also use an address returned by {@link BlueMapAPI#createImage(java.awt.image.BufferedImage, String)}. + * @param iconAddress the web-address of the icon-image. Can be an absolute or relative. + * You can also use an address returned by {@link WebApp#createImage(java.awt.image.BufferedImage, String)}. * @param anchor the position of the position (in pixels) where the icon is anchored to the map */ - void setIcon(String iconAddress, Vector2i anchor); + public void setIcon(String iconAddress, Vector2i anchor) { + this.icon = Objects.requireNonNull(iconAddress, "iconAddress must not be null"); + this.anchor = Objects.requireNonNull(anchor, "anchor must not be null"); + } } diff --git a/src/main/java/de/bluecolored/bluemap/api/marker/ShapeMarker.java b/src/main/java/de/bluecolored/bluemap/api/marker/ShapeMarker.java index 75dcabf..eed2d9a 100644 --- a/src/main/java/de/bluecolored/bluemap/api/marker/ShapeMarker.java +++ b/src/main/java/de/bluecolored/bluemap/api/marker/ShapeMarker.java @@ -24,105 +24,157 @@ */ package de.bluecolored.bluemap.api.marker; -import java.awt.Color; -public interface ShapeMarker extends ObjectMarker, DistanceRangedMarker { +import com.flowpowered.math.vector.Vector2d; +import com.flowpowered.math.vector.Vector3d; +import de.bluecolored.bluemap.api.math.Color; + +import java.util.Objects; + +public class ShapeMarker extends ObjectMarker { + + private Shape shape; + private float shapeY; + private boolean depthTest = true; + private int lineWidth = 2; + private Color lineColor = new Color(255, 0, 0, 1f); + private Color fillColor = new Color(200, 0, 0, 0.3f); + + /** + * Creates a new {@link ShapeMarker}. + *

(The position of the marker will be the center of the shape (it's bounding box))

+ * + * @param label the label of the marker + * @param shape the {@link Shape} of the marker + * @param shapeY the y-position of the shape + * + * @see #setLabel(String) + * @see #setShape(Shape, float) + */ + public ShapeMarker(String label, Shape shape, float shapeY) { + this(label, calculateShapeCenter(Objects.requireNonNull(shape, "shape must not be null"), shapeY), shape, shapeY); + } + + /** + * Creates a new {@link ShapeMarker}. + *

(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)

+ * + * @param label the label of the marker + * @param position the coordinates of the marker + * @param shape the shape of the marker + * @param shapeY the y-position of the shape + * + * @see #setLabel(String) + * @see #setPosition(Vector3d) + * @see #setShape(Shape, float) + */ + public ShapeMarker(String label, Vector3d position, Shape shape, float shapeY) { + super("shape", label, position); + this.shape = Objects.requireNonNull(shape, "shape must not be null"); + this.shapeY = shapeY; + } /** * Getter for {@link Shape} of this {@link ShapeMarker}. *

The shape is placed on the xz-plane of the map, so the y-coordinates of the {@link Shape}'s points are the z-coordinates in the map.

* @return the {@link Shape} */ - Shape getShape(); - - /** - * Getter for the height (y-coordinate) of where the shape is displayed on the map. - * @return the height of the shape on the map - * @deprecated Use {@link #getShapeY()} instead - */ - default float getHeight() { - return getShapeY(); + public Shape getShape() { + return shape; } /** * Getter for the height (y-coordinate) of where the shape is displayed on the map. * @return the height of the shape on the map */ - float getShapeY(); + public float getShapeY() { + return shapeY; + } /** * Sets the {@link Shape} of this {@link ShapeMarker}. *

The shape is placed on the xz-plane of the map, so the y-coordinates of the {@link Shape}'s points will be the z-coordinates in the map.

* @param shape the new {@link Shape} * @param y the new height (y-coordinate) of the shape on the map + * + * @see #centerPosition() */ - void setShape(Shape shape, float y); + public void setShape(Shape shape, float y) { + this.shape = Objects.requireNonNull(shape, "shape must not be null"); + this.shapeY = y; + } + + /** + * Sets the position of this {@link ShapeMarker} to the center of the {@link Shape} (it's bounding box). + *

(Invoke this after changing the {@link Shape} to make sure the markers position gets updated as well)

+ */ + public void centerPosition() { + setPosition(calculateShapeCenter(shape, shapeY)); + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @return true if the depthTest is enabled */ - boolean isDepthTestEnabled(); + public boolean isDepthTestEnabled() { + return depthTest; + } /** * If the depth-test is disabled, you can see the marker fully through all objects on the map. If it is enabled, you'll only see the marker when it is not behind anything. * @param enabled if the depth-test should be enabled for this {@link ShapeMarker} */ - void setDepthTestEnabled(boolean enabled); + public void setDepthTestEnabled(boolean enabled) { + this.depthTest = enabled; + } /** * Getter for the width of the border-line of this {@link ShapeMarker}. * @return the width of the line in pixels */ - int getLineWidth(); + public int getLineWidth() { + return lineWidth; + } /** * Sets the width of the border-line for this {@link ShapeMarker}. * @param width the new width in pixels */ - void setLineWidth(int width); - - /** - * Getter for the {@link Color} of the border of the shape. - * @return the border-color - * @deprecated Use {@link #getLineColor()} instead - */ - default Color getBorderColor() { - return getLineColor(); - } - - /** - * Sets the {@link Color} of the border of the shape. - * @param color the new border-color - * @deprecated Use {@link #setLineColor(Color)} instead - */ - default void setBorderColor(Color color){ - setLineColor(color); + public void setLineWidth(int width) { + this.lineWidth = width; } /** * Getter for the {@link Color} of the border-line of the shape. * @return the line-color */ - Color getLineColor(); + public Color getLineColor() { + return lineColor; + } /** * Sets the {@link Color} of the border-line of the shape. * @param color the new line-color */ - void setLineColor(Color color); + public void setLineColor(Color color) { + this.lineColor = Objects.requireNonNull(color, "color must not be null"); + } /** * Getter for the fill-{@link Color} of the shape. * @return the fill-color */ - Color getFillColor(); + public Color getFillColor() { + return fillColor; + } /** * Sets the fill-{@link Color} of the shape. * @param color the new fill-color */ - void setFillColor(Color color); + public void setFillColor(Color color) { + this.fillColor = Objects.requireNonNull(color, "color must not be null"); + } /** * Sets the border- and fill- color. @@ -131,9 +183,14 @@ default void setBorderColor(Color color){ * @see #setLineColor(Color) * @see #setFillColor(Color) */ - default void setColors(Color lineColor, Color fillColor) { + public void setColors(Color lineColor, Color fillColor) { setLineColor(lineColor); setFillColor(fillColor); } + private static Vector3d calculateShapeCenter(Shape shape, float shapeY) { + Vector2d center = shape.getMin().add(shape.getMax()).mul(0.5); + return new Vector3d(center.getX(), shapeY, center.getY()); + } + } diff --git a/src/main/java/de/bluecolored/bluemap/api/math/Color.java b/src/main/java/de/bluecolored/bluemap/api/math/Color.java new file mode 100644 index 0000000..60883b9 --- /dev/null +++ b/src/main/java/de/bluecolored/bluemap/api/math/Color.java @@ -0,0 +1,83 @@ +package de.bluecolored.bluemap.api.math; + +import java.util.Objects; + +public class Color { + + private final int r, g, b; + private final float a; + + /** + * Creates a new color with the given red, green and blue values. + * + * @param red the red value in range 0-255 + * @param green the green value in range 0-255 + * @param blue the blue value in range 0-255 + */ + public Color(int red, int green, int blue) { + this(red, green, blue, 1); + } + + /** + * Creates a new color with the given red, green, blue and alpha values. + * + * @param red the red value in range 0-255 + * @param green the green value in range 0-255 + * @param blue the blue value in range 0-255 + * @param alpha the alpha value in range 0-1 + */ + public Color(int red, int green, int blue, float alpha) { + this.r = red; + this.g = green; + this.b = blue; + this.a = alpha; + } + + /** + * Creates a new color from the given integer in the format 0xAARRGGBB. + * @param i the integer to create the color from + */ + public Color(int i) { + this((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF, ((i >> 24) & 0xFF) / 255f); + } + + /** + * The value can be an integer in String-Format (see {@link #Color(int)}) or a string in hexadecimal format + * prefixed with # (css-style: e.g. #f16 becomes #ff1166). + * @param cssColorString The string to parse to a color + * @throws NumberFormatException If the value is not formatted correctly. + */ + public Color(String cssColorString) { + this(parseColorString(Objects.requireNonNull(cssColorString))); + } + + public int getRed() { + return r; + } + public int getGreen() { + return g; + } + + public int getBlue() { + return b; + } + + public float getAlpha() { + return a; + } + + private static int parseColorString(String val) { + if (val.charAt(0) == '#') { + val = val.substring(1); + if (val.length() == 3) val = val + "f"; + if (val.length() == 4) val = "" + val.charAt(0) + val.charAt(0) + val.charAt(1) + val.charAt(1) + val.charAt(2) + val.charAt(2) + val.charAt(3) + val.charAt(3); + if (val.length() == 6) val = val + "ff"; + if (val.length() != 8) throw new NumberFormatException("Invalid color format!"); + val = val.substring(6, 8) + val.substring(0, 6); // move alpha to front + return Integer.parseUnsignedInt(val, 16); + } + + return Integer.parseInt(val); + } + +} diff --git a/src/main/resources/de.bluecolored.bluemap.api/version b/src/main/resources/de.bluecolored.bluemap.api/version new file mode 100644 index 0000000..f048a44 --- /dev/null +++ b/src/main/resources/de.bluecolored.bluemap.api/version @@ -0,0 +1,3 @@ +${version} +${gitHash} +${gitClean} \ No newline at end of file