From 7861405f605e57f57e1611085cc6212156d619ca Mon Sep 17 00:00:00 2001 From: "Blue (Lukas Rieger)" Date: Mon, 3 Aug 2020 14:15:05 +0200 Subject: [PATCH] Fix Fabric build script and implement the fabric-plugin --- .../common/plugin/MapUpdateHandler.java | 13 +- .../bluemap/common/plugin/Plugin.java | 10 +- BlueMapFabric/build.gradle | 15 +- .../bluemap/fabric/FabricEventForwarder.java | 95 ++++++++++ .../bluecolored/bluemap/fabric/FabricMod.java | 99 +++++++++-- .../fabric/events/ChunkFinalizeCallback.java | 19 ++ .../fabric/events/WorldSaveCallback.java | 17 ++ .../fabric/mixin/MixinChunkGenerator.java | 32 ++++ .../fabric/mixin/MixinServerWorld.java | 21 +++ .../resources/bluemap-fabric-defaults.conf | 11 ++ .../src/main/resources/bluemap-fabric.conf | 166 ++++++++++++++++++ .../src/main/resources/bluemap.mixins.json | 26 +-- .../bluecolored/bluemap/forge/ForgeMod.java | 25 +++ 13 files changed, 495 insertions(+), 54 deletions(-) create mode 100644 BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricEventForwarder.java create mode 100644 BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/ChunkFinalizeCallback.java create mode 100644 BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/WorldSaveCallback.java create mode 100644 BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinChunkGenerator.java create mode 100644 BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinServerWorld.java create mode 100644 BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf create mode 100644 BlueMapFabric/src/main/resources/bluemap-fabric.conf diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java index 8f8b9925..ac69cd1a 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java @@ -38,15 +38,18 @@ public class MapUpdateHandler implements ServerEventListener { - public Multimap updateBuffer; + private Plugin plugin; - public MapUpdateHandler() { + private Multimap updateBuffer; + + public MapUpdateHandler(Plugin plugin) { + this.plugin = plugin; updateBuffer = MultimapBuilder.hashKeys().hashSetValues().build(); } @Override public void onWorldSaveToDisk(final UUID world) { - RenderManager renderManager = Plugin.getInstance().getRenderManager(); + RenderManager renderManager = plugin.getRenderManager(); new Thread(() -> { try { @@ -106,7 +109,7 @@ private void updateChunk(UUID world, Vector2i chunkPos) { private void updateBlock(UUID world, Vector3i pos){ synchronized (updateBuffer) { - for (MapType mapType : Plugin.getInstance().getMapTypes()) { + for (MapType mapType : plugin.getMapTypes()) { if (mapType.getWorld().getUUID().equals(world)) { mapType.getWorld().invalidateChunkCache(mapType.getWorld().blockPosToChunkPos(pos)); @@ -122,7 +125,7 @@ public int getUpdateBufferCount() { } public void flushTileBuffer() { - RenderManager renderManager = Plugin.getInstance().getRenderManager(); + RenderManager renderManager = plugin.getRenderManager(); synchronized (updateBuffer) { for (MapType map : updateBuffer.keySet()) { diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index 7c0ef346..17daded0 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -72,8 +72,6 @@ public class Plugin { public static final String PLUGIN_ID = "bluemap"; public static final String PLUGIN_NAME = "BlueMap"; - - private static Plugin instance; private BlueMapAPIImpl api; @@ -104,8 +102,6 @@ public Plugin(String implementationType, ServerInterface serverInterface) { this.maps = new HashMap<>(); this.worlds = new HashMap<>(); - - instance = this; } public synchronized void load() throws IOException, ParseResourceException { @@ -270,7 +266,7 @@ public synchronized void load() throws IOException, ParseResourceException { periodicalSaveThread.start(); //start map updater - this.updateHandler = new MapUpdateHandler(); + this.updateHandler = new MapUpdateHandler(this); serverInterface.registerListener(updateHandler); //create/update webfiles @@ -427,8 +423,4 @@ public boolean isLoaded() { return loaded; } - public static Plugin getInstance() { - return instance; - } - } diff --git a/BlueMapFabric/build.gradle b/BlueMapFabric/build.gradle index d75cc224..c94a5520 100644 --- a/BlueMapFabric/build.gradle +++ b/BlueMapFabric/build.gradle @@ -5,7 +5,7 @@ plugins { } configurations { - compile.extendsFrom include + compile.extendsFrom shadowInclude } dependencies { @@ -14,7 +14,7 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:0.8.2+build.194" modImplementation "net.fabricmc.fabric-api:fabric-api:0.5.1+build.294-1.15" - compile (project(':BlueMapCommon')) { + shadowInclude (project(':BlueMapCommon')) { //exclude dependencies provided by fabric exclude group: 'com.google.guava', module: 'guava' exclude group: 'com.google.code.gson', module: 'gson' @@ -38,13 +38,7 @@ processResources { } shadowJar { - configurations = [project.configurations.compile] - - dependencies { - include(dependency(':BlueMapCommon')) - include(dependency(':BlueMapCore')) - include(dependency(':BlueMapAPI')) - } + configurations = [project.configurations.shadowInclude] //relocate 'com.flowpowered.math', 'de.bluecolored.shadow.flowpowered.math' //DON'T relocate this, because the API depends on it relocate 'com.typesafe.config', 'de.bluecolored.shadow.typesafe.config' @@ -52,7 +46,7 @@ shadowJar { relocate 'ninja.leaping.configurate', 'de.bluecolored.shadow.ninja.leaping.configurate' relocate 'org.yaml.snakeyaml', 'de.bluecolored.shadow.yaml.snakeyaml' - exclude '/mappings/*' + //exclude '/mappings/*' } task ramappedShadowJar(type: RemapJarTask) { @@ -62,6 +56,7 @@ task ramappedShadowJar(type: RemapJarTask) { addNestedDependencies = true archiveName = "BlueMap-${version}-fabric.jar" } +build.dependsOn ramappedShadowJar task sourcesJar(type: Jar, dependsOn: classes) { classifier = "sources" diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricEventForwarder.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricEventForwarder.java new file mode 100644 index 00000000..d46fd3e5 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricEventForwarder.java @@ -0,0 +1,95 @@ +package de.bluecolored.bluemap.fabric; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.UUID; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.fabric.events.ChunkFinalizeCallback; +import de.bluecolored.bluemap.fabric.events.WorldSaveCallback; +import net.fabricmc.fabric.api.event.player.AttackBlockCallback; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +public class FabricEventForwarder { + + private FabricMod mod; + private Collection eventListeners; + + public FabricEventForwarder(FabricMod mod) { + this.mod = mod; + this.eventListeners = new ArrayList<>(1); + + WorldSaveCallback.EVENT.register(this::onWorldSave); + ChunkFinalizeCallback.EVENT.register(this::onChunkFinalize); + AttackBlockCallback.EVENT.register(this::onBlockAttack); + UseBlockCallback.EVENT.register(this::onBlockUse); + } + + public void addEventListener(ServerEventListener listener) { + this.eventListeners.add(listener); + } + + public void removeAllListeners() { + this.eventListeners.clear(); + } + + + public ActionResult onBlockUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) { + if (world instanceof ServerWorld) { + onBlockChange((ServerWorld) world, hitResult.getBlockPos()); + } + + return ActionResult.PASS; + } + + public ActionResult onBlockAttack(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) { + if (world instanceof ServerWorld) { + onBlockChange((ServerWorld) world, pos); + } + + return ActionResult.PASS; + } + + public void onBlockChange(ServerWorld world, BlockPos blockPos) { + Vector3i position = new Vector3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + + try { + UUID uuid = mod.getUUIDForWorld(world); + eventListeners.forEach(e -> e.onBlockChange(uuid, position)); + } catch (IOException e) { + Logger.global.logError("Failed to get UUID for world: " + world, e); + } + } + + public void onWorldSave(ServerWorld world) { + try { + UUID uuid = mod.getUUIDForWorld(world); + eventListeners.forEach(e -> e.onWorldSaveToDisk(uuid)); + } catch (IOException e) { + Logger.global.logError("Failed to get UUID for world: " + world, e); + } + } + + public void onChunkFinalize(ServerWorld world, Vector2i chunkPos) { + try { + UUID uuid = mod.getUUIDForWorld(world); + eventListeners.forEach(e -> e.onChunkFinishedGeneration(uuid, chunkPos)); + } catch (IOException e) { + Logger.global.logError("Failed to get UUID for world: " + world, e); + } + } + +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricMod.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricMod.java index 2fb082c1..bf095dba 100644 --- a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricMod.java +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricMod.java @@ -2,62 +2,125 @@ import java.io.File; import java.io.IOException; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import org.apache.logging.log4j.LogManager; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + import de.bluecolored.bluemap.common.plugin.Plugin; import de.bluecolored.bluemap.common.plugin.commands.Commands; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.server.ServerStartCallback; +import net.fabricmc.fabric.api.event.server.ServerStopCallback; import net.fabricmc.fabric.api.registry.CommandRegistry; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; public class FabricMod implements ModInitializer, ServerInterface { + + private Plugin pluginInstance = null; - private Plugin plugin; + private Map worldUuids; + private FabricEventForwarder eventForwarder; + + private LoadingCache worldUuidCache; + + public FabricMod() { + Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME)); + + pluginInstance = new Plugin("fabric", this); + + this.worldUuids = new ConcurrentHashMap<>(); + this.eventForwarder = new FabricEventForwarder(this); + this.worldUuidCache = CacheBuilder.newBuilder() + .weakKeys() + .maximumSize(1000) + .build(new CacheLoader() { + @Override + public UUID load(ServerWorld key) throws Exception { + return loadUUIDForWorld(key); + } + }); + } @Override public void onInitialize() { - Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME)); - - this.plugin = new Plugin("forge", this); //register commands CommandRegistry.INSTANCE.register(true, dispatcher -> { - new Commands<>(plugin, dispatcher, fabricSource -> new FabricCommandSource(this, plugin, fabricSource)); + new Commands<>(pluginInstance, dispatcher, fabricSource -> new FabricCommandSource(this, pluginInstance, fabricSource)); + }); + + ServerStartCallback.EVENT.register((MinecraftServer server) -> { + new Thread(()->{ + Logger.global.logInfo("Loading BlueMap..."); + + try { + pluginInstance.load(); + Logger.global.logInfo("BlueMap loaded!"); + } catch (IOException | ParseResourceException e) { + Logger.global.logError("Failed to load bluemap!", e); + } + }).start(); + }); + + ServerStopCallback.EVENT.register((MinecraftServer server) -> { + pluginInstance.unload(); + Logger.global.logInfo("BlueMap unloaded!"); }); } - public UUID getUUIDForWorld(ServerWorld world) throws IOException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Not implemented!"); - } - @Override public void registerListener(ServerEventListener listener) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Not implemented!"); + eventForwarder.addEventListener(listener); } @Override public void unregisterAllListeners() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Not implemented!"); + eventForwarder.removeAllListeners(); } @Override public UUID getUUIDForWorld(File worldFolder) throws IOException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Not implemented!"); + worldFolder = worldFolder.getCanonicalFile(); + + UUID uuid = worldUuids.get(worldFolder); + if (uuid == null) { + uuid = UUID.randomUUID(); + worldUuids.put(worldFolder, uuid); + } + + return uuid; + } + + public UUID getUUIDForWorld(ServerWorld world) throws IOException { + try { + return worldUuidCache.get(world); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) throw (IOException) cause; + else throw new IOException(cause); + } + } + + private UUID loadUUIDForWorld(ServerWorld world) throws IOException { + File dimensionDir = world.getDimension().getType().getSaveDirectory(world.getSaveHandler().getWorldDir()); + return getUUIDForWorld(dimensionDir); } @Override public File getConfigFolder() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Not implemented!"); + return new File("config/bluemap"); } } diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/ChunkFinalizeCallback.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/ChunkFinalizeCallback.java new file mode 100644 index 00000000..bf20dd88 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/ChunkFinalizeCallback.java @@ -0,0 +1,19 @@ +package de.bluecolored.bluemap.fabric.events; + +import com.flowpowered.math.vector.Vector2i; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.server.world.ServerWorld; + +public interface ChunkFinalizeCallback { + Event EVENT = EventFactory.createArrayBacked(ChunkFinalizeCallback.class, + (listeners) -> (world, chunkPos) -> { + for (ChunkFinalizeCallback event : listeners) { + event.onChunkFinalized(world, chunkPos); + } + } + ); + + void onChunkFinalized(ServerWorld world, Vector2i chunkPos); +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/WorldSaveCallback.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/WorldSaveCallback.java new file mode 100644 index 00000000..56b6eeab --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/WorldSaveCallback.java @@ -0,0 +1,17 @@ +package de.bluecolored.bluemap.fabric.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.server.world.ServerWorld; + +public interface WorldSaveCallback { + Event EVENT = EventFactory.createArrayBacked(WorldSaveCallback.class, + (listeners) -> (world) -> { + for (WorldSaveCallback event : listeners) { + event.onWorldSaved(world); + } + } + ); + + void onWorldSaved(ServerWorld world); +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinChunkGenerator.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinChunkGenerator.java new file mode 100644 index 00000000..cf15eb34 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinChunkGenerator.java @@ -0,0 +1,32 @@ +package de.bluecolored.bluemap.fabric.mixin; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.flowpowered.math.vector.Vector2i; + +import de.bluecolored.bluemap.fabric.events.ChunkFinalizeCallback; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.IWorld; +import net.minecraft.world.gen.chunk.ChunkGenerator; + +@Mixin(ChunkGenerator.class) +public class MixinChunkGenerator { + + @Shadow + @Final + protected IWorld world; + + @Inject(at = @At("RETURN"), method = "generateFeatures") + public void generateFeatures(ChunkRegion region, CallbackInfo ci) { + if (world instanceof ServerWorld) { + ChunkFinalizeCallback.EVENT.invoker().onChunkFinalized((ServerWorld) world, new Vector2i(region.getCenterChunkX(), region.getCenterChunkZ())); + } + } + +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinServerWorld.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinServerWorld.java new file mode 100644 index 00000000..fb9e9bc0 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinServerWorld.java @@ -0,0 +1,21 @@ +package de.bluecolored.bluemap.fabric.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import de.bluecolored.bluemap.fabric.events.WorldSaveCallback; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ProgressListener; +import net.minecraft.world.SessionLockException; + +@Mixin(ServerWorld.class) +public abstract class MixinServerWorld { + + @Inject(at = @At("RETURN"), method = "save") + public void save(ProgressListener progressListener, boolean flush, boolean bl, CallbackInfo ci) throws SessionLockException { + WorldSaveCallback.EVENT.invoker().onWorldSaved((ServerWorld) (Object) this); + } + +} diff --git a/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf b/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf new file mode 100644 index 00000000..c6f20621 --- /dev/null +++ b/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf @@ -0,0 +1,11 @@ +accept-download: false +metrics: true +renderThreadCount: -2 +data: "bluemap" +webroot: "bluemap/web" +useCookies: true +webserver { + enabled: true + port: 8100 + maxConnectionCount: 100 +} diff --git a/BlueMapFabric/src/main/resources/bluemap-fabric.conf b/BlueMapFabric/src/main/resources/bluemap-fabric.conf new file mode 100644 index 00000000..8b740ce2 --- /dev/null +++ b/BlueMapFabric/src/main/resources/bluemap-fabric.conf @@ -0,0 +1,166 @@ +## ## +## BlueMap ## +## ## +## by Blue (Lukas Rieger) ## +## http://bluecolored.de/ ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"forge","version":"%version%"} +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +data: "bluemap" + +# The webroot of the website that displays the map. +webroot: "bluemap/web" + +# Unncomment this to override the path where bluemap stores the data-files. +# Default is "/data" +#webdata: "path/to/data/folder" + +# If the web-application should use cookies to save the configurations of a user. +useCookies: true + +webserver { + # With this setting you can disable the integrated web-server. + # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. + # Default is enabled + enabled: true + + # The IP-Adress that the webserver binds to. + # If this setting is commented out, bluemap tries to find the default ip-adress of your system. + # If you only want to access it locally use "localhost". + #ip: "localhost" + #ip: "127.0.0.1" + + # The port that the webserver listenes to. + # Default is 8100 + port: 8100 + + # Max number of simultaneous connections that the webserver allows + # Default is 100 + maxConnectionCount: 100 +} + +# This is an array with multiple configured maps. +# You can define multiple maps, for different worlds with different render-settings here +maps: [ + + { + # The id of this map + # Should only contain word-charactes: [a-zA-Z0-9_] + # Changing this value breaks your existing renders. + id: "world" + + # The name of this map + # This defines the display name of this map, you can change this at any time. + # Default is the id of this map + name: "World" + + # The path to the save-folder of the world to render. + world: "world" + + # The position on the world where the map will be centered if you open it. + # You can change this at any time. + # This defaults to the world-spawn if you don't set it. + #startPos: [500, -820] + + # The color of thy sky as a hex-color + # You can change this at any time. + # Default is "#7dabff" + skyColor: "#7dabff" + + # Defines the ambient light-strength that every block is recieving, regardless of the sunlight/blocklight. + # 0 is no ambient light, 1 is fully lighted. + # You can change this at any time. + # Default is 0 + ambientLight: 0 + + # If this is false, BlueMap tries to omit all blocks that are not visible from above-ground. + # More specific: Block-Faces that have a sunlight/skylight value of 0 are removed. + # This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible. + # Changing this value requires a re-render of the map. + # Default is false + renderCaves: false + + # With the below values you can limit the map-render. + # This can be used to ignore the nethers ceiling or render only a certain part of a world. + # Changing this values might require a re-render of the map, already rendered tiles outside the limits will not be deleted. + # Default is no min or max value (= infinite bounds) + #minX: -4000 + #maxX: 4000 + #minZ: -4000 + #maxZ: 4000 + #minY: 50 + #maxY: 126 + + # Using this, BlueMap pretends that every Block out of the defined render-bounds is AIR, + # this means you can see the blocks where the world is cut (instead of having a see-through/xray view). + # This has only an effect if you set some render-bounds above. + # Changing this value requires a re-render of the map. + # Default is true + renderEdges: true + + # With this set to true, the generated files for this world are compressed using gzip to save A LOT of space. + # Files will be only 5% as big with compression! + # Note: If you are using NGINX or Apache to host your map, you can configure them to serve the compressed files directly. + # This is much better than disabling the compression. + # Changing this value requires a re-render of the map. + # Default is true + useCompression: true + } + + # Here another example for the End-Map + # Things we don't want to change from default we can just omit + { + id: "end" + name: "End" + world: "world/DIM1" + + # We dont want a blue sky in the end + skyColor: "#080010" + + # In the end is no sky-light, so we need to enable this or we won't see anything. + renderCaves: true + + # Same here, we don't want a dark map. But not completely lighted, so we see the effect of e.g torches. + ambientLight: 0.6 + } + + # Here another example for the Nether-Map + { + id: "nether" + name: "Nether" + world: "world/DIM-1" + + skyColor: "#290000" + + renderCaves: true + ambientLight: 0.6 + + # We slice the whole world at y:90 so every block above 90 will be air. + # This way we don't render the nethers ceiling. + maxY: 90 + renderEdges: true + } + +] diff --git a/BlueMapFabric/src/main/resources/bluemap.mixins.json b/BlueMapFabric/src/main/resources/bluemap.mixins.json index abb10ecd..e8c98a84 100644 --- a/BlueMapFabric/src/main/resources/bluemap.mixins.json +++ b/BlueMapFabric/src/main/resources/bluemap.mixins.json @@ -1,13 +1,15 @@ { - "required": true, - "minVersion": "0.8", - "package": "de.bluecolored.bluemap.fabric.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - ], - "client": [ - ], - "injectors": { - "defaultRequire": 1 - } -} + "required": true, + "minVersion": "0.8", + "package": "de.bluecolored.bluemap.fabric.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [ + "MixinServerWorld", + "MixinChunkGenerator" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java b/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java index 66cb7a9c..be051dd2 100644 --- a/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java +++ b/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java @@ -31,10 +31,14 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ExecutionException; import org.apache.logging.log4j.LogManager; import com.flowpowered.math.vector.Vector3i; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import de.bluecolored.bluemap.common.plugin.Plugin; import de.bluecolored.bluemap.common.plugin.commands.Commands; @@ -59,12 +63,23 @@ public class ForgeMod implements ServerInterface { private Map worldUUIDs; private Collection eventListeners; + private LoadingCache worldUuidCache; + public ForgeMod() { Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME)); this.bluemap = new Plugin("forge", this); this.worldUUIDs = new HashMap<>(); this.eventListeners = new ArrayList<>(1); + this.worldUuidCache = CacheBuilder.newBuilder() + .weakKeys() + .maximumSize(1000) + .build(new CacheLoader() { + @Override + public UUID load(ServerWorld key) throws Exception { + return loadUUIDForWorld(key); + } + }); MinecraftForge.EVENT_BUS.register(this); } @@ -175,6 +190,16 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException { } public UUID getUUIDForWorld(ServerWorld world) throws IOException { + try { + return worldUuidCache.get(world); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) throw (IOException) cause; + else throw new IOException(cause); + } + } + + private UUID loadUUIDForWorld(ServerWorld world) throws IOException { synchronized (worldUUIDs) { String key = getFolderForWorld(world).getPath();