First changes towards API 2

This commit is contained in:
Lukas Rieger (Blue) 2022-07-05 12:50:26 +02:00
parent 938621deb0
commit 6e9415ee33
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
23 changed files with 845 additions and 915 deletions

View File

@ -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/"
)
}
}
}

View File

@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
apiVersion=1.7.0
apiVersion=2.0.0

View File

@ -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

View File

@ -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 @@
* <p>This API is thread-save, so you <b>can</b> use it async, off the main-server-thread, to save performance!</p>
*/
public abstract class BlueMapAPI {
private static BlueMapAPI instance;
@Deprecated
private static final Collection<BlueMapAPIListener> 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<Consumer<BlueMapAPI>> onEnableConsumers = new HashSet<>(2);
private static final Collection<Consumer<BlueMapAPI>> 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}.<br>
* 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<BlueMapWorld> getWorlds();
/**
* Getter for a {@link BlueMapWorld} loaded by BlueMap with the given {@link UUID}.
*
* <p><i>See the documentation of {@link BlueMapWorld#getUuid()} for more information about the nature of the worlds {@link UUID}s!</i></p>
*
* @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.
* <p>
* <b>This could be:</b>
* <ul>
* <li>A {@link String} that is the id of the world</li>
* <li>A {@link Path} that is the path to the world-folder</li>
* <li>A Resource-Key object, {@link UUID} or anything that your platform uses to identify worlds</li>
* <li>The actual world-object, any object directly representing the a world on your platform</li>
* </ul>
* <i>("Platform" here stands for the mod/plugin-loader or server-implementation you are using,
* e.g. Spigot, Forge, Fabric or Sponge)</i>
* </p>
* @return an {@link Optional} with the {@link BlueMapWorld} if it exists
*/
public abstract Optional<BlueMapWorld> getWorld(UUID uuid);
public abstract Optional<BlueMapWorld> 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<BlueMapMap> 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).
*
* <p>The given <code>path</code> is used as file-name and (separated with '/') optional folders to organize the image-files. Do NOT include the file-ending! (e.g. <code>"someFolder/somePOIIcon"</code> will result in a file "somePOIIcon.png" in a folder "someFolder").</p>
* <p>If the image file with the given path already exists, it will be replaced.</p>
*
* @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:
* <ul>
* <li>the <b>key</b> is the image path how it would be used in the "path" parameter of the {@link #createImage(BufferedImage, String)} method</li>
* <li>and the <b>value</b> is the relative address of the image. The same ones that are returned from the {@link #createImage(BufferedImage, String)} method</li>
* </ul>
* @throws IOException If an {@link IOException} is thrown while reading the images
*/
public abstract Map<String, String> 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 <code>true</code> 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<BlueMapAPI> consu
* Used by BlueMap to register the API and call the listeners properly.
* @param instance the {@link BlueMapAPI}-instance
* @return <code>true</code> if the instance has been registered, <code>false</code> 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 <code>true</code> if the instance was unregistered, <code>false</code> 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()) {

View File

@ -1,52 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* 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.<br>
* If {@link BlueMapAPI} is already enabled when this listener is registered this method will be called immediately <i>(on the same thread)</i>!
* <p><i>(Note: This method will likely be called asynchronously, <b>not</b> on the server-thread!</i></p>
* @param blueMapApi the {@link BlueMapAPI}
*/
default void onEnable(BlueMapAPI blueMapApi) {}
/**
* Called <b>before</b> BlueMap is being unloaded and stopped, after this method returns the API is no longer usable!<br>
* Unlike {@link BlueMapAPIListener#onEnable(BlueMapAPI)}, if {@link BlueMapAPI} is not enabled when this listener is registered this method will <b>not</b> be called immediately.
* <p><i>(Note: This method will likely be called asynchronously, <b>not</b> on the server-thread!</i></p>
* @param blueMapApi the {@link BlueMapAPI}
*/
default void onDisable(BlueMapAPI blueMapApi) {}
}

View File

@ -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<String, MarkerSet> 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())
);

View File

