package erebus.world.teleporter; import java.util.UUID; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList; import net.minecraft.entity.item.EntityMinecartContainer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.DimensionType; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; import net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent; import erebus.Erebus; import erebus.core.handler.configs.ConfigHandler; import gnu.trove.map.TObjectByteMap; import gnu.trove.map.hash.TObjectByteHashMap; public final class TeleporterHandler { private static TeleporterHandler INSTANCE = new TeleporterHandler(); public static void init() { MinecraftForge.EVENT_BUS.register(INSTANCE); } public static void transferToOverworld(Entity entity) { INSTANCE.transferEntity(entity, 0); } public static void transferToErebus(Entity entity) { INSTANCE.transferEntity(entity, ConfigHandler.INSTANCE.erebusDimensionID); } private final TObjectByteMap<UUID> waitingPlayers = new TObjectByteHashMap<UUID>(); private boolean checkWaitingPlayers = false; private TeleporterErebus teleportToOverworld; private TeleporterErebus teleportToErebus; private TeleporterHandler() { } @SubscribeEvent public void onWorldLoad(WorldEvent.Load e) { if (!(e.getWorld() instanceof WorldServer)) return; WorldServer world = (WorldServer) e.getWorld(); if (world.provider.getDimensionType() == DimensionType.OVERWORLD) world.customTeleporters.add(teleportToOverworld = new TeleporterErebus(world)); else if (world.provider.getDimensionType() == Erebus.dimensionType) world.customTeleporters.add(teleportToErebus = new TeleporterErebus(world)); System.out.println("added to " + e.getWorld()); } @SubscribeEvent public void onServerTick(ServerTickEvent e) { if (e.phase != Phase.END || !checkWaitingPlayers) return; UUID[] ids = waitingPlayers.keys(new UUID[waitingPlayers.size()]); for (UUID uuid : ids) if (waitingPlayers.adjustOrPutValue(uuid, (byte) -1, (byte) 0) <= 0) { waitingPlayers.remove(uuid); if (waitingPlayers.isEmpty()) checkWaitingPlayers = false; } } private void transferEntity(Entity entity, int dimensionId) { if (dimensionId != 0 && dimensionId != ConfigHandler.INSTANCE.erebusDimensionID) throw new IllegalArgumentException("Supplied invalid dimension ID into Erebus teleporter: " + dimensionId); World world = entity.worldObj; if (!world.isRemote && !entity.isDead) if (entity instanceof EntityPlayerMP) { if (entity instanceof FakePlayer) return; EntityPlayerMP player = (EntityPlayerMP) entity; if (waitingPlayers.containsKey(player.getUniqueID())) { waitingPlayers.put(player.getUniqueID(), (byte) 20); return; } waitingPlayers.put(player.getUniqueID(), (byte) 40); // if there are any issues, we can either increase the number or rewrite the "is player in portal?" checking part checkWaitingPlayers = true; player.mcServer.getPlayerList().transferPlayerToDimension(player, dimensionId, dimensionId == 0 ? teleportToOverworld : teleportToErebus); player.timeUntilPortal = 0; /* * player.lastExperience = -1; player.lastHealth = -1.0F; player.lastFoodLevel = -1; */ } else if (!(entity instanceof EntityMinecartContainer)) { // TODO we cannot handle this, would result in container breaking in both worlds and duplicate items; // find some sneaky solution around this issue fixme copy paste world.theProfiler.startSection("changeDimension"); MinecraftServer mcServer = world.getMinecraftServer(); WorldServer worldCurrent = mcServer.worldServerForDimension(entity.dimension); WorldServer worldTarget = mcServer.worldServerForDimension(dimensionId); entity.dimension = dimensionId; world.removeEntity(entity); entity.isDead = false; world.theProfiler.startSection("reposition"); mcServer.getPlayerList().transferEntityToWorld(entity, dimensionId, worldCurrent, worldTarget, dimensionId == 0 ? teleportToOverworld : teleportToErebus); world.theProfiler.endStartSection("reloading"); Entity newEntity = EntityList.createEntityByName(EntityList.getEntityString(entity), worldTarget); if (newEntity != null) { //newEntity.copyDataFromOld(entity); worldTarget.spawnEntityInWorld(newEntity); } entity.isDead = true; world.theProfiler.endSection(); worldCurrent.resetUpdateEntityTick(); worldTarget.resetUpdateEntityTick(); world.theProfiler.endSection(); newEntity.timeUntilPortal = entity.getPortalCooldown(); } } }