Add Renderer-API and API-Listener

This commit is contained in:
Blue (Lukas Rieger) 2020-04-10 14:55:08 +02:00
parent 982f01cc47
commit daebd9a1b8
7 changed files with 494 additions and 0 deletions

View File

@ -10,6 +10,10 @@ repositories {
}
}
dependencies {
compile 'com.flowpowered:flow-math:1.0.3'
}
apply plugin: 'java'
group = 'de.bluecolored.bluemap.api'

View File

@ -0,0 +1,116 @@
/*
* 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.ArrayList;
import java.util.Collection;
import java.util.Optional;
import de.bluecolored.bluemap.api.renderer.BlueMapMap;
import de.bluecolored.bluemap.api.renderer.BlueMapWorld;
import de.bluecolored.bluemap.api.renderer.Renderer;
public abstract class BlueMapAPI {
private static BlueMapAPI instance;
private static Collection<BlueMapAPIListener> listener = new ArrayList<>();
/**
* Getter for the {@link Renderer} instance.
* @return the {@link Renderer}
*/
public abstract Renderer getRenderer();
/**
* Getter for all {@link BlueMapMap}s loaded by BlueMap.
* @return an immutable collection of all loaded {@link BlueMapMap}s
*/
public abstract Collection<BlueMapMap> getMaps();
/**
* Getter for all {@link BlueMapWorld}s loaded by BlueMap.
* @return an immutable collection of all loaded {@link BlueMapWorld}s
*/
public abstract Collection<BlueMapWorld> getWorlds();
/**
* Getter for the installed BlueMap version
* @return the version-string
*/
public abstract String getBlueMapVersion();
/**
* Register a listener that will be called when the API enables/disables
* @param listener the {@link BlueMapAPIListener}
*/
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
*/
public static synchronized boolean unregisterListener(BlueMapAPIListener listener) {
return BlueMapAPI.listener.remove(listener);
}
/**
* Returns an instance of {@link BlueMapAPI} if it is currently enabled, else an empty {@link Optional} is returned.
* @return an {@link Optional}&lt;{@link BlueMapAPI}&gt;
*/
public static synchronized Optional<BlueMapAPI> getInstance() {
return Optional.ofNullable(instance);
}
/**
* Used by BlueMap to register the API and call the listeners properly.
* @param instance {@link BlueMapAPI}-instance
*/
static synchronized void registerInstance(BlueMapAPI instance) {
if (BlueMapAPI.instance != null) throw new IllegalStateException("There already is an API instance registered!");
BlueMapAPI.instance = instance;
for (BlueMapAPIListener listener : BlueMapAPI.listener) {
listener.onEnable(BlueMapAPI.instance);
}
}
/**
* Used by BlueMap to unregister the API and call the listeners properly.
*/
static synchronized void unregisterInstance() {
if (BlueMapAPI.instance == null) throw new IllegalStateException("There is no API instance registered!");
for (BlueMapAPIListener listener : BlueMapAPI.listener) {
listener.onDisable(BlueMapAPI.instance);
}
BlueMapAPI.instance = null;
}
}

View File

@ -0,0 +1,45 @@
/*
* 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;
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
*/
default void onDisable(BlueMapAPI blueMapApi) {}
}

View File

