mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-25 20:16:00 +01:00
Add more supported forge and fabric versions
This commit is contained in:
parent
36161a1f49
commit
e6d5058326
65
implementations/fabric-1.15.2/build.gradle
Normal file
65
implementations/fabric-1.15.2/build.gradle
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
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.17:v2"
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:0.9.2+build.206"
|
||||||
|
modImplementation "net.fabricmc.fabric-api:fabric-api:0.19.0+build.325-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'
|
||||||
|
relocate 'com.github.benmanes.caffeine', 'de.bluecolored.shadow.benmanes.caffeine'
|
||||||
|
relocate 'com.google.errorprone', 'de.bluecolored.shadow.google.errorprone'
|
||||||
|
relocate 'org.checkerframework', 'de.bluecolored.shadow.checkerframework'
|
||||||
|
}
|
||||||
|
|
||||||
|
task ramappedShadowJar(type: RemapJarTask) {
|
||||||
|
destinationDir = file '../../build/release'
|
||||||
|
dependsOn tasks.shadowJar
|
||||||
|
input = tasks.shadowJar.archivePath
|
||||||
|
addNestedDependencies = true
|
||||||
|
archiveName = "BlueMap-${version}-fabric-1.15.2.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,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
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);
|
||||||
|
|
||||||
|
PlayerJoinCallback.EVENT.register(this::onPlayerJoin);
|
||||||
|
PlayerLeaveCallback.EVENT.register(this::onPlayerLeave);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addEventListener(ServerEventListener listener) {
|
||||||
|
this.eventListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized 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 synchronized void onBlockChange(ServerWorld world, BlockPos blockPos) {
|
||||||
|
Vector3i position = new Vector3i(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onBlockChange(uuid, position);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onWorldSave(ServerWorld world) {
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(uuid);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onChunkFinalize(ServerWorld world, Vector2i chunkPos) {
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onChunkFinishedGeneration(uuid, chunkPos);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.mod.getServer() != server) return;
|
||||||
|
|
||||||
|
UUID uuid = player.getUuid();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerJoin(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.mod.getServer() != server) return;
|
||||||
|
|
||||||
|
UUID uuid = player.getUuid();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerLeave(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* 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.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.commands.Commands;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||||
|
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
|
||||||
|
public class FabricMod implements ModInitializer, ServerInterface {
|
||||||
|
|
||||||
|
private Plugin pluginInstance = null;
|
||||||
|
private MinecraftServer serverInstance = null;
|
||||||
|
|
||||||
|
private Map<File, UUID> worldUUIDs;
|
||||||
|
private FabricEventForwarder eventForwarder;
|
||||||
|
|
||||||
|
private LoadingCache<ServerWorld, UUID> worldUuidCache;
|
||||||
|
|
||||||
|
private int playerUpdateIndex = 0;
|
||||||
|
private Map<UUID, Player> onlinePlayerMap;
|
||||||
|
private List<FabricPlayer> onlinePlayerList;
|
||||||
|
|
||||||
|
public FabricMod() {
|
||||||
|
Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME));
|
||||||
|
|
||||||
|
this.onlinePlayerMap = new ConcurrentHashMap<>();
|
||||||
|
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
pluginInstance = new Plugin(MinecraftVersion.MC_1_15, "fabric", this);
|
||||||
|
|
||||||
|
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||||
|
this.eventForwarder = new FabricEventForwarder(this);
|
||||||
|
this.worldUuidCache = Caffeine.newBuilder()
|
||||||
|
.weakKeys()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build(this::loadUUIDForWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
|
||||||
|
//register commands
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
|
||||||
|
new Commands<>(pluginInstance, dispatcher, fabricSource -> new FabricCommandSource(this, pluginInstance, fabricSource));
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register((MinecraftServer server) -> {
|
||||||
|
this.serverInstance = server;
|
||||||
|
|
||||||
|
new Thread(()->{
|
||||||
|
Logger.global.logInfo("Loading BlueMap...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
pluginInstance.load();
|
||||||
|
if (pluginInstance.isLoaded()) Logger.global.logInfo("BlueMap loaded!");
|
||||||
|
} catch (IOException | ParseResourceException e) {
|
||||||
|
Logger.global.logError("Failed to load bluemap!", e);
|
||||||
|
pluginInstance.unload();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STOPPING.register((MinecraftServer server) -> {
|
||||||
|
pluginInstance.unload();
|
||||||
|
Logger.global.logInfo("BlueMap unloaded!");
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerJoinCallback.EVENT.register(this::onPlayerJoin);
|
||||||
|
PlayerLeaveCallback.EVENT.register(this::onPlayerLeave);
|
||||||
|
|
||||||
|
ServerTickEvents.END_SERVER_TICK.register((MinecraftServer server) -> {
|
||||||
|
if (server == this.serverInstance) this.updateSomePlayers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (RuntimeException 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.getCanonicalFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getConfigFolder() {
|
||||||
|
return new File("config/bluemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerJoin(MinecraftServer server, ServerPlayerEntity playerInstance) {
|
||||||
|
if (this.serverInstance != server) return;
|
||||||
|
|
||||||
|
FabricPlayer player = new FabricPlayer(this, playerInstance);
|
||||||
|
onlinePlayerMap.put(player.getUuid(), player);
|
||||||
|
onlinePlayerList.add(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.serverInstance != server) return;
|
||||||
|
|
||||||
|
UUID playerUUID = player.getUuid();
|
||||||
|
onlinePlayerMap.remove(playerUUID);
|
||||||
|
synchronized (onlinePlayerList) {
|
||||||
|
onlinePlayerList.removeIf(p -> p.getUuid().equals(playerUUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftServer getServer() {
|
||||||
|
return this.serverInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Player> getOnlinePlayers() {
|
||||||
|
return onlinePlayerMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Player> getPlayer(UUID uuid) {
|
||||||
|
return Optional.ofNullable(onlinePlayerMap.get(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only update some of the online players each tick to minimize performance impact on the server-thread.
|
||||||
|
* Only call this method on the server-thread.
|
||||||
|
*/
|
||||||
|
private void updateSomePlayers() {
|
||||||
|
int onlinePlayerCount = onlinePlayerList.size();
|
||||||
|
if (onlinePlayerCount == 0) return;
|
||||||
|
|
||||||
|
int playersToBeUpdated = onlinePlayerCount / 20; //with 20 tps, each player is updated once a second
|
||||||
|
if (playersToBeUpdated == 0) playersToBeUpdated = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < playersToBeUpdated; i++) {
|
||||||
|
playerUpdateIndex++;
|
||||||
|
if (playerUpdateIndex >= 20 && playerUpdateIndex >= onlinePlayerCount) playerUpdateIndex = 0;
|
||||||
|
|
||||||
|
if (playerUpdateIndex < onlinePlayerCount) {
|
||||||
|
onlinePlayerList.get(playerUpdateIndex).update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.ref.WeakReference;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3d;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Gamemode;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.text.Text;
|
||||||
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.GameMode;
|
||||||
|
|
||||||
|
public class FabricPlayer implements Player {
|
||||||
|
|
||||||
|
private static final UUID UNKNOWN_WORLD_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
private static final Map<GameMode, Gamemode> GAMEMODE_MAP = new EnumMap<>(GameMode.class);
|
||||||
|
static {
|
||||||
|
GAMEMODE_MAP.put(GameMode.ADVENTURE, Gamemode.ADVENTURE);
|
||||||
|
GAMEMODE_MAP.put(GameMode.SURVIVAL, Gamemode.SURVIVAL);
|
||||||
|
GAMEMODE_MAP.put(GameMode.CREATIVE, Gamemode.CREATIVE);
|
||||||
|
GAMEMODE_MAP.put(GameMode.SPECTATOR, Gamemode.SPECTATOR);
|
||||||
|
GAMEMODE_MAP.put(GameMode.NOT_SET, Gamemode.SURVIVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private Text name;
|
||||||
|
private UUID world;
|
||||||
|
private Vector3d position;
|
||||||
|
private boolean online;
|
||||||
|
private boolean sneaking;
|
||||||
|
private boolean invisible;
|
||||||
|
private Gamemode gamemode;
|
||||||
|
|
||||||
|
private FabricMod mod;
|
||||||
|
private WeakReference<ServerPlayerEntity> delegate;
|
||||||
|
|
||||||
|
public FabricPlayer(FabricMod mod, ServerPlayerEntity delegate) {
|
||||||
|
this.uuid = delegate.getUuid();
|
||||||
|
this.mod = mod;
|
||||||
|
this.delegate = new WeakReference<>(delegate);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUuid() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getWorld() {
|
||||||
|
return this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnline() {
|
||||||
|
return this.online;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSneaking() {
|
||||||
|
return this.sneaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible() {
|
||||||
|
return this.invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Gamemode getGamemode() {
|
||||||
|
return this.gamemode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only call on server thread!
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
ServerPlayerEntity player = delegate.get();
|
||||||
|
if (player == null) {
|
||||||
|
MinecraftServer server = mod.getServer();
|
||||||
|
if (server != null) {
|
||||||
|
player = server.getPlayerManager().getPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
this.online = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate = new WeakReference<>(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gamemode = GAMEMODE_MAP.get(player.interactionManager.getGameMode());
|
||||||
|
|
||||||
|
StatusEffectInstance invis = player.getStatusEffect(StatusEffects.INVISIBILITY);
|
||||||
|
this.invisible = invis != null && invis.getDuration() > 0;
|
||||||
|
|
||||||
|
this.name = Text.of(player.getName().getString());
|
||||||
|
this.online = true;
|
||||||
|
|
||||||
|
Vec3d pos = player.getPos();
|
||||||
|
this.position = new Vector3d(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.sneaking = player.isSneaking();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.world = mod.getUUIDForWorld(player.getServerWorld());
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.world = UNKNOWN_WORLD_UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
public interface PlayerJoinCallback {
|
||||||
|
Event<PlayerJoinCallback> EVENT = EventFactory.createArrayBacked(PlayerJoinCallback.class,
|
||||||
|
(listeners) -> (server, player) -> {
|
||||||
|
for (PlayerJoinCallback event : listeners) {
|
||||||
|
event.onPlayerJoin(server, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player);
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
public interface PlayerLeaveCallback {
|
||||||
|
Event<PlayerLeaveCallback> EVENT = EventFactory.createArrayBacked(PlayerLeaveCallback.class,
|
||||||
|
(listeners) -> (server, player) -> {
|
||||||
|
for (PlayerLeaveCallback event : listeners) {
|
||||||
|
event.onPlayerLeave(server, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player);
|
||||||
|
}
|
@ -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,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.flowpowered.math.vector.Vector2i;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.fabric.events.ChunkFinalizeCallback;
|
||||||
|
import net.minecraft.world.ChunkRegion;
|
||||||
|
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||||
|
|
||||||
|
@Mixin(ChunkGenerator.class)
|
||||||
|
public class MixinChunkGenerator {
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "generateFeatures")
|
||||||
|
public void generateFeatures(ChunkRegion region, CallbackInfo ci) {
|
||||||
|
ChunkFinalizeCallback.EVENT.invoker().onChunkFinalized(region.getWorld(), new Vector2i(region.getCenterChunkX(), region.getCenterChunkZ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.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 de.bluecolored.bluemap.fabric.events.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
import net.minecraft.network.ClientConnection;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.PlayerManager;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
@Mixin(PlayerManager.class)
|
||||||
|
public abstract class MixinPlayerManager {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
public abstract MinecraftServer getServer();
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "onPlayerConnect")
|
||||||
|
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) {
|
||||||
|
PlayerJoinCallback.EVENT.invoker().onPlayerJoin(this.getServer(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("HEAD"), method = "remove")
|
||||||
|
public void remove(ServerPlayerEntity player, CallbackInfo ci) {
|
||||||
|
PlayerLeaveCallback.EVENT.invoker().onPlayerLeave(this.getServer(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
@Mixin(ServerWorld.class)
|
||||||
|
public abstract class MixinServerWorld {
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "save")
|
||||||
|
public void save(ProgressListener progressListener, boolean flush, boolean bl, CallbackInfo ci) {
|
||||||
|
WorldSaveCallback.EVENT.invoker().onWorldSaved((ServerWorld) (Object) this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "de.bluecolored.bluemap.fabric.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_8",
|
||||||
|
"mixins": [],
|
||||||
|
"client": [],
|
||||||
|
"server": [
|
||||||
|
"MixinChunkGenerator",
|
||||||
|
"MixinPlayerManager",
|
||||||
|
"MixinServerWorld"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,30 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Core-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
|
||||||
|
# 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":"bukkit","version":"%version%"}
|
||||||
|
# Default is true
|
||||||
|
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.
|
||||||
|
# Default is "bluemap"
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,27 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Plugin-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# If the server should send live-updates and player-positions.
|
||||||
|
# This only works if the integrated webserver is enabled.
|
||||||
|
# Default is true
|
||||||
|
liveUpdates: true
|
||||||
|
|
||||||
|
# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers.
|
||||||
|
# Default is true
|
||||||
|
skinDownload: true
|
||||||
|
|
||||||
|
# A list of gamemodes that will prevent a player from appearing on the map.
|
||||||
|
# Possible values are: survival, creative, spectator, adventure
|
||||||
|
hiddenGameModes: [
|
||||||
|
"spectator"
|
||||||
|
]
|
||||||
|
|
||||||
|
# If this is true, players that have an invisibility (potion-)effect will be hidden on the map.
|
||||||
|
# Default is true
|
||||||
|
hideInvisible: true
|
||||||
|
|
||||||
|
# If this is true, players that are sneaking will be hidden on the map.
|
||||||
|
# Default is false
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -0,0 +1,126 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Render-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
|
useCookies: true
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks.
|
||||||
|
# If this is set to true BlueMap will render Chunks even if there is no light-data!
|
||||||
|
# This can be usefull for example if some mod prevents light-data from being saved correctly.
|
||||||
|
# However, this also has a few drawbacks:
|
||||||
|
# - For those chunks, every block will always be fully lit
|
||||||
|
# - Night-mode might not work correctly
|
||||||
|
# - Caves will always be rendered (ignoring the 'renderCaves' setting)
|
||||||
|
# Default is false
|
||||||
|
ignoreMissingLightData: false
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -0,0 +1,29 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Webserver-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 webroot that the server will host to the web.
|
||||||
|
# Usually this should be set to the same directory like in the Core-Config!
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# The IP-Adress that the webserver binds to.
|
||||||
|
# Use "0.0.0.0" to bind to all available local adresses.
|
||||||
|
# If you only want to access it locally use "localhost".
|
||||||
|
# Default is "0.0.0.0"
|
||||||
|
#ip: "localhost"
|
||||||
|
#ip: "123.45.6.78"
|
||||||
|
|
||||||
|
# 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
|
@ -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.9.0",
|
||||||
|
"fabric": "*",
|
||||||
|
"minecraft": "1.15.2"
|
||||||
|
},
|
||||||
|
"suggests": {}
|
||||||
|
}
|
65
implementations/fabric-1.16.1/build.gradle
Normal file
65
implementations/fabric-1.16.1/build.gradle
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import net.fabricmc.loom.task.RemapJarTask
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'fabric-loom' version '0.4-SNAPSHOT'
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compile.extendsFrom shadowInclude
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
minecraft "com.mojang:minecraft:1.16.1"
|
||||||
|
mappings "net.fabricmc:yarn:1.16.1+build.21:v2"
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:0.9.2+build.206"
|
||||||
|
modImplementation "net.fabricmc.fabric-api:fabric-api:0.16.2+build.385-1.16.1"
|
||||||
|
|
||||||
|
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'
|
||||||
|
relocate 'com.github.benmanes.caffeine', 'de.bluecolored.shadow.benmanes.caffeine'
|
||||||
|
relocate 'com.google.errorprone', 'de.bluecolored.shadow.google.errorprone'
|
||||||
|
relocate 'org.checkerframework', 'de.bluecolored.shadow.checkerframework'
|
||||||
|
}
|
||||||
|
|
||||||
|
task ramappedShadowJar(type: RemapJarTask) {
|
||||||
|
destinationDir = file '../../build/release'
|
||||||
|
dependsOn tasks.shadowJar
|
||||||
|
input = tasks.shadowJar.archivePath
|
||||||
|
addNestedDependencies = true
|
||||||
|
archiveName = "BlueMap-${version}-fabric-1.16.1.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,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
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);
|
||||||
|
|
||||||
|
PlayerJoinCallback.EVENT.register(this::onPlayerJoin);
|
||||||
|
PlayerLeaveCallback.EVENT.register(this::onPlayerLeave);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addEventListener(ServerEventListener listener) {
|
||||||
|
this.eventListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized 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 synchronized void onBlockChange(ServerWorld world, BlockPos blockPos) {
|
||||||
|
Vector3i position = new Vector3i(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onBlockChange(uuid, position);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onWorldSave(ServerWorld world) {
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(uuid);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onChunkFinalize(ServerWorld world, Vector2i chunkPos) {
|
||||||
|
try {
|
||||||
|
UUID uuid = mod.getUUIDForWorld(world);
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onChunkFinishedGeneration(uuid, chunkPos);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.mod.getServer() != server) return;
|
||||||
|
|
||||||
|
UUID uuid = player.getUuid();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerJoin(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.mod.getServer() != server) return;
|
||||||
|
|
||||||
|
UUID uuid = player.getUuid();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerLeave(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* 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.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.commands.Commands;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||||
|
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
|
|
||||||
|
public class FabricMod implements ModInitializer, ServerInterface {
|
||||||
|
|
||||||
|
private Plugin pluginInstance = null;
|
||||||
|
private MinecraftServer serverInstance = null;
|
||||||
|
|
||||||
|
private Map<File, UUID> worldUUIDs;
|
||||||
|
private FabricEventForwarder eventForwarder;
|
||||||
|
|
||||||
|
private LoadingCache<ServerWorld, UUID> worldUuidCache;
|
||||||
|
|
||||||
|
private int playerUpdateIndex = 0;
|
||||||
|
private Map<UUID, Player> onlinePlayerMap;
|
||||||
|
private List<FabricPlayer> onlinePlayerList;
|
||||||
|
|
||||||
|
public FabricMod() {
|
||||||
|
Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME));
|
||||||
|
|
||||||
|
this.onlinePlayerMap = new ConcurrentHashMap<>();
|
||||||
|
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
pluginInstance = new Plugin(MinecraftVersion.MC_1_16, "fabric", this);
|
||||||
|
|
||||||
|
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||||
|
this.eventForwarder = new FabricEventForwarder(this);
|
||||||
|
this.worldUuidCache = Caffeine.newBuilder()
|
||||||
|
.weakKeys()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build(this::loadUUIDForWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
|
||||||
|
//register commands
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
|
||||||
|
new Commands<>(pluginInstance, dispatcher, fabricSource -> new FabricCommandSource(this, pluginInstance, fabricSource));
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register((MinecraftServer server) -> {
|
||||||
|
this.serverInstance = server;
|
||||||
|
|
||||||
|
new Thread(()->{
|
||||||
|
Logger.global.logInfo("Loading BlueMap...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
pluginInstance.load();
|
||||||
|
if (pluginInstance.isLoaded()) Logger.global.logInfo("BlueMap loaded!");
|
||||||
|
} catch (IOException | ParseResourceException e) {
|
||||||
|
Logger.global.logError("Failed to load bluemap!", e);
|
||||||
|
pluginInstance.unload();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STOPPING.register((MinecraftServer server) -> {
|
||||||
|
pluginInstance.unload();
|
||||||
|
Logger.global.logInfo("BlueMap unloaded!");
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerJoinCallback.EVENT.register(this::onPlayerJoin);
|
||||||
|
PlayerLeaveCallback.EVENT.register(this::onPlayerLeave);
|
||||||
|
|
||||||
|
ServerTickEvents.END_SERVER_TICK.register((MinecraftServer server) -> {
|
||||||
|
if (server == this.serverInstance) this.updateSomePlayers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (RuntimeException e) {
|
||||||
|
Throwable cause = e.getCause();
|
||||||
|
if (cause instanceof IOException) throw (IOException) cause;
|
||||||
|
else throw new IOException(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID loadUUIDForWorld(ServerWorld world) throws IOException {
|
||||||
|
MinecraftServer server = world.getServer();
|
||||||
|
String worldName = server.getSaveProperties().getLevelName();
|
||||||
|
File worldFolder = new File(world.getServer().getRunDirectory(), worldName);
|
||||||
|
File dimensionFolder = DimensionType.getSaveDirectory(world.getRegistryKey(), worldFolder);
|
||||||
|
File dimensionDir = dimensionFolder.getCanonicalFile();
|
||||||
|
return getUUIDForWorld(dimensionDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getConfigFolder() {
|
||||||
|
return new File("config/bluemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerJoin(MinecraftServer server, ServerPlayerEntity playerInstance) {
|
||||||
|
if (this.serverInstance != server) return;
|
||||||
|
|
||||||
|
FabricPlayer player = new FabricPlayer(this, playerInstance);
|
||||||
|
onlinePlayerMap.put(player.getUuid(), player);
|
||||||
|
onlinePlayerList.add(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||||
|
if (this.serverInstance != server) return;
|
||||||
|
|
||||||
|
UUID playerUUID = player.getUuid();
|
||||||
|
onlinePlayerMap.remove(playerUUID);
|
||||||
|
synchronized (onlinePlayerList) {
|
||||||
|
onlinePlayerList.removeIf(p -> p.getUuid().equals(playerUUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftServer getServer() {
|
||||||
|
return this.serverInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Player> getOnlinePlayers() {
|
||||||
|
return onlinePlayerMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Player> getPlayer(UUID uuid) {
|
||||||
|
return Optional.ofNullable(onlinePlayerMap.get(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only update some of the online players each tick to minimize performance impact on the server-thread.
|
||||||
|
* Only call this method on the server-thread.
|
||||||
|
*/
|
||||||
|
private void updateSomePlayers() {
|
||||||
|
int onlinePlayerCount = onlinePlayerList.size();
|
||||||
|
if (onlinePlayerCount == 0) return;
|
||||||
|
|
||||||
|
int playersToBeUpdated = onlinePlayerCount / 20; //with 20 tps, each player is updated once a second
|
||||||
|
if (playersToBeUpdated == 0) playersToBeUpdated = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < playersToBeUpdated; i++) {
|
||||||
|
playerUpdateIndex++;
|
||||||
|
if (playerUpdateIndex >= 20 && playerUpdateIndex >= onlinePlayerCount) playerUpdateIndex = 0;
|
||||||
|
|
||||||
|
if (playerUpdateIndex < onlinePlayerCount) {
|
||||||
|
onlinePlayerList.get(playerUpdateIndex).update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.ref.WeakReference;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3d;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Gamemode;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.text.Text;
|
||||||
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.GameMode;
|
||||||
|
|
||||||
|
public class FabricPlayer implements Player {
|
||||||
|
|
||||||
|
private static final UUID UNKNOWN_WORLD_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
private static final Map<GameMode, Gamemode> GAMEMODE_MAP = new EnumMap<>(GameMode.class);
|
||||||
|
static {
|
||||||
|
GAMEMODE_MAP.put(GameMode.ADVENTURE, Gamemode.ADVENTURE);
|
||||||
|
GAMEMODE_MAP.put(GameMode.SURVIVAL, Gamemode.SURVIVAL);
|
||||||
|
GAMEMODE_MAP.put(GameMode.CREATIVE, Gamemode.CREATIVE);
|
||||||
|
GAMEMODE_MAP.put(GameMode.SPECTATOR, Gamemode.SPECTATOR);
|
||||||
|
GAMEMODE_MAP.put(GameMode.NOT_SET, Gamemode.SURVIVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private Text name;
|
||||||
|
private UUID world;
|
||||||
|
private Vector3d position;
|
||||||
|
private boolean online;
|
||||||
|
private boolean sneaking;
|
||||||
|
private boolean invisible;
|
||||||
|
private Gamemode gamemode;
|
||||||
|
|
||||||
|
private FabricMod mod;
|
||||||
|
private WeakReference<ServerPlayerEntity> delegate;
|
||||||
|
|
||||||
|
public FabricPlayer(FabricMod mod, ServerPlayerEntity delegate) {
|
||||||
|
this.uuid = delegate.getUuid();
|
||||||
|
this.mod = mod;
|
||||||
|
this.delegate = new WeakReference<>(delegate);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUuid() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getWorld() {
|
||||||
|
return this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnline() {
|
||||||
|
return this.online;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSneaking() {
|
||||||
|
return this.sneaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible() {
|
||||||
|
return this.invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Gamemode getGamemode() {
|
||||||
|
return this.gamemode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only call on server thread!
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
ServerPlayerEntity player = delegate.get();
|
||||||
|
if (player == null) {
|
||||||
|
MinecraftServer server = mod.getServer();
|
||||||
|
if (server != null) {
|
||||||
|
player = server.getPlayerManager().getPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
this.online = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate = new WeakReference<>(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gamemode = GAMEMODE_MAP.get(player.interactionManager.getGameMode());
|
||||||
|
|
||||||
|
StatusEffectInstance invis = player.getStatusEffect(StatusEffects.INVISIBILITY);
|
||||||
|
this.invisible = invis != null && invis.getDuration() > 0;
|
||||||
|
|
||||||
|
this.name = Text.of(player.getName().getString());
|
||||||
|
this.online = true;
|
||||||
|
|
||||||
|
Vec3d pos = player.getPos();
|
||||||
|
this.position = new Vector3d(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.sneaking = player.isSneaking();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.world = mod.getUUIDForWorld(player.getServerWorld());
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.world = UNKNOWN_WORLD_UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
public interface PlayerJoinCallback {
|
||||||
|
Event<PlayerJoinCallback> EVENT = EventFactory.createArrayBacked(PlayerJoinCallback.class,
|
||||||
|
(listeners) -> (server, player) -> {
|
||||||
|
for (PlayerJoinCallback event : listeners) {
|
||||||
|
event.onPlayerJoin(server, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player);
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
public interface PlayerLeaveCallback {
|
||||||
|
Event<PlayerLeaveCallback> EVENT = EventFactory.createArrayBacked(PlayerLeaveCallback.class,
|
||||||
|
(listeners) -> (server, player) -> {
|
||||||
|
for (PlayerLeaveCallback event : listeners) {
|
||||||
|
event.onPlayerLeave(server, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player);
|
||||||
|
}
|
@ -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,47 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.flowpowered.math.vector.Vector2i;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.fabric.events.ChunkFinalizeCallback;
|
||||||
|
import net.minecraft.world.ChunkRegion;
|
||||||
|
import net.minecraft.world.gen.StructureAccessor;
|
||||||
|
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||||
|
|
||||||
|
@Mixin(ChunkGenerator.class)
|
||||||
|
public class MixinChunkGenerator {
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "generateFeatures")
|
||||||
|
public void generateFeatures(ChunkRegion region, StructureAccessor accessor, CallbackInfo ci) {
|
||||||
|
ChunkFinalizeCallback.EVENT.invoker().onChunkFinalized(region.getWorld(), new Vector2i(region.getCenterChunkX(), region.getCenterChunkZ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.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 de.bluecolored.bluemap.fabric.events.PlayerJoinCallback;
|
||||||
|
import de.bluecolored.bluemap.fabric.events.PlayerLeaveCallback;
|
||||||
|
import net.minecraft.network.ClientConnection;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.PlayerManager;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
@Mixin(PlayerManager.class)
|
||||||
|
public abstract class MixinPlayerManager {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
public abstract MinecraftServer getServer();
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "onPlayerConnect")
|
||||||
|
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) {
|
||||||
|
PlayerJoinCallback.EVENT.invoker().onPlayerJoin(this.getServer(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("HEAD"), method = "remove")
|
||||||
|
public void remove(ServerPlayerEntity player, CallbackInfo ci) {
|
||||||
|
PlayerLeaveCallback.EVENT.invoker().onPlayerLeave(this.getServer(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
@Mixin(ServerWorld.class)
|
||||||
|
public abstract class MixinServerWorld {
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "save")
|
||||||
|
public void save(ProgressListener progressListener, boolean flush, boolean bl, CallbackInfo ci) {
|
||||||
|
WorldSaveCallback.EVENT.invoker().onWorldSaved((ServerWorld) (Object) this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "de.bluecolored.bluemap.fabric.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_8",
|
||||||
|
"mixins": [],
|
||||||
|
"client": [],
|
||||||
|
"server": [
|
||||||
|
"MixinChunkGenerator",
|
||||||
|
"MixinPlayerManager",
|
||||||
|
"MixinServerWorld"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,30 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Core-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
|
||||||
|
# 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":"bukkit","version":"%version%"}
|
||||||
|
# Default is true
|
||||||
|
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.
|
||||||
|
# Default is "bluemap"
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,27 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Plugin-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# If the server should send live-updates and player-positions.
|
||||||
|
# This only works if the integrated webserver is enabled.
|
||||||
|
# Default is true
|
||||||
|
liveUpdates: true
|
||||||
|
|
||||||
|
# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers.
|
||||||
|
# Default is true
|
||||||
|
skinDownload: true
|
||||||
|
|
||||||
|
# A list of gamemodes that will prevent a player from appearing on the map.
|
||||||
|
# Possible values are: survival, creative, spectator, adventure
|
||||||
|
hiddenGameModes: [
|
||||||
|
"spectator"
|
||||||
|
]
|
||||||
|
|
||||||
|
# If this is true, players that have an invisibility (potion-)effect will be hidden on the map.
|
||||||
|
# Default is true
|
||||||
|
hideInvisible: true
|
||||||
|
|
||||||
|
# If this is true, players that are sneaking will be hidden on the map.
|
||||||
|
# Default is false
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -0,0 +1,126 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Render-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
|
useCookies: true
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks.
|
||||||
|
# If this is set to true BlueMap will render Chunks even if there is no light-data!
|
||||||
|
# This can be usefull for example if some mod prevents light-data from being saved correctly.
|
||||||
|
# However, this also has a few drawbacks:
|
||||||
|
# - For those chunks, every block will always be fully lit
|
||||||
|
# - Night-mode might not work correctly
|
||||||
|
# - Caves will always be rendered (ignoring the 'renderCaves' setting)
|
||||||
|
# Default is false
|
||||||
|
ignoreMissingLightData: false
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -0,0 +1,29 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Webserver-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 webroot that the server will host to the web.
|
||||||
|
# Usually this should be set to the same directory like in the Core-Config!
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# The IP-Adress that the webserver binds to.
|
||||||
|
# Use "0.0.0.0" to bind to all available local adresses.
|
||||||
|
# If you only want to access it locally use "localhost".
|
||||||
|
# Default is "0.0.0.0"
|
||||||
|
#ip: "localhost"
|
||||||
|
#ip: "123.45.6.78"
|
||||||
|
|
||||||
|
# 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
|
@ -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.9.0",
|
||||||
|
"fabric": "*",
|
||||||
|
"minecraft": "1.16.1"
|
||||||
|
},
|
||||||
|
"suggests": {}
|
||||||
|
}
|
@ -12,7 +12,7 @@ dependencies {
|
|||||||
minecraft "com.mojang:minecraft:1.16.2"
|
minecraft "com.mojang:minecraft:1.16.2"
|
||||||
mappings "net.fabricmc:yarn:1.16.2+build.21:v2"
|
mappings "net.fabricmc:yarn:1.16.2+build.21:v2"
|
||||||
modImplementation "net.fabricmc:fabric-loader:0.9.2+build.206"
|
modImplementation "net.fabricmc:fabric-loader:0.9.2+build.206"
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:0.16.2+build.385-1.16.1"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:0.19.0+build.398-1.16"
|
||||||
|
|
||||||
shadowInclude (project(':BlueMapCommon')) {
|
shadowInclude (project(':BlueMapCommon')) {
|
||||||
//exclude dependencies provided by fabric
|
//exclude dependencies provided by fabric
|
||||||
|
67
implementations/forge-1.14.4/build.gradle
Normal file
67
implementations/forge-1.14.4/build.gradle
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven { url = 'https://files.minecraftforge.net/maven/' }
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'net.minecraftforge.gradle'
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
mappings channel: 'snapshot', version: '20190719-1.14.3'
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compile.extendsFrom include
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
minecraft 'net.minecraftforge:forge:1.14.4-28.2.0'
|
||||||
|
|
||||||
|
include (project(':BlueMapCommon')) {
|
||||||
|
//exclude dependencies provided by forge
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.dependsOn shadowJar {
|
||||||
|
destinationDir = file '../../build/release'
|
||||||
|
archiveFileName = "BlueMap-${version}-forge-1.14.4.jar"
|
||||||
|
|
||||||
|
configurations = [project.configurations.include]
|
||||||
|
|
||||||
|
//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'
|
||||||
|
relocate 'com.github.benmanes.caffeine', 'de.bluecolored.shadow.benmanes.caffeine'
|
||||||
|
relocate 'com.google.errorprone', 'de.bluecolored.shadow.google.errorprone'
|
||||||
|
relocate 'org.checkerframework', 'de.bluecolored.shadow.checkerframework'
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
|
include 'mcmod.info','META-INF/mods.toml'
|
||||||
|
|
||||||
|
expand (
|
||||||
|
version: project.version
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
reobf {
|
||||||
|
shadowJar {
|
||||||
|
mappings = createMcpToSrg.output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.forge;
|
||||||
|
|
||||||
|
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.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
|
||||||
|
public class ForgeCommandSource implements CommandSource {
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private Plugin plugin;
|
||||||
|
private net.minecraft.command.CommandSource delegate;
|
||||||
|
|
||||||
|
public ForgeCommandSource(ForgeMod mod, Plugin plugin, net.minecraft.command.CommandSource delegate) {
|
||||||
|
this.mod = mod;
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Text text) {
|
||||||
|
delegate.sendFeedback(ITextComponent.Serializer.fromJson(text.toJSONString()), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(String permission) {
|
||||||
|
return delegate.hasPermissionLevel(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Vector3d> getPosition() {
|
||||||
|
Vec3d pos = delegate.getPos();
|
||||||
|
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,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.bluecolored.bluemap.forge;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
|
||||||
|
import net.minecraftforge.event.world.BlockEvent;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
|
||||||
|
public class ForgeEventForwarder {
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private Collection<ServerEventListener> eventListeners;
|
||||||
|
|
||||||
|
public ForgeEventForwarder(ForgeMod mod) {
|
||||||
|
this.mod = mod;
|
||||||
|
this.eventListeners = new ArrayList<>(1);
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addEventListener(ServerEventListener listener) {
|
||||||
|
this.eventListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeAllListeners() {
|
||||||
|
this.eventListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onBlockBreak(BlockEvent.BreakEvent evt) {
|
||||||
|
onBlockChange(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onBlockPlace(BlockEvent.EntityPlaceEvent evt) {
|
||||||
|
onBlockChange(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void onBlockChange(BlockEvent evt) {
|
||||||
|
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID world = mod.getUUIDForWorld((ServerWorld) evt.getWorld());
|
||||||
|
Vector3i position = new Vector3i(
|
||||||
|
evt.getPos().getX(),
|
||||||
|
evt.getPos().getY(),
|
||||||
|
evt.getPos().getZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onBlockChange(world, position);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onWorldSave(WorldEvent.Save evt) {
|
||||||
|
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID world = mod.getUUIDForWorld((ServerWorld) evt.getWorld());
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(world);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onPlayerJoin(PlayerLoggedInEvent evt) {
|
||||||
|
UUID uuid = evt.getPlayer().getUniqueID();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerJoin(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onPlayerLeave(PlayerLoggedOutEvent evt) {
|
||||||
|
UUID uuid = evt.getPlayer().getUniqueID();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerLeave(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* 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.forge;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.commands.Commands;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||||
|
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.TickEvent.ServerTickEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
|
||||||
|
|
||||||
|
@Mod(Plugin.PLUGIN_ID)
|
||||||
|
public class ForgeMod implements ServerInterface {
|
||||||
|
|
||||||
|
private Plugin pluginInstance = null;
|
||||||
|
private MinecraftServer serverInstance = null;
|
||||||
|
|
||||||
|
private Map<File, UUID> worldUUIDs;
|
||||||
|
private ForgeEventForwarder eventForwarder;
|
||||||
|
|
||||||
|
private LoadingCache<ServerWorld, UUID> worldUuidCache;
|
||||||
|
|
||||||
|
private int playerUpdateIndex = 0;
|
||||||
|
private Map<UUID, Player> onlinePlayerMap;
|
||||||
|
private List<ForgePlayer> onlinePlayerList;
|
||||||
|
|
||||||
|
public ForgeMod() {
|
||||||
|
Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME));
|
||||||
|
|
||||||
|
this.onlinePlayerMap = new ConcurrentHashMap<>();
|
||||||
|
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
this.pluginInstance = new Plugin(MinecraftVersion.MC_1_14, "forge", this);
|
||||||
|
|
||||||
|
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||||
|
this.eventForwarder = new ForgeEventForwarder(this);
|
||||||
|
this.worldUuidCache = Caffeine.newBuilder()
|
||||||
|
.weakKeys()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build(this::loadUUIDForWorld);
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerStarting(FMLServerStartingEvent event) {
|
||||||
|
this.worldUUIDs.clear();
|
||||||
|
|
||||||
|
//save worlds to generate level.dat files
|
||||||
|
event.getServer().save(false, true, true);
|
||||||
|
|
||||||
|
//register commands
|
||||||
|
new Commands<>(pluginInstance, event.getServer().getCommandManager().getDispatcher(), forgeSource -> new ForgeCommandSource(this, pluginInstance, forgeSource));
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
Logger.global.logInfo("Loading...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
pluginInstance.load();
|
||||||
|
if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
|
||||||
|
} catch (IOException | ParseResourceException e) {
|
||||||
|
Logger.global.logError("Failed to load bluemap!", e);
|
||||||
|
pluginInstance.unload();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerStopping(FMLServerStoppingEvent event) {
|
||||||
|
pluginInstance.unload();
|
||||||
|
Logger.global.logInfo("BlueMap unloaded!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onTick(ServerTickEvent evt) {
|
||||||
|
updateSomePlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (RuntimeException 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 key = getFolderForWorld(world);
|
||||||
|
|
||||||
|
UUID uuid = worldUUIDs.get(key);
|
||||||
|
if (uuid == null) {
|
||||||
|
uuid = UUID.randomUUID();
|
||||||
|
worldUUIDs.put(key, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getFolderForWorld(ServerWorld world) throws IOException {
|
||||||
|
File worldFolder = world.getSaveHandler().getWorldDirectory();
|
||||||
|
|
||||||
|
int dimensionId = world.getDimension().getType().getId();
|
||||||
|
if (dimensionId != 0) {
|
||||||
|
worldFolder = new File(worldFolder, "DIM" + dimensionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return worldFolder.getCanonicalFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getConfigFolder() {
|
||||||
|
return new File("config/bluemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onPlayerJoin(PlayerLoggedInEvent evt) {
|
||||||
|
PlayerEntity playerInstance = evt.getPlayer();
|
||||||
|
if (!(playerInstance instanceof ServerPlayerEntity)) return;
|
||||||
|
|
||||||
|
ForgePlayer player = new ForgePlayer(this, (ServerPlayerEntity) playerInstance);
|
||||||
|
onlinePlayerMap.put(player.getUuid(), player);
|
||||||
|
onlinePlayerList.add(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onPlayerLeave(PlayerLoggedOutEvent evt) {
|
||||||
|
PlayerEntity player = evt.getPlayer();
|
||||||
|
if (!(player instanceof ServerPlayerEntity)) return;
|
||||||
|
|
||||||
|
UUID playerUUID = player.getUniqueID();
|
||||||
|
onlinePlayerMap.remove(playerUUID);
|
||||||
|
synchronized (onlinePlayerList) {
|
||||||
|
onlinePlayerList.removeIf(p -> p.getUuid().equals(playerUUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftServer getServer() {
|
||||||
|
return this.serverInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Player> getOnlinePlayers() {
|
||||||
|
return onlinePlayerMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Player> getPlayer(UUID uuid) {
|
||||||
|
return Optional.ofNullable(onlinePlayerMap.get(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only update some of the online players each tick to minimize performance impact on the server-thread.
|
||||||
|
* Only call this method on the server-thread.
|
||||||
|
*/
|
||||||
|
private void updateSomePlayers() {
|
||||||
|
int onlinePlayerCount = onlinePlayerList.size();
|
||||||
|
if (onlinePlayerCount == 0) return;
|
||||||
|
|
||||||
|
int playersToBeUpdated = onlinePlayerCount / 20; //with 20 tps, each player is updated once a second
|
||||||
|
if (playersToBeUpdated == 0) playersToBeUpdated = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < playersToBeUpdated; i++) {
|
||||||
|
playerUpdateIndex++;
|
||||||
|
if (playerUpdateIndex >= 20 && playerUpdateIndex >= onlinePlayerCount) playerUpdateIndex = 0;
|
||||||
|
|
||||||
|
if (playerUpdateIndex < onlinePlayerCount) {
|
||||||
|
onlinePlayerList.get(playerUpdateIndex).update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.forge;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3d;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Gamemode;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.text.Text;
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.potion.EffectInstance;
|
||||||
|
import net.minecraft.potion.Effects;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.GameType;
|
||||||
|
|
||||||
|
public class ForgePlayer implements Player {
|
||||||
|
|
||||||
|
private static final UUID UNKNOWN_WORLD_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
private static final Map<GameType, Gamemode> GAMEMODE_MAP = new EnumMap<>(GameType.class);
|
||||||
|
static {
|
||||||
|
GAMEMODE_MAP.put(GameType.ADVENTURE, Gamemode.ADVENTURE);
|
||||||
|
GAMEMODE_MAP.put(GameType.SURVIVAL, Gamemode.SURVIVAL);
|
||||||
|
GAMEMODE_MAP.put(GameType.CREATIVE, Gamemode.CREATIVE);
|
||||||
|
GAMEMODE_MAP.put(GameType.SPECTATOR, Gamemode.SPECTATOR);
|
||||||
|
GAMEMODE_MAP.put(GameType.NOT_SET, Gamemode.SURVIVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private Text name;
|
||||||
|
private UUID world;
|
||||||
|
private Vector3d position;
|
||||||
|
private boolean online;
|
||||||
|
private boolean sneaking;
|
||||||
|
private boolean invisible;
|
||||||
|
private Gamemode gamemode;
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private WeakReference<ServerPlayerEntity> delegate;
|
||||||
|
|
||||||
|
public ForgePlayer(ForgeMod mod, ServerPlayerEntity delegate) {
|
||||||
|
this.uuid = delegate.getUniqueID();
|
||||||
|
this.mod = mod;
|
||||||
|
this.delegate = new WeakReference<>(delegate);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUuid() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getWorld() {
|
||||||
|
return this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnline() {
|
||||||
|
return this.online;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSneaking() {
|
||||||
|
return this.sneaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible() {
|
||||||
|
return this.invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Gamemode getGamemode() {
|
||||||
|
return this.gamemode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only call on server thread!
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
ServerPlayerEntity player = delegate.get();
|
||||||
|
if (player == null) {
|
||||||
|
MinecraftServer server = mod.getServer();
|
||||||
|
if (server != null) {
|
||||||
|
player = server.getPlayerList().getPlayerByUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
this.online = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate = new WeakReference<>(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gamemode = GAMEMODE_MAP.get(player.interactionManager.getGameType());
|
||||||
|
|
||||||
|
EffectInstance invis = player.getActivePotionEffect(Effects.INVISIBILITY);
|
||||||
|
this.invisible = invis != null && invis.getDuration() > 0;
|
||||||
|
|
||||||
|
this.name = Text.of(player.getName().getString());
|
||||||
|
this.online = true;
|
||||||
|
|
||||||
|
Vec3d pos = player.getPositionVec();
|
||||||
|
this.position = new Vector3d(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.sneaking = player.isSneaking();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.world = mod.getUUIDForWorld(player.getServerWorld());
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.world = UNKNOWN_WORLD_UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.forge;
|
||||||
|
|
||||||
|
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,25 @@
|
|||||||
|
modLoader="javafml"
|
||||||
|
loaderVersion="[28,)"
|
||||||
|
issueTrackerURL="https://github.com/BlueMap-Minecraft/BlueMap/issues"
|
||||||
|
[[mods]]
|
||||||
|
modId="bluemap"
|
||||||
|
version="${version}"
|
||||||
|
displayName="BlueMap"
|
||||||
|
displayURL="https://github.com/BlueMap-Minecraft/BlueMap"
|
||||||
|
authors="Blue (TBlueF, Lukas Rieger)"
|
||||||
|
description='''
|
||||||
|
A 3d-map of your Minecraft worlds view-able in your browser using three.js (WebGL)
|
||||||
|
'''
|
||||||
|
|
||||||
|
[[dependencies.bluemap]]
|
||||||
|
modId="forge"
|
||||||
|
mandatory=true
|
||||||
|
versionRange="[28,)"
|
||||||
|
ordering="NONE"
|
||||||
|
side="SERVER"
|
||||||
|
[[dependencies.bluemap]]
|
||||||
|
modId="minecraft"
|
||||||
|
mandatory=true
|
||||||
|
versionRange="[1.14.4]"
|
||||||
|
ordering="NONE"
|
||||||
|
side="SERVER"
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,30 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Core-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
|
||||||
|
# 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":"bukkit","version":"%version%"}
|
||||||
|
# Default is true
|
||||||
|
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.
|
||||||
|
# Default is "bluemap"
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,27 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Plugin-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# If the server should send live-updates and player-positions.
|
||||||
|
# This only works if the integrated webserver is enabled.
|
||||||
|
# Default is true
|
||||||
|
liveUpdates: true
|
||||||
|
|
||||||
|
# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers.
|
||||||
|
# Default is true
|
||||||
|
skinDownload: true
|
||||||
|
|
||||||
|
# A list of gamemodes that will prevent a player from appearing on the map.
|
||||||
|
# Possible values are: survival, creative, spectator, adventure
|
||||||
|
hiddenGameModes: [
|
||||||
|
"spectator"
|
||||||
|
]
|
||||||
|
|
||||||
|
# If this is true, players that have an invisibility (potion-)effect will be hidden on the map.
|
||||||
|
# Default is true
|
||||||
|
hideInvisible: true
|
||||||
|
|
||||||
|
# If this is true, players that are sneaking will be hidden on the map.
|
||||||
|
# Default is false
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -0,0 +1,126 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Render-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
|
useCookies: true
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks.
|
||||||
|
# If this is set to true BlueMap will render Chunks even if there is no light-data!
|
||||||
|
# This can be usefull for example if some mod prevents light-data from being saved correctly.
|
||||||
|
# However, this also has a few drawbacks:
|
||||||
|
# - For those chunks, every block will always be fully lit
|
||||||
|
# - Night-mode might not work correctly
|
||||||
|
# - Caves will always be rendered (ignoring the 'renderCaves' setting)
|
||||||
|
# Default is false
|
||||||
|
ignoreMissingLightData: false
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -0,0 +1,29 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Webserver-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 webroot that the server will host to the web.
|
||||||
|
# Usually this should be set to the same directory like in the Core-Config!
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# The IP-Adress that the webserver binds to.
|
||||||
|
# Use "0.0.0.0" to bind to all available local adresses.
|
||||||
|
# If you only want to access it locally use "localhost".
|
||||||
|
# Default is "0.0.0.0"
|
||||||
|
#ip: "localhost"
|
||||||
|
#ip: "123.45.6.78"
|
||||||
|
|
||||||
|
# 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
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"description": "BlueMap - A 3d-map of your Minecraft worlds view-able in your browser using three.js (WebGL)",
|
||||||
|
"pack_format": 5
|
||||||
|
}
|
||||||
|
}
|
67
implementations/forge-1.15.2/build.gradle
Normal file
67
implementations/forge-1.15.2/build.gradle
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven { url = 'https://files.minecraftforge.net/maven/' }
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'net.minecraftforge.gradle'
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
mappings channel: 'snapshot', version: '20190719-1.14.3'
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compile.extendsFrom include
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
minecraft 'net.minecraftforge:forge:1.15.2-31.2.0'
|
||||||
|
|
||||||
|
include (project(':BlueMapCommon')) {
|
||||||
|
//exclude dependencies provided by forge
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.dependsOn shadowJar {
|
||||||
|
destinationDir = file '../../build/release'
|
||||||
|
archiveFileName = "BlueMap-${version}-forge-1.15.2.jar"
|
||||||
|
|
||||||
|
configurations = [project.configurations.include]
|
||||||
|
|
||||||
|
//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'
|
||||||
|
relocate 'com.github.benmanes.caffeine', 'de.bluecolored.shadow.benmanes.caffeine'
|
||||||
|
relocate 'com.google.errorprone', 'de.bluecolored.shadow.google.errorprone'
|
||||||
|
relocate 'org.checkerframework', 'de.bluecolored.shadow.checkerframework'
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
|
include 'mcmod.info','META-INF/mods.toml'
|
||||||
|
|
||||||
|
expand (
|
||||||
|
version: project.version
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
reobf {
|
||||||
|
shadowJar {
|
||||||
|
mappings = createMcpToSrg.output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.forge;
|
||||||
|
|
||||||
|
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.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
|
||||||
|
public class ForgeCommandSource implements CommandSource {
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private Plugin plugin;
|
||||||
|
private net.minecraft.command.CommandSource delegate;
|
||||||
|
|
||||||
|
public ForgeCommandSource(ForgeMod mod, Plugin plugin, net.minecraft.command.CommandSource delegate) {
|
||||||
|
this.mod = mod;
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Text text) {
|
||||||
|
delegate.sendFeedback(ITextComponent.Serializer.fromJson(text.toJSONString()), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(String permission) {
|
||||||
|
return delegate.hasPermissionLevel(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Vector3d> getPosition() {
|
||||||
|
Vec3d pos = delegate.getPos();
|
||||||
|
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,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.bluecolored.bluemap.forge;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
|
||||||
|
import net.minecraftforge.event.world.BlockEvent;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
|
||||||
|
public class ForgeEventForwarder {
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private Collection<ServerEventListener> eventListeners;
|
||||||
|
|
||||||
|
public ForgeEventForwarder(ForgeMod mod) {
|
||||||
|
this.mod = mod;
|
||||||
|
this.eventListeners = new ArrayList<>(1);
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addEventListener(ServerEventListener listener) {
|
||||||
|
this.eventListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeAllListeners() {
|
||||||
|
this.eventListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onBlockBreak(BlockEvent.BreakEvent evt) {
|
||||||
|
onBlockChange(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onBlockPlace(BlockEvent.EntityPlaceEvent evt) {
|
||||||
|
onBlockChange(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void onBlockChange(BlockEvent evt) {
|
||||||
|
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID world = mod.getUUIDForWorld((ServerWorld) evt.getWorld());
|
||||||
|
Vector3i position = new Vector3i(
|
||||||
|
evt.getPos().getX(),
|
||||||
|
evt.getPos().getY(),
|
||||||
|
evt.getPos().getZ()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onBlockChange(world, position);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onWorldSave(WorldEvent.Save evt) {
|
||||||
|
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID world = mod.getUUIDForWorld((ServerWorld) evt.getWorld());
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(world);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onPlayerJoin(PlayerLoggedInEvent evt) {
|
||||||
|
UUID uuid = evt.getPlayer().getUniqueID();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerJoin(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public synchronized void onPlayerLeave(PlayerLoggedOutEvent evt) {
|
||||||
|
UUID uuid = evt.getPlayer().getUniqueID();
|
||||||
|
for (ServerEventListener listener : eventListeners) listener.onPlayerLeave(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* 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.forge;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.commands.Commands;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||||
|
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.TickEvent.ServerTickEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
|
||||||
|
|
||||||
|
@Mod(Plugin.PLUGIN_ID)
|
||||||
|
public class ForgeMod implements ServerInterface {
|
||||||
|
|
||||||
|
private Plugin pluginInstance = null;
|
||||||
|
private MinecraftServer serverInstance = null;
|
||||||
|
|
||||||
|
private Map<File, UUID> worldUUIDs;
|
||||||
|
private ForgeEventForwarder eventForwarder;
|
||||||
|
|
||||||
|
private LoadingCache<ServerWorld, UUID> worldUuidCache;
|
||||||
|
|
||||||
|
private int playerUpdateIndex = 0;
|
||||||
|
private Map<UUID, Player> onlinePlayerMap;
|
||||||
|
private List<ForgePlayer> onlinePlayerList;
|
||||||
|
|
||||||
|
public ForgeMod() {
|
||||||
|
Logger.global = new Log4jLogger(LogManager.getLogger(Plugin.PLUGIN_NAME));
|
||||||
|
|
||||||
|
this.onlinePlayerMap = new ConcurrentHashMap<>();
|
||||||
|
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
this.pluginInstance = new Plugin(MinecraftVersion.MC_1_15, "forge", this);
|
||||||
|
|
||||||
|
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||||
|
this.eventForwarder = new ForgeEventForwarder(this);
|
||||||
|
this.worldUuidCache = Caffeine.newBuilder()
|
||||||
|
.weakKeys()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build(this::loadUUIDForWorld);
|
||||||
|
|
||||||
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerStarting(FMLServerStartingEvent event) {
|
||||||
|
this.worldUUIDs.clear();
|
||||||
|
|
||||||
|
//save worlds to generate level.dat files
|
||||||
|
event.getServer().save(false, true, true);
|
||||||
|
|
||||||
|
//register commands
|
||||||
|
new Commands<>(pluginInstance, event.getServer().getCommandManager().getDispatcher(), forgeSource -> new ForgeCommandSource(this, pluginInstance, forgeSource));
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
Logger.global.logInfo("Loading...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
pluginInstance.load();
|
||||||
|
if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
|
||||||
|
} catch (IOException | ParseResourceException e) {
|
||||||
|
Logger.global.logError("Failed to load bluemap!", e);
|
||||||
|
pluginInstance.unload();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerStopping(FMLServerStoppingEvent event) {
|
||||||
|
pluginInstance.unload();
|
||||||
|
Logger.global.logInfo("BlueMap unloaded!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onTick(ServerTickEvent evt) {
|
||||||
|
updateSomePlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (RuntimeException 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 key = getFolderForWorld(world);
|
||||||
|
|
||||||
|
UUID uuid = worldUUIDs.get(key);
|
||||||
|
if (uuid == null) {
|
||||||
|
uuid = UUID.randomUUID();
|
||||||
|
worldUUIDs.put(key, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getFolderForWorld(ServerWorld world) throws IOException {
|
||||||
|
File worldFolder = world.getSaveHandler().getWorldDirectory();
|
||||||
|
|
||||||
|
int dimensionId = world.getDimension().getType().getId();
|
||||||
|
if (dimensionId != 0) {
|
||||||
|
worldFolder = new File(worldFolder, "DIM" + dimensionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return worldFolder.getCanonicalFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getConfigFolder() {
|
||||||
|
return new File("config/bluemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onPlayerJoin(PlayerLoggedInEvent evt) {
|
||||||
|
PlayerEntity playerInstance = evt.getPlayer();
|
||||||
|
if (!(playerInstance instanceof ServerPlayerEntity)) return;
|
||||||
|
|
||||||
|
ForgePlayer player = new ForgePlayer(this, (ServerPlayerEntity) playerInstance);
|
||||||
|
onlinePlayerMap.put(player.getUuid(), player);
|
||||||
|
onlinePlayerList.add(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onPlayerLeave(PlayerLoggedOutEvent evt) {
|
||||||
|
PlayerEntity player = evt.getPlayer();
|
||||||
|
if (!(player instanceof ServerPlayerEntity)) return;
|
||||||
|
|
||||||
|
UUID playerUUID = player.getUniqueID();
|
||||||
|
onlinePlayerMap.remove(playerUUID);
|
||||||
|
synchronized (onlinePlayerList) {
|
||||||
|
onlinePlayerList.removeIf(p -> p.getUuid().equals(playerUUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftServer getServer() {
|
||||||
|
return this.serverInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Player> getOnlinePlayers() {
|
||||||
|
return onlinePlayerMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Player> getPlayer(UUID uuid) {
|
||||||
|
return Optional.ofNullable(onlinePlayerMap.get(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only update some of the online players each tick to minimize performance impact on the server-thread.
|
||||||
|
* Only call this method on the server-thread.
|
||||||
|
*/
|
||||||
|
private void updateSomePlayers() {
|
||||||
|
int onlinePlayerCount = onlinePlayerList.size();
|
||||||
|
if (onlinePlayerCount == 0) return;
|
||||||
|
|
||||||
|
int playersToBeUpdated = onlinePlayerCount / 20; //with 20 tps, each player is updated once a second
|
||||||
|
if (playersToBeUpdated == 0) playersToBeUpdated = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < playersToBeUpdated; i++) {
|
||||||
|
playerUpdateIndex++;
|
||||||
|
if (playerUpdateIndex >= 20 && playerUpdateIndex >= onlinePlayerCount) playerUpdateIndex = 0;
|
||||||
|
|
||||||
|
if (playerUpdateIndex < onlinePlayerCount) {
|
||||||
|
onlinePlayerList.get(playerUpdateIndex).update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.forge;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.flowpowered.math.vector.Vector3d;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Gamemode;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.serverinterface.Player;
|
||||||
|
import de.bluecolored.bluemap.common.plugin.text.Text;
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.potion.EffectInstance;
|
||||||
|
import net.minecraft.potion.Effects;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.GameType;
|
||||||
|
|
||||||
|
public class ForgePlayer implements Player {
|
||||||
|
|
||||||
|
private static final UUID UNKNOWN_WORLD_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
private static final Map<GameType, Gamemode> GAMEMODE_MAP = new EnumMap<>(GameType.class);
|
||||||
|
static {
|
||||||
|
GAMEMODE_MAP.put(GameType.ADVENTURE, Gamemode.ADVENTURE);
|
||||||
|
GAMEMODE_MAP.put(GameType.SURVIVAL, Gamemode.SURVIVAL);
|
||||||
|
GAMEMODE_MAP.put(GameType.CREATIVE, Gamemode.CREATIVE);
|
||||||
|
GAMEMODE_MAP.put(GameType.SPECTATOR, Gamemode.SPECTATOR);
|
||||||
|
GAMEMODE_MAP.put(GameType.NOT_SET, Gamemode.SURVIVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private Text name;
|
||||||
|
private UUID world;
|
||||||
|
private Vector3d position;
|
||||||
|
private boolean online;
|
||||||
|
private boolean sneaking;
|
||||||
|
private boolean invisible;
|
||||||
|
private Gamemode gamemode;
|
||||||
|
|
||||||
|
private ForgeMod mod;
|
||||||
|
private WeakReference<ServerPlayerEntity> delegate;
|
||||||
|
|
||||||
|
public ForgePlayer(ForgeMod mod, ServerPlayerEntity delegate) {
|
||||||
|
this.uuid = delegate.getUniqueID();
|
||||||
|
this.mod = mod;
|
||||||
|
this.delegate = new WeakReference<>(delegate);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUuid() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getWorld() {
|
||||||
|
return this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3d getPosition() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnline() {
|
||||||
|
return this.online;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSneaking() {
|
||||||
|
return this.sneaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvisible() {
|
||||||
|
return this.invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Gamemode getGamemode() {
|
||||||
|
return this.gamemode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only call on server thread!
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
ServerPlayerEntity player = delegate.get();
|
||||||
|
if (player == null) {
|
||||||
|
MinecraftServer server = mod.getServer();
|
||||||
|
if (server != null) {
|
||||||
|
player = server.getPlayerList().getPlayerByUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
this.online = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate = new WeakReference<>(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gamemode = GAMEMODE_MAP.get(player.interactionManager.getGameType());
|
||||||
|
|
||||||
|
EffectInstance invis = player.getActivePotionEffect(Effects.INVISIBILITY);
|
||||||
|
this.invisible = invis != null && invis.getDuration() > 0;
|
||||||
|
|
||||||
|
this.name = Text.of(player.getName().getString());
|
||||||
|
this.online = true;
|
||||||
|
|
||||||
|
Vec3d pos = player.getPositionVec();
|
||||||
|
this.position = new Vector3d(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.sneaking = player.isCrouching();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.world = mod.getUUIDForWorld(player.getServerWorld());
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.world = UNKNOWN_WORLD_UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.forge;
|
||||||
|
|
||||||
|
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,25 @@
|
|||||||
|
modLoader="javafml"
|
||||||
|
loaderVersion="[28,)"
|
||||||
|
issueTrackerURL="https://github.com/BlueMap-Minecraft/BlueMap/issues"
|
||||||
|
[[mods]]
|
||||||
|
modId="bluemap"
|
||||||
|
version="${version}"
|
||||||
|
displayName="BlueMap"
|
||||||
|
displayURL="https://github.com/BlueMap-Minecraft/BlueMap"
|
||||||
|
authors="Blue (TBlueF, Lukas Rieger)"
|
||||||
|
description='''
|
||||||
|
A 3d-map of your Minecraft worlds view-able in your browser using three.js (WebGL)
|
||||||
|
'''
|
||||||
|
|
||||||
|
[[dependencies.bluemap]]
|
||||||
|
modId="forge"
|
||||||
|
mandatory=true
|
||||||
|
versionRange="[28,)"
|
||||||
|
ordering="NONE"
|
||||||
|
side="SERVER"
|
||||||
|
[[dependencies.bluemap]]
|
||||||
|
modId="minecraft"
|
||||||
|
mandatory=true
|
||||||
|
versionRange="[1.15.2]"
|
||||||
|
ordering="NONE"
|
||||||
|
side="SERVER"
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,30 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Core-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 a minecraft-client file (depending on the minecraft-version) from mojangs servers (https://launcher.mojang.com/) for you.
|
||||||
|
# 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":"bukkit","version":"%version%"}
|
||||||
|
# Default is true
|
||||||
|
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.
|
||||||
|
# Default is "bluemap"
|
||||||
|
data: "bluemap"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,27 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Plugin-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# If the server should send live-updates and player-positions.
|
||||||
|
# This only works if the integrated webserver is enabled.
|
||||||
|
# Default is true
|
||||||
|
liveUpdates: true
|
||||||
|
|
||||||
|
# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers.
|
||||||
|
# Default is true
|
||||||
|
skinDownload: true
|
||||||
|
|
||||||
|
# A list of gamemodes that will prevent a player from appearing on the map.
|
||||||
|
# Possible values are: survival, creative, spectator, adventure
|
||||||
|
hiddenGameModes: [
|
||||||
|
"spectator"
|
||||||
|
]
|
||||||
|
|
||||||
|
# If this is true, players that have an invisibility (potion-)effect will be hidden on the map.
|
||||||
|
# Default is true
|
||||||
|
hideInvisible: true
|
||||||
|
|
||||||
|
# If this is true, players that are sneaking will be hidden on the map.
|
||||||
|
# Default is false
|
||||||
|
hideSneaking: false
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -0,0 +1,126 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Render-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
|
useCookies: true
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks.
|
||||||
|
# If this is set to true BlueMap will render Chunks even if there is no light-data!
|
||||||
|
# This can be usefull for example if some mod prevents light-data from being saved correctly.
|
||||||
|
# However, this also has a few drawbacks:
|
||||||
|
# - For those chunks, every block will always be fully lit
|
||||||
|
# - Night-mode might not work correctly
|
||||||
|
# - Caves will always be rendered (ignoring the 'renderCaves' setting)
|
||||||
|
# Default is false
|
||||||
|
ignoreMissingLightData: false
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -0,0 +1,29 @@
|
|||||||
|
## ##
|
||||||
|
## BlueMap ##
|
||||||
|
## Webserver-Config ##
|
||||||
|
## ##
|
||||||
|
|
||||||
|
# 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 webroot that the server will host to the web.
|
||||||
|
# Usually this should be set to the same directory like in the Core-Config!
|
||||||
|
# Default is "bluemap/web"
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
|
# The IP-Adress that the webserver binds to.
|
||||||
|
# Use "0.0.0.0" to bind to all available local adresses.
|
||||||
|
# If you only want to access it locally use "localhost".
|
||||||
|
# Default is "0.0.0.0"
|
||||||
|
#ip: "localhost"
|
||||||
|
#ip: "123.45.6.78"
|
||||||
|
|
||||||
|
# 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
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"description": "BlueMap - A 3d-map of your Minecraft worlds view-able in your browser using three.js (WebGL)",
|
||||||
|
"pack_format": 5
|
||||||
|
}
|
||||||
|
}
|
@ -102,6 +102,9 @@ public void onServerStarting(FMLServerStartingEvent event) {
|
|||||||
//register commands
|
//register commands
|
||||||
new Commands<>(pluginInstance, event.getServer().getCommandManager().getDispatcher(), forgeSource -> new ForgeCommandSource(this, pluginInstance, forgeSource));
|
new Commands<>(pluginInstance, event.getServer().getCommandManager().getDispatcher(), forgeSource -> new ForgeCommandSource(this, pluginInstance, forgeSource));
|
||||||
|
|
||||||
|
//save worlds to generate level.dat files
|
||||||
|
event.getServer().save(false, true, true);
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
Logger.global.logInfo("Loading...");
|
Logger.global.logInfo("Loading...");
|
||||||
|
|
||||||
|
@ -19,8 +19,14 @@ include ':BlueMapCommon'
|
|||||||
include ':cli'
|
include ':cli'
|
||||||
include ':sponge-7.2.0'
|
include ':sponge-7.2.0'
|
||||||
include ':spigot'
|
include ':spigot'
|
||||||
|
|
||||||
include ':forge-1.16.2'
|
include ':forge-1.16.2'
|
||||||
|
include ':forge-1.15.2'
|
||||||
|
include ':forge-1.14.4'
|
||||||
|
|
||||||
include ':fabric-1.16.2'
|
include ':fabric-1.16.2'
|
||||||
|
include ':fabric-1.16.1'
|
||||||
|
include ':fabric-1.15.2'
|
||||||
|
|
||||||
|
|
||||||
project(':BlueMapAPI').projectDir = "$rootDir/BlueMapAPI" as File
|
project(':BlueMapAPI').projectDir = "$rootDir/BlueMapAPI" as File
|
||||||
@ -30,5 +36,11 @@ project(':BlueMapCommon').projectDir = "$rootDir/BlueMapCommon" as File
|
|||||||
project(':cli').projectDir = "$rootDir/implementations/cli" as File
|
project(':cli').projectDir = "$rootDir/implementations/cli" as File
|
||||||
project(':sponge-7.2.0').projectDir = "$rootDir/implementations/sponge-7.2.0" as File
|
project(':sponge-7.2.0').projectDir = "$rootDir/implementations/sponge-7.2.0" as File
|
||||||
project(':spigot').projectDir = "$rootDir/implementations/spigot" as File
|
project(':spigot').projectDir = "$rootDir/implementations/spigot" as File
|
||||||
|
|
||||||
project(':forge-1.16.2').projectDir = "$rootDir/implementations/forge-1.16.2" as File
|
project(':forge-1.16.2').projectDir = "$rootDir/implementations/forge-1.16.2" as File
|
||||||
|
project(':forge-1.15.2').projectDir = "$rootDir/implementations/forge-1.15.2" as File
|
||||||
|
project(':forge-1.14.4').projectDir = "$rootDir/implementations/forge-1.14.4" as File
|
||||||
|
|
||||||
project(':fabric-1.16.2').projectDir = "$rootDir/implementations/fabric-1.16.2" as File
|
project(':fabric-1.16.2').projectDir = "$rootDir/implementations/fabric-1.16.2" as File
|
||||||
|
project(':fabric-1.16.1').projectDir = "$rootDir/implementations/fabric-1.16.1" as File
|
||||||
|
project(':fabric-1.15.2').projectDir = "$rootDir/implementations/fabric-1.15.2" as File
|
||||||
|
Loading…
Reference in New Issue
Block a user