@ -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 {
/**
* <p>Getter for the {@link UUID} of the world.</p>
* <p>
* The {@link UUID}s of this worlds are <b>not</b> guaranteed to be consistent across reloads/restarts!
* </p>
* <p>
* <b>Implementation notes:</b><br>
* The used UUID highly depends on the implementation
* </p>
* <table>
* <caption>Implementations</caption>
* <tr><th>Sponge</th><td>The UUID is equal to the returned UUID by world-instances of the Sponge-API, so you can just use <code>spongeWorld.getUniqueId()</code></td></tr>
* <tr><th>Bukkit</th><td>The UUID is equal to the returned UUID by world-instances of the Bukkit-API, so you can just use <code>bukkitWorld.getUID()</code></td></tr>
* <tr><th>Forge</th><td>The UUID is randomly generated, and changes on each reload/restart</td></tr>
* <tr><th>CLI</th><td>The UUID is randomly generated, and changes on each reload/restart</td></tr>
* </table>
*
* @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 ( <code>world:</code> ).

View File

@ -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.<br>
* If there already is a render scheduled for one of the tiles, a second one will <b>not</b> 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.<br>
* If there already is a render scheduled for one of the tiles, a second one will <b>not</b> 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.<br>
* If there already is a render scheduled for the tile, a second one will <b>not</b> 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.<br>
* If there already is a render scheduled for the tile, a second one will <b>not</b> 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.<br>
* If there already is a render scheduled for the tile, a second one will <b>not</b> 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.<br>
* If there already is a render scheduled for the tile, a second one will <b>not</b> 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 <code>true</code> 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();
}

View File

@ -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).
*
* <p>The given <code>path</code> is used as file-name and (separated with '/') optional folders to organize the image-files.
* Do NOT include the file-ending! (e.g. <code>"someFolder/somePOIIcon"</code> will result in a file "somePOIIcon.png" in a folder "someFolder").</p>
* <p>If the image file with the given path already exists, it will be replaced.</p>
*
* @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:
* <ul>
* <li>the <b>key</b> is the image path how it would be used in the "path" parameter of the {@link #createImage(BufferedImage, String)} method</li>
* <li>and the <b>value</b> is the relative address of the image. The same ones that are returned from the {@link #createImage(BufferedImage, String)} method</li>
* </ul>
* @throws IOException If an {@link IOException} is thrown while reading the images
*/
Map<String, String> availableImages() throws IOException;
}

View File

@ -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.<br>
@ -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.<br>
@ -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.<br>
@ -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.<br>
@ -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;
}
}

View File

@ -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}.
* <p><i>(The position of the marker will be the center of the shape (it's bounding box))</i></p>
*
* @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}.
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.
* <p>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.</p>
* @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.<br>
* <i>(The shape will be extruded from this value to {@link #getShapeMaxY()} on the map)</i>
* @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.
* <i>(The shape will be extruded from {@link #getShapeMinY()} to this value on the map)</i>
* @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).
* <p><i>(Invoke this after changing the {@link Shape} to make sure the markers position gets updated as well)</i></p>
*/
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 <code>true</code> 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());
}
}

View File

@ -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");
}
}

View File

@ -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!");

View File

@ -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}.
* <p><i>(The position of the marker will be the center of the line (it's bounding box))</i></p>
*
* @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}.
* <p><i>(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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).
* <p><i>(Invoke this after changing the {@link Line} to make sure the markers position gets updated as well)</i></p>
*/
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 <code>true</code> 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);
}
}

View File

@ -1,60 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* 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}.<br>
* 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<String> getLink();
/**
* If this is <code>true</code> 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}.<br>
* 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 <code>null</code> 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();
}

View File

@ -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.
* <p>Each marker has an id that is unique in the {@link MarkerSet} that it is in.</p>
* 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}.
* <p>The id is unique in the {@link MarkerSet} that this marker is in.</p>
* @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}.
* <p>
* <b>Using html-tags in the label is possible but deprecated!</b>
* </p>
* <p>
* <b>Important:</b><br>
* Html-tags in the label will not be escaped, so you can use them to style the {@link Marker}-labels.<br>
* Make sure you escape all html-tags from possible user inputs to prevent possible <a href="https://en.wikipedia.org/wiki/Cross-site_scripting">XSS-Attacks</a> on the web-client!
* </p>
* <p><i>(HTML-Tags will be escaped.)</i></p>
*
* @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("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;");
}
/**
* Getter for the minimum distance of the camera to the position ({@link #getPosition()} of the {@link Marker} for it to be displayed.<br>
* 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.<br>
* 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.<br>
* 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.<br>
* 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}.<br>
* 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<String> getLink();
/**
* If this is <code>true</code> 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}.<br>
* 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 <code>null</code> 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));
}
}

View File

@ -1,104 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* 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 <code>markers.json</code> that is used to display different Markers on the map.
* <p>
* <b>Important:</b><br>
* 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()}!<br>
* </p>
* <p>To avoid any concurrent modifications to the <code>markers.json</code>, make sure your {@link MarkerAPI} is always loaded before making any changes, and saved right after the changes.</p>
*
* @see BlueMapAPI#getMarkerAPI()
*/
public interface MarkerAPI {
/**
* Getter for an <i>unmodifiable</i> {@link Collection} containing all {@link MarkerSet}s that are currently loaded with BlueMap.
*
* @return a {@link Collection} with all loaded {@link MarkerSet}s
*/
Collection<MarkerSet> getMarkerSets();
/**
* Getter for a loaded {@link MarkerSet} with the given id.<br>
* 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}&lt;{@link MarkerSet}&gt; with the given id
*/
Optional<MarkerSet> getMarkerSet(String id);
/**
* Created a new {@link MarkerSet} with the given id.<br>
* 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}.<br>
* This is equivalent to calling <code>removeMarkerSet(markerSet.getId())</code>.
*
* @param markerSet the {@link MarkerSet} to be removed
* @return <code>true</code> if the {@link MarkerSet} was removed, <code>false</code> 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 <code>true</code> if the {@link MarkerSet} was removed, <code>false</code> 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 <code>markers.json</code>.<br>
* Calling this will <b>override all unsaved changes</b> you made with this instance!
*
* @throws IOException if an {@link IOException} occurred while loading the <code>markers.json</code>
*/
void load() throws IOException;
/**
* Saves all changes made with this instance to the <code>markers.json</code>.<br>
*
* @throws IOException if an {@link IOException} occurred while saving the <code>markers.json</code>
*/
void save() throws IOException;
}

