package me.km.dimensions; import java.util.Arrays; import java.util.Random; import java.util.TreeSet; import me.km.KajetansMod; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.DimensionType; import net.minecraft.world.ServerWorldEventHandler; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldType; import net.minecraft.world.storage.ISaveHandler; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.network.ForgeMessage.DimensionRegisterMessage; import net.minecraftforge.fml.common.network.FMLEmbeddedChannel; import net.minecraftforge.fml.common.network.FMLOutboundHandler; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.relauncher.Side; public class ModDimensions { public static final TreeSet LOADED_DIMS = new TreeSet<>(); public static final DimensionType CUSTOM_WORLD = DimensionType.register("CUSTOM_WORLD", "_coverworld", 3, ModWorldProvider.class, false); public static String getWorldName(World ws) { if(ws == null) { return "null"; } int dim = ws.provider.getDimension(); switch(dim) { case -1: { World w = DimensionManager.getWorld(-1); if(w == null) { return "null_nether"; } return w.getWorldInfo().getWorldName() + "_nether"; } case 1: { World w = DimensionManager.getWorld(1); if(w == null) { return "null_end"; } return w.getWorldInfo().getWorldName() + "_end"; } } return ws.getWorldInfo().getWorldName(); } public static String getWorldName(int dim) { return getWorldName(DimensionManager.getWorld(dim)); } public static WorldServer getWorldFromName(String s) { WorldServer ws = DimensionManager.getWorld(0); String normal = ws.getWorldInfo().getWorldName(); if(s.equals(normal)) { return ws; } else if(s.equals(normal + "_nether")) { return DimensionManager.getWorld(-1); } else if(s.equals(normal + "_end")) { return DimensionManager.getWorld(1); } return Arrays.stream(DimensionManager.getWorlds()).filter(w -> w.getWorldInfo().getWorldName().equals(s)).findAny().orElse(null); } /** Unloads a world by its name. * * @param name the name of the world * @return false, if world does not exist or cannot be unloaded */ public static boolean unloadWorld(String name) { WorldServer ws = getWorldFromName(name); if(ws == null) { return false; } int id = ws.provider.getDimension(); if(id >= -1 && id <= 1) { return false; } DimensionManager.unloadWorld(id); // doing this on World.Unload Event, otherwise server crashes because unloadWorld is delayed // DimensionManager.unregisterDimension(id); return true; } /** Loads a world by its name. * * @param name the name of the world * @param type a custom dimension type * @return false, if the world is already loaded */ public static boolean loadWorld(String name, DimensionType type) { WorldServer ws = getWorldFromName(name); if(ws != null) { return false; } int i = 10; for(int dim : LOADED_DIMS) { if(dim == i) { i++; } else if(dim > i) { break; } } loadWorld(type, i, name); LOADED_DIMS.add(i); return true; } private static void loadWorld(DimensionType type, int dim, String name) { if(!DimensionManager.isDimensionRegistered(dim)) { DimensionManager.registerDimension(dim, type); } MinecraftServer ms = KajetansMod.server; ISaveHandler isavehandler = ms.getActiveAnvilConverter().getSaveLoader(name, true); WorldInfo worldinfo = isavehandler.loadWorldInfo(); WorldSettings worldsettings; if (worldinfo == null) { worldsettings = new WorldSettings((new Random()).nextLong(), ms.getGameType(), ms.canStructuresSpawn(), ms.isHardcore(), WorldType.DEFAULT); worldsettings.setGeneratorOptions(""); worldinfo = new WorldInfo(worldsettings, name); } else { worldinfo.setWorldName(name); worldsettings = new WorldSettings(worldinfo); } WorldServer overWorld = (WorldServer) new WorldServer(ms, isavehandler, worldinfo, dim, ms.profiler).init(); overWorld.initialize(worldsettings); overWorld.addEventListener(new ServerWorldEventHandler(ms, overWorld)); overWorld.getWorldInfo().setGameType(ms.getGameType()); //net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world)); // Copied from com.forgeessentials.multiworld.MultiworldManager; Thank you guys. // Tell everyone about the new dim sendNotificationForDimension(dim); } private static void sendNotificationForDimension(int dim) { FMLEmbeddedChannel channel = NetworkRegistry.INSTANCE.getChannel("FORGE", Side.SERVER); DimensionRegisterMessage msg = new DimensionRegisterMessage(dim, "OVERWORLD"); channel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL); channel.writeOutbound(msg); } // used on player connection in ModDedicatedPlayerList public static void sendNotificationsForDimensions(EntityPlayerMP p) { FMLEmbeddedChannel channel = NetworkRegistry.INSTANCE.getChannel("FORGE", Side.SERVER); LOADED_DIMS.forEach(i -> { DimensionRegisterMessage msg = new DimensionRegisterMessage(i, "OVERWORLD"); channel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER); channel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(p); channel.writeOutbound(msg); }); } }