diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5360794c..bd008bf7 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -17,7 +17,7 @@ jobs: run: ./gradlew test - name: Build with Gradle run: ./gradlew build - - uses: actions/upload-artifact@v2-preview + - uses: actions/upload-artifact@v2 with: name: artifact path: build/release/* diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/JavaLogger.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/JavaLogger.java index 433bf667..6f51e64f 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/JavaLogger.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/JavaLogger.java @@ -1,5 +1,5 @@ /* - * This file is part of BlueMapSponge, licensed under the MIT License (MIT). + * This file is part of BlueMap, licensed under the MIT License (MIT). * * Copyright (c) Blue (Lukas Rieger) * Copyright (c) contributors diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MapType.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MapType.java index 687fa720..188d0b82 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MapType.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MapType.java @@ -1,5 +1,5 @@ /* - * This file is part of BlueMapSponge, licensed under the MIT License (MIT). + * This file is part of BlueMap, licensed under the MIT License (MIT). * * Copyright (c) Blue (Lukas Rieger) * Copyright (c) contributors 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 eb478b30..7d60f966 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 @@ -39,15 +39,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 { @@ -107,7 +110,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)); @@ -123,7 +126,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 c7c092c8..ac31bc3c 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/BlueMapCore/build.gradle b/BlueMapCore/build.gradle index 5d189319..bfd61afe 100644 --- a/BlueMapCore/build.gradle +++ b/BlueMapCore/build.gradle @@ -31,6 +31,10 @@ node { download = true } +license { + exclude('**/AABB.java') +} + task fixPackageLock() { if (!file("./package-lock.json").exists()) { file("./package-lock.json").text = "" diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java index 60cd87b2..4871b80b 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java @@ -198,20 +198,8 @@ public BlockState getBlockState(Vector3i pos) { int y = pos.getY() & 0xF; int z = pos.getZ() & 0xF; int blockIndex = y * 256 + z * 16 + x; - int index = blockIndex * bitsPerBlock; - int firstLong = index >> 6; // index / 64 - int bitoffset = index & 0x3F; // Math.floorMod(index, 64) - - long value = blocks[firstLong] >>> bitoffset; - - if (bitoffset > 0 && firstLong + 1 < blocks.length) { - long value2 = blocks[firstLong + 1]; - value2 = value2 << -bitoffset; - value = value | value2; - } - - value = value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerBlock); + long value = MCAMath.getValueFromLongStream(blocks, blockIndex, bitsPerBlock); if (value >= palette.length) { Logger.global.noFloodWarning("palettewarning", "Got palette value " + value + " but palette has size of " + palette.length + " (Future occasions of this error will not be logged)"); return BlockState.MISSING; @@ -230,24 +218,11 @@ public LightData getLightData(Vector3i pos) { int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 - int blockLight = this.blockLight.length > 0 ? getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; - int skyLight = this.skyLight.length > 0 ? getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; + int blockLight = this.blockLight.length > 0 ? MCAMath.getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; + int skyLight = this.skyLight.length > 0 ? MCAMath.getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; return new LightData(skyLight, blockLight); } - - /** - * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
- * The value is treated as an unsigned byte. - */ - private int getByteHalf(int value, boolean largeHalf) { - value = value & 0xFF; - if (largeHalf) { - value = value >> 4; - } - value = value & 0xF; - return value; - } } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java index 4b36ad1e..c96b8932 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java @@ -199,20 +199,8 @@ public BlockState getBlockState(Vector3i pos) { int y = pos.getY() & 0xF; int z = pos.getZ() & 0xF; int blockIndex = y * 256 + z * 16 + x; - int index = blockIndex * bitsPerBlock; - int firstLong = index >> 6; // index / 64 - int bitoffset = index & 0x3F; // Math.floorMod(index, 64) - - long value = blocks[firstLong] >>> bitoffset; - - if (bitoffset > 0 && firstLong + 1 < blocks.length) { - long value2 = blocks[firstLong + 1]; - value2 = value2 << -bitoffset; - value = value | value2; - } - - value = value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerBlock); + long value = MCAMath.getValueFromLongStream(blocks, blockIndex, bitsPerBlock); if (value >= palette.length) { Logger.global.noFloodWarning("palettewarning", "Got palette value " + value + " but palette has size of " + palette.length + " (Future occasions of this error will not be logged)"); return BlockState.MISSING; @@ -231,24 +219,11 @@ public LightData getLightData(Vector3i pos) { int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 - int blockLight = this.blockLight.length > 0 ? getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; - int skyLight = this.skyLight.length > 0 ? getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; + int blockLight = this.blockLight.length > 0 ? MCAMath.getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; + int skyLight = this.skyLight.length > 0 ? MCAMath.getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; return new LightData(skyLight, blockLight); } - - /** - * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
- * The value is treated as an unsigned byte. - */ - private int getByteHalf(int value, boolean largeHalf) { - value = value & 0xFF; - if (largeHalf) { - value = value >> 4; - } - value = value & 0xF; - return value; - } } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java index bb185642..637a467f 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java @@ -145,7 +145,6 @@ private class Section { private BlockState[] palette; private int bitsPerBlock; - private int blocksPerLong; @SuppressWarnings("unchecked") public Section(CompoundTag sectionData) { @@ -189,7 +188,6 @@ public Section(CompoundTag sectionData) { this.bitsPerBlock = 32 - Integer.numberOfLeadingZeros(palette.length - 1); if (this.bitsPerBlock < 4) this.bitsPerBlock = 4; - this.blocksPerLong = 64 / bitsPerBlock; } public int getSectionY() { @@ -203,13 +201,8 @@ public BlockState getBlockState(Vector3i pos) { int y = pos.getY() & 0xF; int z = pos.getZ() & 0xF; int blockIndex = y * 256 + z * 16 + x; - int longIndex = blockIndex / blocksPerLong; - int bitIndex = (blockIndex % blocksPerLong) * bitsPerBlock; - - long value = blocks[longIndex] >>> bitIndex; - value = value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerBlock); - + long value = MCAMath.getValueFromLongArray(blocks, blockIndex, bitsPerBlock); if (value >= palette.length) { Logger.global.noFloodWarning("palettewarning", "Got palette value " + value + " but palette has size of " + palette.length + "! (Future occasions of this error will not be logged)"); return BlockState.MISSING; @@ -228,24 +221,11 @@ public LightData getLightData(Vector3i pos) { int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 - int blockLight = this.blockLight.length > 0 ? getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; - int skyLight = this.skyLight.length > 0 ? getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; + int blockLight = this.blockLight.length > 0 ? MCAMath.getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf) : 0; + int skyLight = this.skyLight.length > 0 ? MCAMath.getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf) : 0; return new LightData(skyLight, blockLight); } - - /** - * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
- * The value is treated as an unsigned byte. - */ - private int getByteHalf(int value, boolean largeHalf) { - value = value & 0xFF; - if (largeHalf) { - value = value >> 4; - } - value = value & 0xF; - return value; - } } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAMath.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAMath.java new file mode 100644 index 00000000..e8ccf810 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAMath.java @@ -0,0 +1,74 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.mca; + +public class MCAMath { + + /** + * Having a long array where each long contains as many values as fit in it without overflowing, returning the "valueIndex"-th value when each value has "bitsPerValue" bits. + */ + public static long getValueFromLongArray(long[] data, int valueIndex, int bitsPerValue) { + int valuesPerLong = 64 / bitsPerValue; + int longIndex = valueIndex / valuesPerLong; + int bitIndex = (valueIndex % valuesPerLong) * bitsPerValue; + + long value = data[longIndex] >>> bitIndex; + + return value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerValue); + } + + /** + * Treating the long array "data" as a continuous stream of bits, returning the "valueIndex"-th value when each value has "bitsPerValue" bits. + */ + public static long getValueFromLongStream(long[] data, int valueIndex, int bitsPerValue) { + int bitIndex = valueIndex * bitsPerValue; + int firstLong = bitIndex >> 6; // index / 64 + int bitoffset = bitIndex & 0x3F; // Math.floorMod(index, 64) + + long value = data[firstLong] >>> bitoffset; + + if (bitoffset > 0 && firstLong + 1 < data.length) { + long value2 = data[firstLong + 1]; + value2 = value2 << -bitoffset; + value = value | value2; + } + + return value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerValue); + } + + /** + * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
+ * The value is treated as an unsigned byte. + */ + public static int getByteHalf(int value, boolean largeHalf) { + value = value & 0xFF; + if (largeHalf) { + value = value >> 4; + } + value = value & 0xF; + return value; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java index e2251f21..bbf95e66 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java @@ -38,7 +38,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.function.Predicate; @@ -506,7 +505,7 @@ public WorldChunkHash(MCAWorld world, Vector2i chunk) { @Override public int hashCode() { - return Objects.hash(world, chunk); + return (world.hashCode() * 31 + chunk.getX()) * 31 + chunk.getY(); } @Override diff --git a/BlueMapCore/src/main/resources/blockColors.json b/BlueMapCore/src/main/resources/blockColors.json index 24cf4889..b5c34f4e 100644 --- a/BlueMapCore/src/main/resources/blockColors.json +++ b/BlueMapCore/src/main/resources/blockColors.json @@ -9,5 +9,6 @@ "minecraft:large_fern": "@grass", "minecraft:redstone_wire": "#ff0000", "minecraft:birch_leaves": "#86a863", - "minecraft:spruce_leaves": "#51946b" + "minecraft:spruce_leaves": "#51946b", + "minecraft:stonecutter": "#ffffff" } \ No newline at end of file diff --git a/BlueMapFabric/build.gradle b/BlueMapFabric/build.gradle new file mode 100644 index 00000000..860b9efc --- /dev/null +++ b/BlueMapFabric/build.gradle @@ -0,0 +1,64 @@ +import net.fabricmc.loom.task.RemapJarTask + +plugins { + id 'fabric-loom' version '0.4-SNAPSHOT' +} + +configurations { + compile.extendsFrom shadowInclude +} + +dependencies { + minecraft "com.mojang:minecraft:1.15.2" + mappings "net.fabricmc:yarn:1.15.2+build.15:v2" + modImplementation "net.fabricmc:fabric-loader:0.8.2+build.194" + modImplementation "net.fabricmc.fabric-api:fabric-api:0.5.1+build.294-1.15" + + shadowInclude (project(':BlueMapCommon')) { + //exclude dependencies provided by fabric + exclude group: 'com.google.guava', module: 'guava' + exclude group: 'com.google.code.gson', module: 'gson' + exclude group: 'org.apache.commons', module: 'commons-lang3' + exclude group: 'commons-io', module: 'commons-io' + exclude group: 'com.mojang', module: 'brigadier' + } +} + +processResources { + inputs.property "version", project.version + + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand "version": project.version + } + + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" + } +} + +shadowJar { + 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' + relocate 'net.querz.nbt', 'de.bluecolored.shadow.querz.nbt' + relocate 'ninja.leaping.configurate', 'de.bluecolored.shadow.ninja.leaping.configurate' + relocate 'org.yaml.snakeyaml', 'de.bluecolored.shadow.yaml.snakeyaml' + + //exclude '/mappings/*' +} + +task ramappedShadowJar(type: RemapJarTask) { + destinationDir = file '../build/unsupported' + dependsOn tasks.shadowJar + input = tasks.shadowJar.archivePath + addNestedDependencies = true + archiveName = "BlueMap-${version}-fabric.jar" +} +build.dependsOn ramappedShadowJar + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricCommandSource.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricCommandSource.java new file mode 100644 index 00000000..ed9b1542 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricCommandSource.java @@ -0,0 +1,84 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.fabric; + +import java.io.IOException; +import java.util.Optional; + +import com.flowpowered.math.vector.Vector3d; + +import de.bluecolored.bluemap.common.plugin.Plugin; +import de.bluecolored.bluemap.common.plugin.serverinterface.CommandSource; +import de.bluecolored.bluemap.common.plugin.text.Text; +import de.bluecolored.bluemap.core.world.World; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; + +public class FabricCommandSource implements CommandSource { + + private FabricMod mod; + private Plugin plugin; + private ServerCommandSource delegate; + + public FabricCommandSource(FabricMod mod, Plugin plugin, ServerCommandSource delegate) { + this.mod = mod; + this.plugin = plugin; + this.delegate = delegate; + } + + @Override + public void sendMessage(Text text) { + delegate.sendFeedback(net.minecraft.text.Text.Serializer.fromJson(text.toJSONString()), false); + } + + @Override + public boolean hasPermission(String permission) { + return delegate.hasPermissionLevel(1); + } + + @Override + public Optional getPosition() { + Vec3d pos = delegate.getPosition(); + if (pos != null) { + return Optional.of(new Vector3d(pos.x, pos.y, pos.z)); + } + + return Optional.empty(); + } + + @Override + public Optional getWorld() { + try { + ServerWorld world = delegate.getWorld(); + if (world != null) { + return Optional.ofNullable(plugin.getWorld(mod.getUUIDForWorld(world))); + } + } catch (IOException ignore) {} + + return Optional.empty(); + } + +} 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..cc3f74c0 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricEventForwarder.java @@ -0,0 +1,119 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.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 new file mode 100644 index 00000000..7f75f262 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/FabricMod.java @@ -0,0 +1,150 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.fabric; + +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 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() { + + //register commands + CommandRegistry.INSTANCE.register(true, dispatcher -> { + 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!"); + }); + } + + @Override + public void registerListener(ServerEventListener listener) { + eventForwarder.addEventListener(listener); + } + + @Override + public void unregisterAllListeners() { + eventForwarder.removeAllListeners(); + } + + @Override + public UUID getUUIDForWorld(File worldFolder) throws IOException { + 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() { + return new File("config/bluemap"); + } + +} diff --git a/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/Log4jLogger.java b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/Log4jLogger.java new file mode 100644 index 00000000..2d298f63 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/Log4jLogger.java @@ -0,0 +1,69 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.fabric; + +import org.apache.logging.log4j.Logger; + +import de.bluecolored.bluemap.core.logger.AbstractLogger; + +public class Log4jLogger extends AbstractLogger { + + private Logger out; + + public Log4jLogger(Logger out) { + this.out = out; + } + + @Override + public void logError(String message, Throwable throwable) { + out.error(message, throwable); + } + + @Override + public void logWarning(String message) { + out.warn(message); + } + + @Override + public void logInfo(String message) { + out.info(message); + } + + @Override + public void logDebug(String message) { + if (out.isDebugEnabled()) out.debug(message); + } + + @Override + public void noFloodDebug(String message) { + if (out.isDebugEnabled()) super.noFloodDebug(message); + } + + @Override + public void noFloodDebug(String key, String message) { + if (out.isDebugEnabled()) super.noFloodDebug(key, message); + } + +} 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..49de240d --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/ChunkFinalizeCallback.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.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..25b2ea9f --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/events/WorldSaveCallback.java @@ -0,0 +1,41 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.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..cb61be07 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinChunkGenerator.java @@ -0,0 +1,56 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.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..a521f0d6 --- /dev/null +++ b/BlueMapFabric/src/main/java/de/bluecolored/bluemap/fabric/mixin/MixinServerWorld.java @@ -0,0 +1,45 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.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/assets/bluemap/icon.png b/BlueMapFabric/src/main/resources/assets/bluemap/icon.png new file mode 100644 index 00000000..65d56d7a Binary files /dev/null and b/BlueMapFabric/src/main/resources/assets/bluemap/icon.png differ 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 new file mode 100644 index 00000000..e8c98a84 --- /dev/null +++ b/BlueMapFabric/src/main/resources/bluemap.mixins.json @@ -0,0 +1,15 @@ +{ + "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/BlueMapFabric/src/main/resources/fabric.mod.json b/BlueMapFabric/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..0cec38f6 --- /dev/null +++ b/BlueMapFabric/src/main/resources/fabric.mod.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "id": "bluemap", + "version": "${version}", + + "name": "BlueMap", + "description": "A 3d-map of your Minecraft worlds view-able in your browser using three.js (WebGL)", + "authors": [ + "Blue (TBlueF, Lukas Rieger)" + ], + "contact": { + "homepage": "https://github.com/BlueMap-Minecraft", + "sources": "https://github.com/BlueMap-Minecraft/BlueMap" + }, + + "license": "MIT", + "icon": "assets/bluemap/icon.png", + + "environment": "*", + "entrypoints": { + "main": [ + "de.bluecolored.bluemap.fabric.FabricMod" + ] + }, + "mixins": [ + "bluemap.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.15.x" + }, + "suggests": {} +} 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 67d5d0fd..5c514c7e 100644 --- a/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java +++ b/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/ForgeMod.java @@ -33,10 +33,14 @@ import java.util.Map; import java.util.Optional; 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; @@ -62,12 +66,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); } @@ -178,6 +193,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(); diff --git a/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/Log4jLogger.java b/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/Log4jLogger.java index 50ae484c..39502606 100644 --- a/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/Log4jLogger.java +++ b/BlueMapForge/src/main/java/de/bluecolored/bluemap/forge/Log4jLogger.java @@ -1,5 +1,5 @@ /* - * This file is part of BlueMapSponge, licensed under the MIT License (MIT). + * This file is part of BlueMap, licensed under the MIT License (MIT). * * Copyright (c) Blue (Lukas Rieger) * Copyright (c) contributors diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java index 9c3787e4..7c873747 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java @@ -1,5 +1,5 @@ /* - * This file is part of BlueMapSponge, licensed under the MIT License (MIT). + * This file is part of BlueMap, licensed under the MIT License (MIT). * * Copyright (c) Blue (Lukas Rieger) * Copyright (c) contributors diff --git a/HEADER b/HEADER new file mode 100644 index 00000000..0473d5e9 --- /dev/null +++ b/HEADER @@ -0,0 +1,24 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0b5089b0..26457e38 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java' id 'com.github.johnrengelman.shadow' version '5.1.0' + id 'com.github.hierynomus.license' version '0.15.0' } allprojects { @@ -24,15 +25,34 @@ allprojects { maven { url "https://libraries.minecraft.net" } + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } } compileJava.options.compilerArgs.add '-parameters' compileTestJava.options.compilerArgs.add '-parameters' + + tasks.withType(JavaCompile) { + options.encoding = "UTF-8" + } apply plugin: 'java' group = 'de.bluecolored.bluemap' version = coreVersion + '-' + targetVersion + + apply plugin: 'license' + license { + header rootProject.file('HEADER') + excludes([ + '*.conf', + '*.yml', + '*.zip', + '*.json' + ]) + } } subprojects { diff --git a/settings.gradle b/settings.gradle index fd1b97fc..dd4abee2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,14 @@ +pluginManagement { + repositories { + jcenter() + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} + rootProject.name = 'BlueMap' include ':BlueMapCore' include ':BlueMapCLI' @@ -6,6 +17,7 @@ include ':BlueMapSponge' include ':BlueMapBukkit' include ':BlueMapForge' include ':BlueMapAPI' +include ':BlueMapFabric' project(':BlueMapCore').projectDir = "$rootDir/BlueMapCore" as File project(':BlueMapCLI').projectDir = "$rootDir/BlueMapCLI" as File @@ -14,3 +26,4 @@ project(':BlueMapSponge').projectDir = "$rootDir/BlueMapSponge" as File project(':BlueMapBukkit').projectDir = "$rootDir/BlueMapBukkit" as File project(':BlueMapForge').projectDir = "$rootDir/BlueMapForge" as File project(':BlueMapAPI').projectDir = "$rootDir/BlueMapAPI" as File +project(':BlueMapFabric').projectDir = "$rootDir/BlueMapFabric" as File