Skip to content

Commit

Permalink
Fix teleportation
Browse files Browse the repository at this point in the history
  • Loading branch information
Runemoro committed Dec 18, 2017
1 parent 915bc41 commit 30e7353
Show file tree
Hide file tree
Showing 14 changed files with 76 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState s
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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args
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!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static Pocket readFromNBT(NBTTagCompound nbt) {
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");
Expand All @@ -73,6 +74,7 @@ static NBTBase writeToNBT(Pocket pocket) {
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++) {
Expand Down Expand Up @@ -153,6 +155,7 @@ public void setup() { // Always call after creating a pocket except when buildin
destIterator.remove();
if (index == selectedEntranceIndex) {
entrance = new Location(rift.getWorld(), rift.getPos());
PocketRegistry.getForDim(dimID).markDirty();
List<WeightedRiftDestination> ifDestinations = ((RiftDestination.PocketEntranceDestination) dest).getIfDestinations();
for (WeightedRiftDestination ifDestination : ifDestinations) {
destIterator.add(new WeightedRiftDestination(ifDestination.getDestination(), ifDestination.getWeight() / wdest.getWeight(), ifDestination.getGroup()));
Expand Down Expand Up @@ -190,7 +193,7 @@ public void linkPocketTo(RiftDestination linkTo) {
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();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
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);

Expand All @@ -219,7 +219,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
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);

Expand Down Expand Up @@ -313,6 +313,7 @@ public Location getPrivatePocketEntrance(String playerUUID) {

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?
Expand All @@ -321,6 +322,7 @@ public static Location getEscapeRift(String playerUUID) { // TODO: since this is

public static void setEscapeRift(String playerUUID, Location rift) {
getForDim(0).escapeRifts.put(playerUUID, rift);
getForDim(0).markDirty();
}

public static List<AvailableLinkInfo> getAvailableLinks() { // TODO: cache this
Expand Down
36 changes: 21 additions & 15 deletions src/main/java/com/zixiken/dimdoors/shared/rifts/TileEntityRift.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,10 @@ public void teleportTo(Entity entity) { // TODO: new velocity angle if !preserve

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<WeightedRiftDestination, Float> weightMap = new HashMap<>(); // TODO: cache this, faster implementation of single rift
for (WeightedRiftDestination destination : destinations) {
Expand All @@ -273,10 +276,10 @@ public boolean teleport(Entity entity) { try { // TODO: return failiure message
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
Expand All @@ -286,17 +289,17 @@ public boolean teleport(Entity entity) { try { // TODO: return failiure message
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.
}
Expand All @@ -316,7 +319,10 @@ public boolean teleport(Entity entity) { try { // TODO: return failiure message
// 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
}
Expand Down Expand Up @@ -440,7 +446,7 @@ public void handleUpdateTag(NBTTagCompound tag) {
deserializeNBT(tag);
}

public void notifyStateChanged() {
public void markStateChanged() {
riftStateChanged = true;
markDirty();
}
Expand Down
39 changes: 32 additions & 7 deletions src/main/java/com/zixiken/dimdoors/shared/util/TeleportUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
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;
Expand All @@ -29,6 +31,10 @@ public static Entity teleport(Entity entity, Location location, float yaw, float
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(
Expand All @@ -49,25 +55,37 @@ public static Entity teleport(Entity entity, Location location, float yaw, float
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);
Expand All @@ -81,6 +99,13 @@ public static Entity teleport(Entity entity, Location location, float yaw, float
}

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");
Expand Down

0 comments on commit 30e7353

Please sign in to comment.