feat: implemented PreloadedWorldModule

This commit is contained in:
Andrey Terentev 2024-11-26 20:37:50 +07:00
parent 32b51e8523
commit 516129e898

View File

@ -0,0 +1,63 @@
package ru.dragonestia.msb3.api.module;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.GameMode;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.event.player.PlayerSpawnEvent;
import ru.dragonestia.msb3.api.world.World;
import ru.dragonestia.msb3.api.world.WorldFactory;
import java.io.File;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
public class PreloadedWorldModule {
private static boolean used = false;
private PreloadedWorldModule() {}
public static void init(File worldDir, GameMode gameMode, Pos spawnPos) {
init(worldDir, gameMode, () -> spawnPos);
}
public static synchronized void init(File worldDir, GameMode gameMode, Supplier<Pos> spawnPosSupplier) {
if (used) return;
used = true;
var loadingWorld = MinecraftServer.getInstanceManager().createInstanceContainer();
loadingWorld.eventNode().addListener(PlayerMoveEvent.class, event -> event.setCancelled(true));
var factory = WorldFactory.anvil(worldDir);
var worlds = new ConcurrentHashMap<UUID, World>();
MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> {
var player = event.getPlayer();
player.setRespawnPoint(new Pos(0, 60, 0));
player.setGameMode(gameMode);
event.setSpawningInstance(loadingWorld);
}).addListener(PlayerSpawnEvent.class, event -> {
if (!event.isFirstSpawn()) return;
var player = event.getPlayer();
factory.createWorld().thenAccept(world -> {
worlds.put(player.getUuid(), world);
player.setInstance(world.getInstance(), spawnPosSupplier.get());
});
}).addListener(PlayerDisconnectEvent.class, event -> {
var player = event.getPlayer();
var world = worlds.remove(player.getUuid());
if (world == null) return;
if (world.getInstance().getEntityTracker().entities().stream().filter(entity -> entity != player).count() == 0) {
world.unload();
}
});
}
}