mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 18:45:21 +01:00
Add forge live-implementation, improve fabric implementation and fix possible CME
This commit is contained in:
parent
59c3f8adc5
commit
e72fb4f21a
@ -72,7 +72,7 @@ public synchronized void removeAllListeners() {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public synchronized void onWorldSaveToDisk(WorldSaveEvent evt) {
|
||||
listeners.forEach(l -> l.onWorldSaveToDisk(evt.getWorld().getUID()));
|
||||
for (ServerEventListener listener : listeners) listener.onWorldSaveToDisk(evt.getWorld().getUID());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
@ -123,7 +123,7 @@ public void onBlockChange(BlockFertilizeEvent evt) {
|
||||
private synchronized void onBlockChange(Location loc) {
|
||||
UUID world = loc.getWorld().getUID();
|
||||
Vector3i pos = new Vector3i(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
listeners.forEach(l -> l.onBlockChange(world, pos));
|
||||
for (ServerEventListener listener : listeners) listener.onBlockChange(world, pos);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
@ -131,23 +131,23 @@ public synchronized void onChunkFinishedGeneration(ChunkPopulateEvent evt) {
|
||||
Chunk chunk = evt.getChunk();
|
||||
UUID world = chunk.getWorld().getUID();
|
||||
Vector2i chunkPos = new Vector2i(chunk.getX(), chunk.getZ());
|
||||
listeners.forEach(l -> l.onChunkFinishedGeneration(world, chunkPos));
|
||||
for (ServerEventListener listener : listeners) listener.onChunkFinishedGeneration(world, chunkPos);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerJoin(PlayerJoinEvent evt) {
|
||||
listeners.forEach(l -> l.onPlayerJoin(evt.getPlayer().getUniqueId()));
|
||||
public synchronized void onPlayerJoin(PlayerJoinEvent evt) {
|
||||
for (ServerEventListener listener : listeners) listener.onPlayerJoin(evt.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerLeave(PlayerQuitEvent evt) {
|
||||
listeners.forEach(l -> l.onPlayerJoin(evt.getPlayer().getUniqueId()));
|
||||
public synchronized void onPlayerLeave(PlayerQuitEvent evt) {
|
||||
for (ServerEventListener listener : listeners) listener.onPlayerJoin(evt.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerChat(AsyncPlayerChatEvent evt) {
|
||||
public synchronized void onPlayerChat(AsyncPlayerChatEvent evt) {
|
||||
String message = String.format(evt.getFormat(), evt.getPlayer().getDisplayName(), evt.getMessage());
|
||||
listeners.forEach(l -> l.onChatMessage(Text.of(message)));
|
||||
for (ServerEventListener listener : listeners) listener.onChatMessage(Text.of(message));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -69,11 +69,11 @@ public FabricEventForwarder(FabricMod mod) {
|
||||
PlayerLeaveCallback.EVENT.register(this::onPlayerLeave);
|
||||
}
|
||||
|
||||
public void addEventListener(ServerEventListener listener) {
|
||||
public synchronized void addEventListener(ServerEventListener listener) {
|
||||
this.eventListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeAllListeners() {
|
||||
public synchronized void removeAllListeners() {
|
||||
this.eventListeners.clear();
|
||||
}
|
||||
|
||||
@ -94,45 +94,47 @@ public ActionResult onBlockAttack(PlayerEntity player, World world, Hand hand, B
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
public void onBlockChange(ServerWorld world, BlockPos blockPos) {
|
||||
public synchronized void onBlockChange(ServerWorld world, BlockPos blockPos) {
|
||||
Vector3i position = new Vector3i(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
|
||||
try {
|
||||
UUID uuid = mod.getUUIDForWorld(world);
|
||||
eventListeners.forEach(e -> e.onBlockChange(uuid, position));
|
||||
for (ServerEventListener listener : eventListeners) listener.onBlockChange(uuid, position);
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to get UUID for world: " + world, e);
|
||||
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onWorldSave(ServerWorld world) {
|
||||
public synchronized void onWorldSave(ServerWorld world) {
|
||||
try {
|
||||
UUID uuid = mod.getUUIDForWorld(world);
|
||||
eventListeners.forEach(e -> e.onWorldSaveToDisk(uuid));
|
||||
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(uuid);
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to get UUID for world: " + world, e);
|
||||
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onChunkFinalize(ServerWorld world, Vector2i chunkPos) {
|
||||
public synchronized void onChunkFinalize(ServerWorld world, Vector2i chunkPos) {
|
||||
try {
|
||||
UUID uuid = mod.getUUIDForWorld(world);
|
||||
eventListeners.forEach(e -> e.onChunkFinishedGeneration(uuid, chunkPos));
|
||||
for (ServerEventListener listener : eventListeners) listener.onChunkFinishedGeneration(uuid, chunkPos);
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to get UUID for world: " + world, e);
|
||||
Logger.global.noFloodError("Failed to get the UUID for a world!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player) {
|
||||
public synchronized void onPlayerJoin(MinecraftServer server, ServerPlayerEntity player) {
|
||||
if (this.mod.getServer() != server) return;
|
||||
|
||||
this.eventListeners.forEach(l -> l.onPlayerJoin(player.getUuid()));
|
||||
UUID uuid = player.getUuid();
|
||||
for (ServerEventListener listener : eventListeners) listener.onPlayerJoin(uuid);
|
||||
}
|
||||
|
||||
public void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||
public synchronized void onPlayerLeave(MinecraftServer server, ServerPlayerEntity player) {
|
||||
if (this.mod.getServer() != server) return;
|
||||
|
||||
this.eventListeners.forEach(l -> l.onPlayerLeave(player.getUuid()));
|
||||
|
||||
UUID uuid = player.getUuid();
|
||||
for (ServerEventListener listener : eventListeners) listener.onPlayerLeave(uuid);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class FabricMod implements ModInitializer, ServerInterface {
|
||||
private Plugin pluginInstance = null;
|
||||
private MinecraftServer serverInstance = null;
|
||||
|
||||
private Map<File, UUID> worldUuids;
|
||||
private Map<File, UUID> worldUUIDs;
|
||||
private FabricEventForwarder eventForwarder;
|
||||
|
||||
private LoadingCache<ServerWorld, UUID> worldUuidCache;
|
||||
@ -82,7 +82,7 @@ public FabricMod() {
|
||||
|
||||
pluginInstance = new Plugin("fabric", this);
|
||||
|
||||
this.worldUuids = new ConcurrentHashMap<>();
|
||||
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||
this.eventForwarder = new FabricEventForwarder(this);
|
||||
this.worldUuidCache = CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
@ -111,7 +111,7 @@ public void onInitialize() {
|
||||
|
||||
try {
|
||||
pluginInstance.load();
|
||||
Logger.global.logInfo("BlueMap loaded!");
|
||||
if (pluginInstance.isLoaded()) Logger.global.logInfo("BlueMap loaded!");
|
||||
} catch (IOException | ParseResourceException e) {
|
||||
Logger.global.logError("Failed to load bluemap!", e);
|
||||
}
|
||||
@ -145,10 +145,10 @@ public void unregisterAllListeners() {
|
||||
public UUID getUUIDForWorld(File worldFolder) throws IOException {
|
||||
worldFolder = worldFolder.getCanonicalFile();
|
||||
|
||||
UUID uuid = worldUuids.get(worldFolder);
|
||||
UUID uuid = worldUUIDs.get(worldFolder);
|
||||
if (uuid == null) {
|
||||
uuid = UUID.randomUUID();
|
||||
worldUuids.put(worldFolder, uuid);
|
||||
worldUUIDs.put(worldFolder, uuid);
|
||||
}
|
||||
|
||||
return uuid;
|
||||
|
@ -52,6 +52,7 @@ public class FabricPlayer implements Player {
|
||||
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;
|
||||
@ -115,7 +116,7 @@ public Gamemode getGamemode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* API access, only call on server thread!
|
||||
* Only call on server thread!
|
||||
*/
|
||||
public void update() {
|
||||
ServerPlayerEntity player = delegate.get();
|
||||
@ -139,7 +140,7 @@ public void update() {
|
||||
this.invisible = invis != null && invis.getDuration() > 0;
|
||||
|
||||
this.name = Text.of(player.getName().getString());
|
||||
this.online = !player.removed;
|
||||
this.online = true;
|
||||
|
||||
Vec3d pos = player.getPos();
|
||||
this.position = new Vector3d(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -29,15 +29,15 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
@ -48,11 +48,15 @@
|
||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import net.minecraft.command.CommandSource;
|
||||
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.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
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;
|
||||
@ -60,20 +64,29 @@
|
||||
|
||||
@Mod(Plugin.PLUGIN_ID)
|
||||
public class ForgeMod implements ServerInterface {
|
||||
|
||||
private Plugin pluginInstance = null;
|
||||
private MinecraftServer serverInstance = null;
|
||||
|
||||
private Plugin bluemap;
|
||||
private Commands<CommandSource> commands;
|
||||
private Map<String, UUID> worldUUIDs;
|
||||
private Collection<ServerEventListener> eventListeners;
|
||||
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.bluemap = new Plugin("forge", this);
|
||||
this.worldUUIDs = new HashMap<>();
|
||||
this.eventListeners = new ArrayList<>(1);
|
||||
this.onlinePlayerMap = new ConcurrentHashMap<>();
|
||||
this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
this.pluginInstance = new Plugin("forge", this);
|
||||
|
||||
this.worldUUIDs = new ConcurrentHashMap<>();
|
||||
this.eventForwarder = new ForgeEventForwarder(this);
|
||||
this.worldUuidCache = CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.maximumSize(1000)
|
||||
@ -83,113 +96,61 @@ public UUID load(ServerWorld key) throws Exception {
|
||||
return loadUUIDForWorld(key);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(FMLServerStartingEvent event) {
|
||||
this.worldUUIDs.clear();
|
||||
|
||||
for (ServerWorld world : event.getServer().getWorlds()) {
|
||||
try {
|
||||
registerWorld(world);
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to register world: " + world.getProviderName(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
world.save(null, false, false);
|
||||
} catch (Throwable t) {
|
||||
Logger.global.logError("Failed to save world: " + world.getProviderName(), t);
|
||||
}
|
||||
}
|
||||
|
||||
//register commands
|
||||
this.commands = new Commands<>(bluemap, event.getCommandDispatcher(), forgeSource -> new ForgeCommandSource(this, bluemap, forgeSource));
|
||||
new Commands<>(pluginInstance, event.getCommandDispatcher(), forgeSource -> new ForgeCommandSource(this, pluginInstance, forgeSource));
|
||||
|
||||
new Thread(() -> {
|
||||
Logger.global.logInfo("Loading...");
|
||||
|
||||
try {
|
||||
Logger.global.logInfo("Loading...");
|
||||
bluemap.load();
|
||||
if (bluemap.isLoaded()) Logger.global.logInfo("Loaded!");
|
||||
} catch (Throwable t) {
|
||||
Logger.global.logError("Failed to load!", t);
|
||||
pluginInstance.load();
|
||||
if (pluginInstance.isLoaded()) Logger.global.logInfo("Loaded!");
|
||||
} catch (IOException | ParseResourceException e) {
|
||||
Logger.global.logError("Failed to load bluemap!", e);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void registerWorld(ServerWorld world) throws IOException {
|
||||
getUUIDForWorld(world);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStopping(FMLServerStoppingEvent event) {
|
||||
Logger.global.logInfo("Stopping...");
|
||||
bluemap.unload();
|
||||
Logger.global.logInfo("Saved and stopped!");
|
||||
pluginInstance.unload();
|
||||
Logger.global.logInfo("BlueMap unloaded!");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onTick(ServerTickEvent evt) {
|
||||
updateSomePlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListener(ServerEventListener listener) {
|
||||
eventListeners.add(listener);
|
||||
eventForwarder.addEventListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterAllListeners() {
|
||||
eventListeners.clear();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onBlockBreak(BlockEvent.BreakEvent evt) {
|
||||
onBlockChange(evt);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onBlockPlace(BlockEvent.EntityPlaceEvent evt) {
|
||||
onBlockChange(evt);
|
||||
}
|
||||
|
||||
private void onBlockChange(BlockEvent evt) {
|
||||
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||
|
||||
try {
|
||||
UUID world = 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 ignore) {}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldSave(WorldEvent.Save evt) {
|
||||
if (!(evt.getWorld() instanceof ServerWorld)) return;
|
||||
|
||||
try {
|
||||
UUID world = getUUIDForWorld((ServerWorld) evt.getWorld());
|
||||
|
||||
for (ServerEventListener listener : eventListeners) listener.onWorldSaveToDisk(world);
|
||||
|
||||
} catch (IOException ignore) {}
|
||||
eventForwarder.removeAllListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUIDForWorld(File worldFolder) throws IOException {
|
||||
synchronized (worldUUIDs) {
|
||||
String key = worldFolder.getCanonicalPath();
|
||||
|
||||
UUID uuid = worldUUIDs.get(key);
|
||||
if (uuid == null) {
|
||||
throw new IOException("There is no world with this folder loaded: " + worldFolder.getPath());
|
||||
}
|
||||
|
||||
return uuid;
|
||||
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 {
|
||||
@ -203,17 +164,15 @@ public UUID getUUIDForWorld(ServerWorld world) throws IOException {
|
||||
}
|
||||
|
||||
private UUID loadUUIDForWorld(ServerWorld world) throws IOException {
|
||||
synchronized (worldUUIDs) {
|
||||
String key = getFolderForWorld(world).getPath();
|
||||
|
||||
UUID uuid = worldUUIDs.get(key);
|
||||
if (uuid == null) {
|
||||
uuid = UUID.randomUUID();
|
||||
worldUUIDs.put(key, uuid);
|
||||
}
|
||||
|
||||
return uuid;
|
||||
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 {
|
||||
@ -231,21 +190,60 @@ private File getFolderForWorld(ServerWorld world) throws IOException {
|
||||
public File getConfigFolder() {
|
||||
return new File("config/bluemap");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 Commands<CommandSource> getCommands() {
|
||||
return commands;
|
||||
public MinecraftServer getServer() {
|
||||
return this.serverInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Player> getOnlinePlayers() {
|
||||
// TODO Implement
|
||||
return Collections.emptyList();
|
||||
return onlinePlayerMap.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer(UUID uuid) {
|
||||
// TODO Implement
|
||||
return Optional.empty();
|
||||
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(i).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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user