@ -0,0 +1,91 @@
/*
* 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.renderer;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3d;
import com.flowpowered.math.vector.Vector3i;
public interface BlueMapMap {
/**
* Returns this maps id, this is equal to the id configured in bluemap's config for this map.
* @return the id of this map
*/
String getId();
/**
* Returns this maps display-name, this is equal to the name configured in bluemap's config for this map.
* @return the name of this map
*/
String getName();
/**
* Getter for the {@link BlueMapWorld} of this map.
* @return the {@link BlueMapWorld} of this map
*/
BlueMapWorld getWorld();
/**
* Getter for the size of all tiles on this map in blocks.
* @return the tile-size in blocks
*/
Vector2i getTileSize();
/**
* Getter for the offset of the tile-grid on this map.<br>
* E.g. an offset of (2|-1) would mean that the tile (0|0) has block (2|0|-1) at it's min-corner.
* @return the tile-offset in blocks
*/
Vector2i getTileOffset();
/**
* Converts a block-position to a map-tile-coordinate for this map
*/
default Vector2i posToTile(double blockX, double blockZ){
Vector2i offset = getTileOffset();
Vector2i size = getTileSize();
return Vector2i.from(
(int) Math.floor((blockX - offset.getX()) / size.getX()),
(int) Math.floor((blockZ - offset.getY()) / size.getY())
);
}
/**
* Converts a block-position to a map-tile-coordinate for this map
*/
default Vector2i posToTile(Vector3i pos){
return posToTile(pos.getX(), pos.getZ());
}
/**
* Converts a block-position to a map-tile-coordinate for this map
*/
default Vector2i posToTile(Vector3d pos){
return posToTile(pos.getX(), pos.getZ());
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.renderer;
import java.nio.file.Path;
import java.util.Collection;
import java.util.UUID;
public interface BlueMapWorld {
/**
* <p>Getter for the {@link UUID} of the world.</p>
* <p>
* The {@link UUID} of this world is <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
* <table>
* <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</code><td><tr>
* <tr><th>CLI</th><td>The UUID is randomly generated, and changes on each reload/restart</code><td><tr>
* </table>
*
* @return the {@link UUID} of the world
*/
UUID getUuid();
/**
* 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> ).
* @return the save-folder of this world.
*/
Path getSaveFolder();
/**
* Getter for all {@link BlueMapMap}s for this world
* @return a {@link Collection} of all {@link BlueMapMap}s for this world
*/
Collection<BlueMapMap> getMaps();
}

View File

@ -0,0 +1,62 @@
/*
* 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.renderer;
import java.util.function.Consumer;
import com.flowpowered.math.vector.Vector2i;
public interface RenderTicket {
/**
* <p>Getter for the {@link BlueMapMap} this ticket belongs to.</p>
* @return the map for this ticket
*/
BlueMapMap getMap();
/**
* <p>Getter for the tile coordinates that this ticket renders.</p>
* @return the tile this ticket renders
*/
Vector2i getTile();
/**
* The state of the ticket. This also returns <code>true</code> if the ticket has been processed but has failed to render the tile.
* @return <code>true</code> if this ticket has been processed, <code>false</code> otherwise.
*/
boolean isCompleted();
/**
* Every listener registered with this method will be called (in an undefined order) after this ticket has been completed.
* <p>
* <b>Important:</b><br>
* The callback-method will likely (but is not guaranteed to) be called <b>asynchronously, on the render-thread!</b><br>
* You'll need to handle any further threading, scheduling or synchronizing yourself.
* </p>
* @param callback the method to be called on completion
*/
void onCompletion(Consumer<RenderTicket> callback);
}

View File

@ -0,0 +1,112 @@
/*
* 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.renderer;
import java.util.Collection;
import java.util.HashSet;
import java.util.UUID;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
public interface Renderer {
/**
* Schedules the map-tile at this block position for all maps of this world and returns the created render-tickets.<br>
* If there already is a render-ticket scheduled for a tile, the existing one is returned instead of creating a new one.
*
* @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)
*
* @return a {@link Collection} of the scheduled {@link RenderTicket}s
*/
Collection<RenderTicket> render(UUID world, Vector3i blockPosition);
/**
* Schedules the map-tile at this block position for all maps of this world and returns the created render-tickets.<br>
* If there already is a render-ticket scheduled for a tile, the existing one is returned instead of creating a new one.
*
* @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)
*
* @return a {@link Collection} of the scheduled {@link RenderTicket}s
*/
default Collection<RenderTicket> render(BlueMapWorld world, Vector3i blockPosition) {
Collection<RenderTicket> tickets = new HashSet<>();
for (BlueMapMap map : world.getMaps()) {
tickets.add(render(map, blockPosition));
}
return tickets;
}
/**
* Schedules the map-tile at this block position and returns the created render-ticket.<br>
* If there already is a render-ticket scheduled for that map-tile, the existing one is returned instead of creating a new one.
*
* @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)
*
* @return the scheduled {@link RenderTicket}
*/
RenderTicket render(String mapId, Vector3i blockPosition);
/**
* Schedules the map-tile at this block position and returns the created render-ticket.<br>
* If there already is a render-ticket scheduled for that map-tile, the existing one is returned instead of creating a new one.
*
* @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)
*
* @return the scheduled {@link RenderTicket}
*/
default RenderTicket render(BlueMapMap map, Vector3i blockPosition) {
return render(map, map.posToTile(blockPosition));
}
/**
* Schedules the map-tile and returns the created render-ticket.<br>
* If there already is a render-ticket scheduled for that map-tile, the existing one is returned instead of creating a new one.
*
* @param mapId the id of the {@link BlueMapMap} to render
* @param tile a {@link Vector2i} for the tile-position to render
*
* @return the scheduled {@link RenderTicket}
*/
RenderTicket render(String mapId, Vector2i tile);
/**
* Schedules the map-tile and returns the created render-ticket.<br>
* If there already is a render-ticket scheduled for that map-tile, the existing one is returned instead of creating a new one.
*
* @param map the {@link BlueMapMap}
* @param tile a {@link Vector2i} for the tile-position to render
*
* @return the scheduled {@link RenderTicket}
*/
RenderTicket render(BlueMapMap map, Vector2i tile);
}