Fix teleportation
This commit is contained in:
parent
915bc41a08
commit
30e735385f
14 changed files with 76 additions and 32 deletions
src/main/java/com/zixiken/dimdoors/shared
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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<WeightedRiftDestination> 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AvailableLinkInfo> getAvailableLinks() { // TODO: cache this
|
||||
|
|
|
@ -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<WeightedRiftDestination, Float> 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();
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Add table
Reference in a new issue