From 30e735385f705b14a938b9e88d18537849c438fd Mon Sep 17 00:00:00 2001 From: Runemoro Date: Mon, 18 Dec 2017 01:48:58 -0500 Subject: [PATCH] Fix teleportation --- .../shared/blocks/BlockDimDoorBase.java | 10 ++--- .../shared/commands/PocketCommand.java | 2 +- .../shared/items/ItemBlockFabric.java | 3 +- .../dimdoors/shared/items/ItemDimDoor.java | 1 + .../shared/items/ItemDimDoorGold.java | 1 + .../shared/items/ItemDimDoorPersonal.java | 1 + .../shared/items/ItemDimDoorUnstable.java | 1 + .../shared/items/ItemDimDoorWarp.java | 1 + .../dimdoors/shared/items/ItemDoorGold.java | 1 + .../dimdoors/shared/items/ItemDoorQuartz.java | 1 + .../dimdoors/shared/pockets/Pocket.java | 5 ++- .../dimdoors/shared/rifts/RiftRegistry.java | 6 ++- .../dimdoors/shared/rifts/TileEntityRift.java | 36 ++++++++++------- .../dimdoors/shared/util/TeleportUtils.java | 39 +++++++++++++++---- 14 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/zixiken/dimdoors/shared/blocks/BlockDimDoorBase.java b/src/main/java/com/zixiken/dimdoors/shared/blocks/BlockDimDoorBase.java index 347c2df9..540c2bc1 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/blocks/BlockDimDoorBase.java +++ b/src/main/java/com/zixiken/dimdoors/shared/blocks/BlockDimDoorBase.java @@ -45,12 +45,12 @@ public abstract class BlockDimDoorBase extends BlockDoor implements ITileEntityP if (!(doorState.getBlock() instanceof BlockDoor)) return; if (doorState.getValue(BlockDoor.OPEN) && entityIn.timeUntilPortal == 0) { entityIn.timeUntilPortal = 50; // 2.5s - toggleDoor(worldIn, pos, false); TileEntityEntranceRift rift = getRift(worldIn, pos, state); - if (!rift.teleport(entityIn) && entityIn instanceof EntityPlayer) { - DimDoors.chat((EntityPlayer) entityIn, "Teleporting failed because this entrance has no destinations!"); - } else if (rift.isCloseAfterPassThrough()) { // TODO: move logic to TileEntityEntranceRift? - worldIn.destroyBlock(pos, false); + boolean successful = rift.teleport(entityIn); + if (successful)entityIn.timeUntilPortal = 0; + if (successful && entityIn instanceof EntityPlayer) { + if(!state.getValue(POWERED)) toggleDoor(worldIn, pos, false); // TODO: config option playerClosesDoorBehind + if (rift.isCloseAfterPassThrough()) worldIn.destroyBlock(pos, false); } } } diff --git a/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java b/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java index eb8ad977..9a6fc34f 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java +++ b/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java @@ -53,7 +53,7 @@ public class PocketCommand extends CommandBase { Pocket pocket = PocketGenerator.generatePocketFromTemplate(dim, 0, template, new VirtualLocation(0, 0, 0, 0,0)); // TODO: options for linking back/not setting entrance pocket.setup(); - TileEntityRift entrance = (TileEntityRift) player.world.getTileEntity(pocket.getEntrance().getPos()); + TileEntityRift entrance = (TileEntityRift) player.world.getTileEntity(pocket.getEntrance().getPos()); // TODO: what about no entrances? entrance.teleportTo(player); } else { DimDoors.chat(player, "You must be in a pocket dimension to use this command!"); diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemBlockFabric.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemBlockFabric.java index 18789ee0..fc3da7d4 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemBlockFabric.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemBlockFabric.java @@ -12,9 +12,10 @@ public class ItemBlockFabric extends ItemBlock { public ItemBlockFabric() { super(ModBlocks.FABRIC); - setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setMaxDamage(0); setHasSubtypes(true); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); + setUnlocalizedName(BlockFabric.ID); setRegistryName(BlockFabric.ID); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoor.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoor.java index 3fdbf117..f6249e90 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoor.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoor.java @@ -17,6 +17,7 @@ public class ItemDimDoor extends ItemDoor { public ItemDimDoor() { super(ModBlocks.DIMENSIONAL_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDimDoorIron.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDimDoorIron.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorGold.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorGold.java index 1ed16268..3daf6b52 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorGold.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorGold.java @@ -17,6 +17,7 @@ public class ItemDimDoorGold extends ItemDoor { public ItemDimDoorGold() { super(ModBlocks.GOLD_DIMENSIONAL_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDimDoorGold.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDimDoorGold.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorPersonal.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorPersonal.java index 78f16ddf..71836af3 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorPersonal.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorPersonal.java @@ -17,6 +17,7 @@ public class ItemDimDoorPersonal extends ItemDoor { public ItemDimDoorPersonal() { super(ModBlocks.PERSONAL_DIMENSIONAL_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDimDoorPersonal.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDimDoorPersonal.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorUnstable.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorUnstable.java index a8b91251..b9d9fe90 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorUnstable.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorUnstable.java @@ -17,6 +17,7 @@ public class ItemDimDoorUnstable extends ItemDoor { public ItemDimDoorUnstable() { super(ModBlocks.UNSTABLE_DIMENSIONAL_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDimDoorUnstable.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDimDoorUnstable.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorWarp.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorWarp.java index b043c267..aa4067d6 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorWarp.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDimDoorWarp.java @@ -17,6 +17,7 @@ public class ItemDimDoorWarp extends ItemDoor { public ItemDimDoorWarp() { super(ModBlocks.WARP_DIMENSIONAL_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDimDoorWarp.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDimDoorWarp.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorGold.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorGold.java index 76a9ce3c..0253d967 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorGold.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorGold.java @@ -11,6 +11,7 @@ public class ItemDoorGold extends ItemDoor { public ItemDoorGold() { super(ModBlocks.GOLD_DOOR); setMaxStackSize(16); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDoorGold.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDoorGold.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorQuartz.java b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorQuartz.java index 211fd0fc..2477e7c0 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorQuartz.java +++ b/src/main/java/com/zixiken/dimdoors/shared/items/ItemDoorQuartz.java @@ -10,6 +10,7 @@ public class ItemDoorQuartz extends ItemDoor { public ItemDoorQuartz() { super(ModBlocks.QUARTZ_DOOR); + setCreativeTab(DimDoors.DIM_DOORS_CREATIVE_TAB); setUnlocalizedName(BlockDoorQuartz.ID); setRegistryName(new ResourceLocation(DimDoors.MODID, BlockDoorQuartz.ID)); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/pockets/Pocket.java b/src/main/java/com/zixiken/dimdoors/shared/pockets/Pocket.java index d49724b3..2ff424e2 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/pockets/Pocket.java +++ b/src/main/java/com/zixiken/dimdoors/shared/pockets/Pocket.java @@ -50,6 +50,7 @@ public class Pocket { // TODO: better visibilities pocket.z = nbt.getInteger("z"); pocket.size = nbt.getInteger("size"); if (nbt.hasKey("virtualLocation")) pocket.virtualLocation = VirtualLocation.readFromNBT(nbt.getCompoundTag("virtualLocation")); + if (nbt.hasKey("entrance")) pocket.entrance = Location.readFromNBT(nbt.getCompoundTag("entrance")); pocket.playerUUIDs = new ArrayList<>(); NBTTagList playerUUIDsNBT = (NBTTagList) nbt.getTag("playerUUIDs"); @@ -73,6 +74,7 @@ public class Pocket { // TODO: better visibilities nbt.setInteger("z", pocket.z); nbt.setInteger("size", pocket.size); if (pocket.virtualLocation != null) nbt.setTag("virtualLocation", pocket.virtualLocation.writeToNBT()); + if (pocket.entrance != null) nbt.setTag("entrance", Location.writeToNBT(pocket.entrance)); NBTTagList playerUUIDsNBT = new NBTTagList(); for (int i = 0; i < pocket.playerUUIDs.size(); i++) { @@ -153,6 +155,7 @@ public class Pocket { // TODO: better visibilities destIterator.remove(); if (index == selectedEntranceIndex) { entrance = new Location(rift.getWorld(), rift.getPos()); + PocketRegistry.getForDim(dimID).markDirty(); List ifDestinations = ((RiftDestination.PocketEntranceDestination) dest).getIfDestinations(); for (WeightedRiftDestination ifDestination : ifDestinations) { destIterator.add(new WeightedRiftDestination(ifDestination.getDestination(), ifDestination.getWeight() / wdest.getWeight(), ifDestination.getGroup())); @@ -190,7 +193,7 @@ public class Pocket { // TODO: better visibilities if (dest.getType() == RiftDestination.EnumType.POCKET_EXIT) { destIterator.remove(); destIterator.add(new WeightedRiftDestination(linkTo.withOldDestination(dest), wdest.getWeight(), wdest.getGroup())); - rift.notifyStateChanged(); + rift.markStateChanged(); rift.markDirty(); } } diff --git a/src/main/java/com/zixiken/dimdoors/shared/rifts/RiftRegistry.java b/src/main/java/com/zixiken/dimdoors/shared/rifts/RiftRegistry.java index a7768e7e..1194409c 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/rifts/RiftRegistry.java +++ b/src/main/java/com/zixiken/dimdoors/shared/rifts/RiftRegistry.java @@ -209,7 +209,7 @@ public class RiftRegistry extends WorldSavedData { NBTTagCompound privatePocketEntranceNBT = new NBTTagCompound(); privatePocketEntranceNBT.setString("uuid", privatePocketEntrance.getKey()); privatePocketEntranceNBT.setTag("location", Location.writeToNBT(privatePocketEntrance.getValue())); - riftsNBT.appendTag(privatePocketEntranceNBT); + privatePocketEntrancesNBT.appendTag(privatePocketEntranceNBT); } nbt.setTag("privatePocketEntrances", privatePocketEntrancesNBT); @@ -219,7 +219,7 @@ public class RiftRegistry extends WorldSavedData { NBTTagCompound escapeRiftNBT = new NBTTagCompound(); escapeRiftNBT.setString("uuid", escapeRift.getKey()); escapeRiftNBT.setTag("location", Location.writeToNBT(escapeRift.getValue())); - riftsNBT.appendTag(escapeRiftNBT); + escapeRiftsNBT.appendTag(escapeRiftNBT); } nbt.setTag("escapeRifts", escapeRiftsNBT); @@ -313,6 +313,7 @@ public class RiftRegistry extends WorldSavedData { public void setPrivatePocketEntrance(String playerUUID, Location rift) { privatePocketEntrances.put(playerUUID, rift); + markDirty(); } public static Location getEscapeRift(String playerUUID) { // TODO: since this is per-world, move to different registry? @@ -321,6 +322,7 @@ public class RiftRegistry extends WorldSavedData { public static void setEscapeRift(String playerUUID, Location rift) { getForDim(0).escapeRifts.put(playerUUID, rift); + getForDim(0).markDirty(); } public static List getAvailableLinks() { // TODO: cache this diff --git a/src/main/java/com/zixiken/dimdoors/shared/rifts/TileEntityRift.java b/src/main/java/com/zixiken/dimdoors/shared/rifts/TileEntityRift.java index 9ddcfa0c..0372bbb5 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/rifts/TileEntityRift.java +++ b/src/main/java/com/zixiken/dimdoors/shared/rifts/TileEntityRift.java @@ -250,7 +250,10 @@ public abstract class TileEntityRift extends TileEntity implements ITickable { / public boolean teleport(Entity entity) { try { // TODO: return failiure message string rather than boolean riftStateChanged = false; - if (destinations.size() == 0) return false; + if (destinations.size() == 0) { + if (entity instanceof EntityPlayer) DimDoors.chat((EntityPlayer) entity, "This rift has no destinations!"); + return false; + } Map weightMap = new HashMap<>(); // TODO: cache this, faster implementation of single rift for (WeightedRiftDestination destination : destinations) { @@ -273,10 +276,10 @@ public abstract class TileEntityRift extends TileEntity implements ITickable { / destLoc = destinationToLocation(dest); break; case NEW_PUBLIC: - Pocket publicPocket = PocketGenerator.generatePublicPocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-1).build() : null); // TODO: random transform - publicPocket.setup(); - publicPocket.linkPocketTo(destHere); - destLoc = publicPocket.getEntrance(); + Pocket pocket = PocketGenerator.generatePublicPocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-1).build() : null); // TODO: random transform + pocket.setup(); + pocket.linkPocketTo(destHere); + destLoc = pocket.getEntrance(); if (destLoc != null) makeDestinationPermanent(weightedDestination, destLoc); break; case PRIVATE: // TODO: move logic to PrivatePocketTeleportDestination @@ -286,17 +289,17 @@ public abstract class TileEntityRift extends TileEntity implements ITickable { / if (uuid != null) { PocketRegistry privatePocketRegistry = PocketRegistry.getForDim(DimDoorDimensions.getPrivateDimID()); RiftRegistry privateRiftRegistry = RiftRegistry.getForDim(DimDoorDimensions.getPrivateDimID()); - Pocket privatePocket = privatePocketRegistry.getPocket(privatePocketRegistry.getPrivatePocketID(uuid)); - if (privatePocket == null) { // generate the private pocket and get its entrance - privatePocket = PocketGenerator.generatePrivatePocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-2).build() : null); // set to where the pocket was first created TODO: private pocket deletion - privatePocket.setup(); - privatePocketRegistry.setPrivatePocketID(uuid, privatePocket.getId()); - destLoc = privatePocket.getEntrance(); + /*Pocket*/ pocket = privatePocketRegistry.getPocket(privatePocketRegistry.getPrivatePocketID(uuid)); + if (pocket == null) { // generate the private pocket and get its entrance + pocket = PocketGenerator.generatePrivatePocket(virtualLocation != null ? virtualLocation.toBuilder().depth(-2).build() : null); // set to where the pocket was first created TODO: private pocket deletion + pocket.setup(); + privatePocketRegistry.setPrivatePocketID(uuid, pocket.getId()); + destLoc = pocket.getEntrance(); } else { destLoc = privateRiftRegistry.getPrivatePocketEntrance(uuid); // get the last used entrance - if (destLoc == null) destLoc = privatePocket.getEntrance(); // if there's none, then set the target to the main entrance + if (destLoc == null) destLoc = pocket.getEntrance(); // if there's none, then set the target to the main entrance } - privateRiftRegistry.setPrivatePocketEntrance(uuid, null); // forget the last entered entrance + // privateRiftRegistry.setPrivatePocketEntrance(uuid, null); // --forget the last entered entrance-- Actually, remember it. We'll eventually store it only in the rift registry, not in the pocket. } else { return false; // TODO: There should be a way to get other entities into your private pocket, though. Add API for other mods. } @@ -316,7 +319,10 @@ public abstract class TileEntityRift extends TileEntity implements ITickable { / // TODO: teleport the player to random coordinates based on depth around destLoc return true; } - if (destLoc == null) return false; // TODO: The player probably teleported into the dungeon/private pocket and is now trying to escape... What should we do? Limbo? + if (destLoc == null) { + if (entity instanceof EntityPlayer) DimDoors.chat((EntityPlayer) entity, "You tried to escape a pocket or leave your private pocket, but you teleported into it!"); + return false; // TODO: limbo? + } } else { return false; // Non-player/owned entity tried to escape/leave private pocket } @@ -440,7 +446,7 @@ public abstract class TileEntityRift extends TileEntity implements ITickable { / deserializeNBT(tag); } - public void notifyStateChanged() { + public void markStateChanged() { riftStateChanged = true; markDirty(); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/util/TeleportUtils.java b/src/main/java/com/zixiken/dimdoors/shared/util/TeleportUtils.java index d77f8326..8f877583 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/util/TeleportUtils.java +++ b/src/main/java/com/zixiken/dimdoors/shared/util/TeleportUtils.java @@ -6,11 +6,13 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.play.server.*; import net.minecraft.potion.PotionEffect; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.WorldServer; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fml.common.FMLCommonHandler; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.EnumSet; @@ -29,6 +31,10 @@ public class TeleportUtils { int oldDimension = entity.dimension; int newDimension = location.getDimID(); + if (entity instanceof EntityPlayerMP) { + entity.noClip = true; + } + if (oldDimension == newDimension) { // Based on CommandTeleport.doTeleport if (entity instanceof EntityPlayerMP) { ((EntityPlayerMP) entity).connection.setPlayerLocation( @@ -49,25 +55,37 @@ public class TeleportUtils { WorldServer newServer = server.getWorld(newDimension); // Allow other mods to cancel the event - if (!ForgeHooks.onTravelToDimension(entity, newDimension)) return entity; // TODO: Original code returns null, but that might be a bug + if (!ForgeHooks.onTravelToDimension(entity, newDimension)) return entity; if (entity instanceof EntityPlayerMP) { EntityPlayerMP player = (EntityPlayerMP) entity; - // TODO: set invulnerableDimensionChange like in EntityPlayerMP? + try { + Field invulnerableDimensionChange = EntityPlayerMP.class.getDeclaredField("invulnerableDimensionChange"); // Prevents cancelling the position change in survival. TODO: necessary? + invulnerableDimensionChange.setAccessible(true); + invulnerableDimensionChange.setBoolean(player, true); // without this, there's a chance that the new player position gets cancelled + } catch (NoSuchFieldException|IllegalAccessException e) { + throw new RuntimeException(e); + } + // player.enteredNetherPosition = null; player.dimension = newDimension; + player.connection.sendPacket(new SPacketRespawn(player.dimension, newServer.getDifficulty(), newServer.getWorldInfo().getTerrainType(), player.interactionManager.getGameType())); // Remove from old world - player.connection.sendPacket(new SPacketRespawn(player.dimension, newServer.getDifficulty(), newServer.getWorldInfo().getTerrainType(), player.interactionManager.getGameType())); player.mcServer.getPlayerList().updatePermissionLevel(player); oldServer.removeEntityDangerously(player); player.isDead = false; // Move to new world - player.moveToBlockPosAndAngles(location.getPos(), yaw, pitch); - oldServer.updateEntityWithOptionalForce(entity, false); - player.setWorld(newServer); - newServer.spawnEntity(player); // TODO: necessary? + oldServer.profiler.startSection("moving"); + player.moveToBlockPosAndAngles(location.getPos(), yaw, pitch); // TODO: clamp to world border or -29999872, 29999872 like in original code? + if (entity.isEntityAlive()) oldServer.updateEntityWithOptionalForce(entity, false); + oldServer.profiler.endSection(); + + oldServer.profiler.startSection("placing"); + newServer.spawnEntity(player); newServer.updateEntityWithOptionalForce(player, false); + oldServer.profiler.endSection(); + player.setWorld(newServer); // Sync the player player.mcServer.getPlayerList().preparePlayer(player, oldServer); @@ -81,6 +99,13 @@ public class TeleportUtils { } FMLCommonHandler.instance().firePlayerChangedDimensionEvent(player, oldDimension, newDimension); + + player.connection.sendPacket(new SPacketEffect(1032, BlockPos.ORIGIN, 0, false)); + + //player.prevBlockpos = null; // For frost walk. Is this needed? What about other fields? + /*player.lastExperience = -1; + player.lastHealth = -1.0F; + player.lastFoodLevel = -1;*/ return entity; } else { entity.world.profiler.startSection("changeDimension");