mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 10:35:16 +01:00
Merge branch 'mc/1.13' into feature/live
This commit is contained in:
commit
b64941783f
2
.github/workflows/gradle.yml
vendored
2
.github/workflows/gradle.yml
vendored
@ -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/*
|
||||
|
@ -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) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
|
@ -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) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
|
@ -39,15 +39,18 @@
|
||||
|
||||
public class MapUpdateHandler implements ServerEventListener {
|
||||
|
||||
public Multimap<MapType, Vector2i> updateBuffer;
|
||||
private Plugin plugin;
|
||||
|
||||
public MapUpdateHandler() {
|
||||
private Multimap<MapType, Vector2i> 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()) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ node {
|
||||
download = true
|
||||
}
|
||||
|
||||
license {
|
||||
exclude('**/AABB.java')
|
||||
}
|
||||
|
||||
task fixPackageLock() {
|
||||
if (!file("./package-lock.json").exists()) {
|
||||
file("./package-lock.json").text = ""
|
||||
|
@ -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 = <code>true</code>) or the right (largeHalf = <code>false</code>) side of the byte stored in <code>value</code>.<br>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 = <code>true</code>) or the right (largeHalf = <code>false</code>) side of the byte stored in <code>value</code>.<br>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 = <code>true</code>) or the right (largeHalf = <code>false</code>) side of the byte stored in <code>value</code>.<br>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.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 = <code>true</code>) or the right (largeHalf = <code>false</code>) side of the byte stored in <code>value</code>.<br>
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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"
|
||||
}
|
64
BlueMapFabric/build.gradle
Normal file
64
BlueMapFabric/build.gradle
Normal file
@ -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
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.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<Vector3d> 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<World> getWorld() {
|
||||
try {
|
||||
ServerWorld world = delegate.getWorld();
|
||||
if (world != null) {
|
||||
return Optional.ofNullable(plugin.getWorld(mod.getUUIDForWorld(world)));
|
||||
}
|
||||
} catch (IOException ignore) {}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.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<ServerEventListener> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.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<File, UUID> worldUuids;
|
||||
private FabricEventForwarder eventForwarder;
|
||||
|
||||
private LoadingCache<ServerWorld, UUID> 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<ServerWorld, UUID>() {
|
||||
@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");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.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);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.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<ChunkFinalizeCallback> EVENT = EventFactory.createArrayBacked(ChunkFinalizeCallback.class,
|
||||
(listeners) -> (world, chunkPos) -> {
|
||||
for (ChunkFinalizeCallback event : listeners) {
|
||||
event.onChunkFinalized(world, chunkPos);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
void onChunkFinalized(ServerWorld world, Vector2i chunkPos);
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.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<WorldSaveCallback> EVENT = EventFactory.createArrayBacked(WorldSaveCallback.class,
|
||||
(listeners) -> (world) -> {
|
||||
for (WorldSaveCallback event : listeners) {
|
||||
event.onWorldSaved(world);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
void onWorldSaved(ServerWorld world);
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.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()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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.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);
|
||||
}
|
||||
|
||||
}
|
BIN
BlueMapFabric/src/main/resources/assets/bluemap/icon.png
Normal file
BIN
BlueMapFabric/src/main/resources/assets/bluemap/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -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
|
||||
}
|
166
BlueMapFabric/src/main/resources/bluemap-fabric.conf
Normal file
166
BlueMapFabric/src/main/resources/bluemap-fabric.conf
Normal file
@ -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: <data>/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 "<webroot>/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
|
||||
}
|
||||
|
||||
]
|
15
BlueMapFabric/src/main/resources/bluemap.mixins.json
Normal file
15
BlueMapFabric/src/main/resources/bluemap.mixins.json
Normal file
@ -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
|
||||
}
|
||||
}
|
35
BlueMapFabric/src/main/resources/fabric.mod.json
Normal file
35
BlueMapFabric/src/main/resources/fabric.mod.json
Normal file
@ -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": {}
|
||||
}
|
@ -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<String, UUID> worldUUIDs;
|
||||
private Collection<ServerEventListener> eventListeners;
|
||||
|
||||
private LoadingCache<ServerWorld, UUID> 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<ServerWorld, UUID>() {
|
||||
@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();
|
||||
|
||||
|
@ -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) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
|
@ -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) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
|
24
HEADER
Normal file
24
HEADER
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
20
build.gradle
20
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 {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user