View File

@ -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.
*
* <p>Each {@link MarkerSet} has an unique id.</p>
*/
public interface MarkerSet {
public class MarkerSet {
private String label;
private boolean toggleable, defaultHidden;
private final Map<String, Marker> 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}.
* <p>The label is used in the web-app to name the toggle-button of this {@link MarkerSet} if it is toggleable. ({@link #isToggleable()})</p>
* @return the label of this {@link MarkerSet}
*/
String getLabel();
public String getLabel() {
return label;
}
/**
* Sets the label of this {@link MarkerSet}.
* <p>The label is used in the web-app to name the toggle-button of this {@link MarkerSet} if it is toggleable. ({@link #isToggleable()})</p>
* @param label the new label
*/
void setLabel(String label);
public void setLabel(String label) {
this.label = label;
}
/**
* Checks if the {@link MarkerSet} is toggleable.
* <p>If this is <code>true</code>, 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.</p>
* @return whether this {@link MarkerSet} is toggleable
*/
boolean isToggleable();
public boolean isToggleable() {
return toggleable;
}
/**
* Changes if this {@link MarkerSet} is toggleable.
* <p>If this is <code>true</code>, 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.</p>
* @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 <b>unmodifiable</b> {@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<Marker> getMarkers();
/**
* Getter for a {@link Marker} with the given id.<br>
* 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}&lt;{@link Marker}&gt; with the given id
*/
Optional<Marker> getMarker(String id);
/**
* Creates a {@link POIMarker} with the given id and adds it to this {@link MarkerSet}.<br>
* 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}.<br>
* 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}.<br>
* 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}.<br>
* 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}.<br>
* 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.
*
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.<br>
* If a Marker with that id already exists, it will be replaced by the new {@link ShapeMarker}!
*
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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<String, Marker> getMarkers() {
return markers;
}
/**
* Creates a {@link ShapeMarker} with the given id and adds it to this {@link MarkerSet}.<br>
* If a Marker with that id already exists, it will be replaced by the new {@link ShapeMarker}!
*
* <p><i>(The position of the marker will be the center of the shape (it's bounding box))</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}!
*
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}!
*
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link ExtrudeMarker}!
*
* <p><i>(The position of the marker will be the center of the shape (it's bounding box))</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}!
*
* <p><i>(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}!
*
* <p><i>(Since the line has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.<br>
* If a {@link Marker} with that id already exists, it will be replaced by the new {@link LineMarker}!
*
* <p><i>(The position of the marker will be the center of the line (it's bounding box))</i></p>
*
* @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}.<br>
* This is equivalent to calling <code>removeMarker(marker.getId())</code>.
*
* @param marker the {@link Marker} to be removed
* @return <code>true</code> if the {@link Marker} was removed, <code>false</code> 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 <code>true</code> if the {@link Marker} was removed, <code>false</code> if there was no {@link Marker} with that id
*/
boolean removeMarker(String id);
}

View File

@ -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.<br>
@ -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}.<br>
* 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<String> getLink() {
return Optional.ofNullable(link);
}
/**
* If this is <code>true</code> 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}.<br>
* 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 <code>null</code> 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;
}
}

View File

@ -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");
}
}

View File

@ -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}.
* <p><i>(The position of the marker will be the center of the shape (it's bounding box))</i></p>
*
* @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}.
* <p><i>(Since the shape has its own positions, the position is only used to determine e.g. the distance to the camera)</i></p>
*
* @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}.
* <p>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.</p>
* @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}.
* <p>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.</p>
* @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).
* <p><i>(Invoke this after changing the {@link Shape} to make sure the markers position gets updated as well)</i></p>
*/
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 <code>true</code> 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());
}
}

View File

@ -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 # <i>(css-style: e.g. <code>#f16</code> becomes <code>#ff1166</code>)</i>.
* @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);
}
}

View File

@ -0,0 +1,3 @@
${version}
${gitHash}
${gitClean}