From b3847a62b7ffb7a710a8b768056949ba9aad5ada Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Wed, 4 Sep 2013 13:48:54 -0400 Subject: [PATCH 1/4] Fixed More Bugs 1. Fixed mistakes in PocketBuilder that would cause dungeons to be initialized as non-dungeon pockets. This restored Monolith spawning around dungeons. 2. Fixed a bug in DungeonSchematic - returning links through entry doors should work now. 3. Made minor changes to DungeonSchematic for clarity --- .../mod_pocketDim/dungeon/DungeonSchematic.java | 10 +++++----- StevenDimDoors/mod_pocketDim/world/PocketBuilder.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java b/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java index c118c17..d61f64e 100644 --- a/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java +++ b/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java @@ -168,14 +168,14 @@ public class DungeonSchematic extends Schematic { return new DungeonSchematic(Schematic.copyFromWorld(world, x, y, z, width, height, length, doCompactBounds)); } - public void copyToWorld(World world, Point3D pocketCenter, int dungeonOrientation, DimLink entryLink, Random random) + public void copyToWorld(World world, Point3D pocketCenter, int targetOrientation, DimLink entryLink, Random random) { //TODO: This function is an improvised solution so we can get the release moving. In the future, //we should generalize block transformations and implement support for them at the level of Schematic, //then just use that support from DungeonSchematic instead of making this local fix. //It might be easiest to support transformations using a WorldOperation - final int turnAngle = dungeonOrientation - orientation; + final int turnAngle = targetOrientation - this.orientation; int index; int count; @@ -285,10 +285,10 @@ public class DungeonSchematic extends Schematic { private static void createEntranceReverseLink(NewDimData dimension, Point3D pocketCenter, DimLink entryLink) { - DimLink link = dimension.createLink(pocketCenter.getX(), pocketCenter.getY(), pocketCenter.getZ(), LinkTypes.NORMAL); - Point4D destination = link.source(); + DimLink reverseLink = dimension.createLink(pocketCenter.getX(), pocketCenter.getY(), pocketCenter.getZ(), LinkTypes.NORMAL); + Point4D destination = entryLink.source(); NewDimData prevDim = PocketManager.getDimensionData(destination.getDimension()); - prevDim.setDestination(link, destination.getX(), destination.getY(), destination.getZ()); + prevDim.setDestination(reverseLink, destination.getX(), destination.getY(), destination.getZ()); } private static void createExitDoorLink(NewDimData dimension, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter) diff --git a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java index 1f9aa7b..98e51a4 100644 --- a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java +++ b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java @@ -55,7 +55,7 @@ public class PocketBuilder { //Register a new dimension NewDimData parent = PocketManager.getDimensionData(link.source().getDimension()); - NewDimData dimension = PocketManager.registerPocket(parent, false); + NewDimData dimension = PocketManager.registerPocket(parent, true); //Load a world World world = DimensionManager.getWorld(dimension.id()); @@ -106,7 +106,7 @@ public class PocketBuilder schematic.copyToWorld(world, destination, orientation, link, random); //Finish up destination initialization - dimension.initializePocket(destination.getX(), destination.getY(), destination.getZ(), orientation, link); + dimension.initializeDungeon(destination.getX(), destination.getY(), destination.getZ(), orientation, link, dungeon); dimension.setFilled(true); return true; } From 70eb27608674a4338029c491cbfef2aa9a1a02b3 Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Wed, 4 Sep 2013 14:29:53 -0400 Subject: [PATCH 2/4] Fixed More Bugs Fixed a similar bug in DDTeleporter and PocketBuilder that caused things to be oriented wrong. Specifically, teleporting would orient the player wrong relative to the destination door and pockets would be oriented wrong relative to their parents. Teleporting works properly now. --- StevenDimDoors/mod_pocketDim/DDTeleporter.java | 6 +++--- StevenDimDoors/mod_pocketDim/world/PocketBuilder.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/StevenDimDoors/mod_pocketDim/DDTeleporter.java b/StevenDimDoors/mod_pocketDim/DDTeleporter.java index bb9ca30..97aae3f 100644 --- a/StevenDimDoors/mod_pocketDim/DDTeleporter.java +++ b/StevenDimDoors/mod_pocketDim/DDTeleporter.java @@ -142,8 +142,8 @@ public class DDTeleporter throw new IllegalStateException("The destination world should be loaded!"); } - //Check if the block at that point is actually a door - int blockID = world.getBlockId(door.getX(), door.getY(), door.getZ()); + //Check if the block below that point is actually a door + int blockID = world.getBlockId(door.getX(), door.getY() - 1, door.getZ()); if (blockID != properties.DimensionalDoorID && blockID != properties.WarpDoorID && blockID != properties.TransientDoorID && blockID != properties.UnstableDoorID) { @@ -152,7 +152,7 @@ public class DDTeleporter } //Return the orientation portion of its metadata - return world.getBlockMetadata(door.getX(), door.getY(), door.getZ()) & 3; + return world.getBlockMetadata(door.getX(), door.getY() - 1, door.getZ()) & 3; } public static Entity teleportEntity(Entity entity, Point4D destination) diff --git a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java index 98e51a4..e8afbe0 100644 --- a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java +++ b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java @@ -227,8 +227,8 @@ public class PocketBuilder throw new IllegalStateException("The link's source world should be loaded!"); } - //Check if the block at that point is actually a door - int blockID = world.getBlockId(source.getX(), source.getY(), source.getZ()); + //Check if the block below that point is actually a door + int blockID = world.getBlockId(source.getX(), source.getY() - 1, source.getZ()); if (blockID != properties.DimensionalDoorID && blockID != properties.WarpDoorID && blockID != properties.TransientDoorID) { @@ -236,7 +236,7 @@ public class PocketBuilder } //Return the orientation portion of its metadata - int orientation = world.getBlockMetadata(source.getX(), source.getY(), source.getZ()) & 3; + int orientation = world.getBlockMetadata(source.getX(), source.getY() - 1, source.getZ()) & 3; return orientation; } From 8d5a3ac72ed7457f879ceecec378661fdbcb437f Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Wed, 4 Sep 2013 16:06:54 -0400 Subject: [PATCH 3/4] Fixed More Bugs Fixed how the door in a pocket is placed so that it doesn't break and so that it's placed facing into the pocket. Also added code to make that door link back to the parent dimension - forgot that before! --- .../mod_pocketDim/world/PocketBuilder.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java index e8afbe0..d76e9b6 100644 --- a/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java +++ b/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java @@ -10,7 +10,9 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.common.DimensionManager; import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.core.DimLink; +import StevenDimDoors.mod_pocketDim.core.LinkTypes; import StevenDimDoors.mod_pocketDim.core.NewDimData; import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.dungeon.DungeonData; @@ -18,6 +20,7 @@ import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic; import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPackConfig; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; +import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor; import StevenDimDoors.mod_pocketDim.schematic.BlockRotator; import StevenDimDoors.mod_pocketDim.util.Pair; import StevenDimDoors.mod_pocketDim.util.Point4D; @@ -301,6 +304,10 @@ public class PocketBuilder int destinationY = yCoordHelper.adjustDestinationY(source.getY(), world.getHeight(), wallThickness + 1, size); int orientation = getDoorOrientation(source, properties); + //Place a link leading back out of the pocket + DimLink reverseLink = dimension.createLink(source.getX(), destinationY, source.getZ(), LinkTypes.NORMAL); + parent.setDestination(reverseLink, source.getX(), source.getY(), source.getZ()); + //Build the actual pocket area buildPocket(world, source.getX(), destinationY, source.getZ(), orientation, size, wallThickness, properties); @@ -352,11 +359,10 @@ public class PocketBuilder buildBox(world, center.getX(), center.getY(), center.getZ(), (size / 2) - layer, properties.FabricBlockID, layer < (wallThickness - 1) && properties.TNFREAKINGT_Enabled, properties.NonTntWeight); } - + //Build the door - int metadata = BlockRotator.transformMetadata(BlockRotator.EAST_DOOR_METADATA, orientation - BlockRotator.EAST_DOOR_METADATA, properties.DimensionalDoorID); - setBlockDirectly(world, x, y, z, properties.DimensionalDoorID, metadata); - setBlockDirectly(world, x, y - 1, z, properties.DimensionalDoorID, metadata); + int doorOrientation = BlockRotator.transformMetadata(BlockRotator.EAST_DOOR_METADATA, orientation - BlockRotator.EAST_DOOR_METADATA + 2, properties.DimensionalDoorID); + ItemDimensionalDoor.placeDoorBlock(world, x, y - 1, z, doorOrientation, mod_pocketDim.dimensionalDoor); } private static void buildBox(World world, int centerX, int centerY, int centerZ, int radius, int blockID, boolean placeTnt, int nonTntWeight) From fa33fa95c8b298feaea77a31b00f95fc3d795251 Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Wed, 4 Sep 2013 19:26:59 -0400 Subject: [PATCH 4/4] Fixed Rift Signatures Fixed Rift Signatures and Stabilized Rift Signatures. A few unexpected MC-related issues were preventing them from working properly. Also fixed a typo that caused us to place rift blocks at the wrong coordinates with respect to the rift sig endpoints. Autocorrected the indentation on both source files for aesthetics. --- .../items/ItemRiftSignature.java | 126 ++++++++-------- .../items/ItemStabilizedRiftSignature.java | 140 ++++++++++++------ 2 files changed, 158 insertions(+), 108 deletions(-) diff --git a/StevenDimDoors/mod_pocketDim/items/ItemRiftSignature.java b/StevenDimDoors/mod_pocketDim/items/ItemRiftSignature.java index 088b93d..05b1f51 100644 --- a/StevenDimDoors/mod_pocketDim/items/ItemRiftSignature.java +++ b/StevenDimDoors/mod_pocketDim/items/ItemRiftSignature.java @@ -24,9 +24,9 @@ public class ItemRiftSignature extends Item { super(itemID); this.setMaxStackSize(1); - this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab); this.setMaxDamage(0); this.hasSubtypes = true; + this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab); } @SideOnly(Side.CLIENT) @@ -43,67 +43,69 @@ public class ItemRiftSignature extends Item } @Override - public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int par7, float par8, float par9, float par10) + public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) { - tryItemUse(stack, player, world, x, y, z); - return true; - } - - protected boolean tryItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z) - { - if (!world.isRemote) + // We must use onItemUseFirst() instead of onItemUse() because Minecraft checks + // whether the user is in creative mode after calling onItemUse() and undoes any + // damage we might set to indicate the rift sig has been activated. Otherwise, + // we would need to rely on checking NBT tags for hasEffect() and that function + // gets called constantly. Avoiding NBT lookups reduces our performance impact. + + // Return false on the client side to pass this request to the server + if (world.isRemote) + { + return false; + } + + //We don't check for replaceable blocks. The user can deal with that. <_< + + y += 2; //Increase y by 2 to place the rift at head level + if (!player.canPlayerEdit(x, y, z, 0, stack)) { - //We don't check for replaceable blocks. The user can deal with that. <_< - - y += 2; //Increase y by 2 to place the rift at head level - if (!player.canPlayerEdit(x, y, z, 0, stack)) - { - return false; - } - - Point4D source = getSource(stack); - if (source != null) - { - //The link was used before and already has an endpoint stored. Create links connecting the two endpoints. - NewDimData sourceDimension = PocketManager.getDimensionData(source.getDimension()); - NewDimData destinationDimension = PocketManager.getDimensionData(world); - DimLink link = sourceDimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.NORMAL); - DimLink reverse = destinationDimension.createLink(x, y, z, LinkTypes.NORMAL); - destinationDimension.setDestination(link, x, y, z); - sourceDimension.setDestination(reverse, source.getX(), source.getY(), source.getZ()); - - //Try placing a rift at the destination point - if (!mod_pocketDim.blockRift.isBlockImmune(world, x, y, z)) - { - world.setBlock(x, y, z, mod_pocketDim.blockRift.blockID); - } - - //Try placing a rift at the source point, but check if its world is loaded first - World sourceWorld = DimensionManager.getWorld(sourceDimension.id()); - if (sourceWorld != null && - !mod_pocketDim.blockRift.isBlockImmune(sourceWorld, source.getX(), source.getY(), source.getZ())) - { - sourceWorld.setBlock(source.getX(), source.getY(), source.getY(), mod_pocketDim.blockRift.blockID); - } - - if (!player.capabilities.isCreativeMode) - { - stack.stackSize--; - } - clearSource(stack); - player.sendChatToPlayer("Rift Created"); - world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftEnd", 0.6f, 1); - } - else - { - //The link signature has not been used. Store its current target as the first location. - setSource(stack, x, y, z, PocketManager.getDimensionData(world)); - player.sendChatToPlayer("Location Stored in Rift Signature"); - world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftStart", 0.6f, 1); - } return true; } - return false; + + Point4D source = getSource(stack); + if (source != null) + { + //The link was used before and already has an endpoint stored. Create links connecting the two endpoints. + NewDimData sourceDimension = PocketManager.getDimensionData(source.getDimension()); + NewDimData destinationDimension = PocketManager.getDimensionData(world); + DimLink link = sourceDimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.NORMAL); + DimLink reverse = destinationDimension.createLink(x, y, z, LinkTypes.NORMAL); + destinationDimension.setDestination(link, x, y, z); + sourceDimension.setDestination(reverse, source.getX(), source.getY(), source.getZ()); + + //Try placing a rift at the destination point + if (!mod_pocketDim.blockRift.isBlockImmune(world, x, y, z)) + { + world.setBlock(x, y, z, mod_pocketDim.blockRift.blockID); + } + + //Try placing a rift at the source point, but check if its world is loaded first + World sourceWorld = DimensionManager.getWorld(sourceDimension.id()); + if (sourceWorld != null && + !mod_pocketDim.blockRift.isBlockImmune(sourceWorld, source.getX(), source.getY(), source.getZ())) + { + sourceWorld.setBlock(source.getX(), source.getY(), source.getZ(), mod_pocketDim.blockRift.blockID); + } + + if (!player.capabilities.isCreativeMode) + { + stack.stackSize--; + } + clearSource(stack); + player.sendChatToPlayer("Rift Created"); + world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftEnd", 0.6f, 1); + } + else + { + //The link signature has not been used. Store its current target as the first location. + setSource(stack, x, y, z, PocketManager.getDimensionData(world)); + player.sendChatToPlayer("Location Stored in Rift Signature"); + world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftStart", 0.6f, 1); + } + return true; } /** @@ -138,7 +140,7 @@ public class ItemRiftSignature extends Item itemStack.setTagCompound(tag); itemStack.setItemDamage(1); } - + public static void clearSource(ItemStack itemStack) { //Don't just set the tag to null since there may be other data there (e.g. for renamed items) @@ -149,7 +151,7 @@ public class ItemRiftSignature extends Item tag.removeTag("linkDimID"); itemStack.setItemDamage(0); } - + public static Point4D getSource(ItemStack itemStack) { if (itemStack.getItemDamage() != 0) @@ -157,12 +159,12 @@ public class ItemRiftSignature extends Item if (itemStack.hasTagCompound()) { NBTTagCompound tag = itemStack.getTagCompound(); - + Integer x = tag.getInteger("linkX"); Integer y = tag.getInteger("linkY"); Integer z = tag.getInteger("linkZ"); Integer dimID = tag.getInteger("linkDimID"); - + if (x != null && y != null && z != null && dimID != null) { return new Point4D(x, y, z, dimID); diff --git a/StevenDimDoors/mod_pocketDim/items/ItemStabilizedRiftSignature.java b/StevenDimDoors/mod_pocketDim/items/ItemStabilizedRiftSignature.java index 5ea3f9e..0a20abb 100644 --- a/StevenDimDoors/mod_pocketDim/items/ItemStabilizedRiftSignature.java +++ b/StevenDimDoors/mod_pocketDim/items/ItemStabilizedRiftSignature.java @@ -7,65 +7,113 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; import StevenDimDoors.mod_pocketDim.mod_pocketDim; +import StevenDimDoors.mod_pocketDim.core.DimLink; +import StevenDimDoors.mod_pocketDim.core.LinkTypes; +import StevenDimDoors.mod_pocketDim.core.NewDimData; +import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.util.Point4D; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class ItemStabilizedRiftSignature extends ItemRiftSignature { - public ItemStabilizedRiftSignature(int itemID) - { - super(itemID); - } - - public void registerIcons(IconRegister par1IconRegister) - { - this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", "")); - } + public ItemStabilizedRiftSignature(int itemID) + { + super(itemID); + } - @Override - public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int par7, float par8, float par9, float par10) - { - //Check if the Stabilized Rift Signature has been initialized - Point4D source = getSource(stack); - if (source != null) - { - //Yes, it's initialized. Check if the player can pay an Ender Pearl to create a rift. - if (player.inventory.hasItem(Item.enderPearl.itemID)) - { - if (tryItemUse(stack, player, world, x, y, z) && !player.capabilities.isCreativeMode) - { - player.inventory.consumeInventoryItem(Item.enderPearl.itemID); - } - } - } - else - { - //Initialization doesn't cost any materials - tryItemUse(stack, player, world, x, y, z); - } - return true; - } - - /** - * allows items to add custom lines of information to the mouseover description - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) + public void registerIcons(IconRegister par1IconRegister) + { + this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", "")); + } + + @Override + public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) + { + // Return false on the client side to pass this request to the server + if (world.isRemote) + { + return false; + } + + // We don't check for replaceable blocks. The user can deal with that. <_< + y += 2; //Increase y by 2 to place the rift at head level + if (!player.canPlayerEdit(x, y, z, 0, stack)) + { + return true; + } + + // Check if the Stabilized Rift Signature has been initialized + Point4D source = getSource(stack); + if (source != null) + { + // Yes, it's initialized. Check if the player is in creative + // or if the player can pay an Ender Pearl to create a rift. + if (!player.capabilities.isCreativeMode && !player.inventory.hasItem(Item.enderPearl.itemID)) + { + player.sendChatToPlayer("You don't have any Ender Pearls!"); + return true; + } + + //The link was used before and already has an endpoint stored. Create links connecting the two endpoints. + NewDimData sourceDimension = PocketManager.getDimensionData(source.getDimension()); + NewDimData destinationDimension = PocketManager.getDimensionData(world); + DimLink link = sourceDimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.NORMAL); + DimLink reverse = destinationDimension.createLink(x, y, z, LinkTypes.NORMAL); + destinationDimension.setDestination(link, x, y, z); + sourceDimension.setDestination(reverse, source.getX(), source.getY(), source.getZ()); + + //Try placing a rift at the destination point + if (!mod_pocketDim.blockRift.isBlockImmune(world, x, y, z)) + { + world.setBlock(x, y, z, mod_pocketDim.blockRift.blockID); + } + + //Try placing a rift at the source point, but check if its world is loaded first + World sourceWorld = DimensionManager.getWorld(sourceDimension.id()); + if (sourceWorld != null && + !mod_pocketDim.blockRift.isBlockImmune(sourceWorld, source.getX(), source.getY(), source.getZ())) + { + sourceWorld.setBlock(source.getX(), source.getY(), source.getZ(), mod_pocketDim.blockRift.blockID); + } + + if (!player.capabilities.isCreativeMode) + { + player.inventory.consumeInventoryItem(Item.enderPearl.itemID); + } + player.sendChatToPlayer("Rift Created"); + world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftEnd", 0.6f, 1); + } + else + { + //The link signature has not been used. Store its current target as the first location. + setSource(stack, x, y, z, PocketManager.getDimensionData(world)); + player.sendChatToPlayer("Location Stored in Rift Signature"); + world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftStart", 0.6f, 1); + } + return true; + } + + /** + * allows items to add custom lines of information to the mouseover description + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) @SideOnly(Side.CLIENT) - @Override - public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) - { + @Override + public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) + { Point4D source = getSource(par1ItemStack); if (source != null) { par3List.add("Leads to (" + source.getX() + ", " + source.getY() + ", " + source.getZ() + ") at dimension #" + source.getDimension()); } else - { - par3List.add("First click stores a location,"); - par3List.add("second click creates two rifts"); - par3List.add("that link the locations together."); - } - } + { + par3List.add("First click stores a location,"); + par3List.add("second click creates two rifts"); + par3List.add("that link the locations together."); + } + } }