Merge pull request #25 from SenseiKiwi/master
Major Improvements to DungeonHelper, Minor Bug Fixes and Tweaks
This commit is contained in:
commit
7f6f270fba
11 changed files with 240 additions and 363 deletions
|
@ -1,7 +1,7 @@
|
|||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
@ -77,7 +77,7 @@ public class DDLoot {
|
|||
//the same item. For instance, it cannot distinguish between different types of wood. That shouldn't
|
||||
//matter for most chest loot, though. This could be fixed if we cared enough.
|
||||
Random random = new Random();
|
||||
Hashtable<Integer, WeightedRandomChestContent> container = new Hashtable<Integer, WeightedRandomChestContent>();
|
||||
HashMap<Integer, WeightedRandomChestContent> container = new HashMap<Integer, WeightedRandomChestContent>();
|
||||
|
||||
for (String category : categories)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,8 @@ package StevenDimDoors.mod_pocketDim;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.world.LimboGenerator;
|
||||
|
||||
import net.minecraftforge.common.Configuration;
|
||||
|
||||
public class DDProperties
|
||||
|
@ -99,8 +101,9 @@ public class DDProperties
|
|||
|
||||
public final int NonTntWeight;
|
||||
public final int RiftSpreadModifier;
|
||||
public final int DungeonRiftGenDensity;
|
||||
public final int MonolithSpawnDensity;
|
||||
public final int ClusterGenerationChance;
|
||||
public final int GatewayGenerationChance;
|
||||
public final int MonolithSpawningChance;
|
||||
public final int LimboReturnRange;
|
||||
public final String CustomSchematicDirectory;
|
||||
|
||||
|
@ -200,12 +203,18 @@ public class DDProperties
|
|||
WorldRiftGenerationEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift World Generation", true,
|
||||
"Sets whether dungeon rifts generate in dimensions other than Limbo").getBoolean(true);
|
||||
|
||||
MonolithSpawnDensity = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift World Generation", 7,
|
||||
"Sets the chance that monoliths will not spawn in a give Limbo chunk- higher values mean fewer monoliths, must be greater than 0, default is 7.").getInt();
|
||||
MonolithSpawningChance = config.get(Configuration.CATEGORY_GENERAL, "Monolith Spawning Chance", 28,
|
||||
"Sets the chance (out of " + LimboGenerator.MAX_MONOLITH_SPAWNING_CHANCE + ") that Monoliths will " +
|
||||
"spawn in a given Limbo chunk. The default chance is 28.").getInt();
|
||||
|
||||
DungeonRiftGenDensity = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift World Generation", 250,
|
||||
"Sets the dungeon rift density in the overworld, higher values mean less rifts, must be greater than 0. Default is 250.").getInt();
|
||||
ClusterGenerationChance = config.get(Configuration.CATEGORY_GENERAL, "Cluster Generation Chance", 3,
|
||||
"Sets the chance (out of " + RiftGenerator.MAX_CLUSTER_GENERATION_CHANCE + ") that a cluster of rifts will " +
|
||||
"generate in a given chunk. The default chance is 3.").getInt();
|
||||
|
||||
GatewayGenerationChance = config.get(Configuration.CATEGORY_GENERAL, "Gateway Generation Chance", 40,
|
||||
"Sets the chance (out of " + RiftGenerator.MAX_GATEWAY_GENERATION_CHANCE + ") that a Rift Gateway will " +
|
||||
"generate in a given chunk. The default chance is 40.").getInt();
|
||||
|
||||
RiftSpreadModifier = config.get(Configuration.CATEGORY_GENERAL, "Rift Spread Modifier", 3,
|
||||
"Sets the number of times a rift can spread. 0 prevents rifts from spreading at all. " +
|
||||
"A value greater than 5 is not recommended as the growth is exponential.").getInt();
|
||||
|
@ -216,12 +225,12 @@ public class DDProperties
|
|||
config.save();
|
||||
}
|
||||
|
||||
public static DDProperties create(File configFile)
|
||||
public static DDProperties initialize(File configFile)
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new DDProperties(configFile);
|
||||
else
|
||||
throw new IllegalStateException("Cannot create DDProperties twice");
|
||||
throw new IllegalStateException("Cannot initialize DDProperties twice");
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
@ -232,7 +241,7 @@ public class DDProperties
|
|||
{
|
||||
//This is to prevent some frustrating bugs that could arise when classes
|
||||
//are loaded in the wrong order. Trust me, I had to squash a few...
|
||||
throw new IllegalStateException("Instance of DDProperties requested before properties have been loaded");
|
||||
throw new IllegalStateException("Instance of DDProperties requested before initialization");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -2,31 +2,26 @@ package StevenDimDoors.mod_pocketDim;
|
|||
|
||||
import java.util.Random;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemRiftBlade;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemRiftBlade;
|
||||
import StevenDimDoors.mod_pocketDim.world.pocketProvider;
|
||||
import cpw.mods.fml.common.IWorldGenerator;
|
||||
|
||||
public class RiftGenerator implements IWorldGenerator
|
||||
{
|
||||
private int minableBlockId;
|
||||
private int numberOfBlocks;
|
||||
int cycles=40;
|
||||
boolean shouldSave = false;
|
||||
int count = 0;
|
||||
int i;
|
||||
int k;
|
||||
int j;
|
||||
Random rand = new Random();
|
||||
boolean shouldGenHere=true;
|
||||
LinkData link;
|
||||
DimData dimData;
|
||||
|
||||
public static final int MAX_GATEWAY_GENERATION_CHANCE = 10000;
|
||||
public static final int MAX_CLUSTER_GENERATION_CHANCE = 10000;
|
||||
private static final int CLUSTER_GROWTH_CHANCE = 80;
|
||||
private static final int MAX_CLUSTER_GROWTH_CHANCE = 100;
|
||||
private static final int MIN_RIFT_Y = 21;
|
||||
private static final int MAX_RIFT_Y = 250;
|
||||
private static final int CHUNK_LENGTH = 16;
|
||||
private static final int GATEWAY_RADIUS = 3;
|
||||
private static DDProperties properties = null;
|
||||
|
||||
|
||||
public RiftGenerator()
|
||||
{
|
||||
if (properties == null)
|
||||
|
@ -36,227 +31,120 @@ public class RiftGenerator implements IWorldGenerator
|
|||
@Override
|
||||
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
|
||||
{
|
||||
//Long ntime = System.nanoTime();
|
||||
shouldGenHere=true;
|
||||
|
||||
if (world.provider.getDimensionName()=="PocketDim"|| !properties.WorldRiftGenerationEnabled || world.isRemote)
|
||||
//Don't generate rifts or gateways if the rift generation flag is disabled,
|
||||
//the current world is a pocket dimension, or the world is remote.
|
||||
if (!properties.WorldRiftGenerationEnabled || world.provider instanceof pocketProvider || world.isRemote)
|
||||
{
|
||||
|
||||
this.shouldGenHere=false;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y, z;
|
||||
int blockID;
|
||||
LinkData link;
|
||||
|
||||
if(this.shouldGenHere)
|
||||
//Randomly decide whether to place a cluster of rifts here
|
||||
if (random.nextInt(MAX_CLUSTER_GENERATION_CHANCE) < properties.ClusterGenerationChance)
|
||||
{
|
||||
|
||||
//TODO give this a clamp int type functionality
|
||||
if(random.nextInt(3000+properties.DungeonRiftGenDensity*4)==0)
|
||||
link = null;
|
||||
do
|
||||
{
|
||||
i=chunkX*16-random.nextInt(16);
|
||||
k=chunkZ*16-random.nextInt(16);
|
||||
//Pick a random point on the surface of the chunk
|
||||
x = chunkX * CHUNK_LENGTH - random.nextInt(CHUNK_LENGTH);
|
||||
z = chunkZ * CHUNK_LENGTH - random.nextInt(CHUNK_LENGTH);
|
||||
y = world.getHeightValue(x, z);
|
||||
|
||||
j= world.getHeightValue(i, k);
|
||||
|
||||
if(j>20&&world.getBlockId(i, j, k)==0)
|
||||
//If the point is within the acceptable altitude range and the block above is empty, then place a rift
|
||||
if (y >= MIN_RIFT_Y && y <= MAX_RIFT_Y && world.isAirBlock(x, y + 1, z))
|
||||
{
|
||||
// System.out.println(String.valueOf(i)+"x "+String.valueOf(j)+"y "+String.valueOf(k)+"z"+"Large gen");
|
||||
|
||||
link = new LinkData(world.provider.dimensionId, 0, i, j+1, k, i, j+1, k, true,rand.nextInt(4));
|
||||
link = dimHelper.instance.createPocket(link,true, true);
|
||||
this.shouldSave=true;
|
||||
|
||||
|
||||
// SchematicLoader loader = new SchematicLoader();
|
||||
// loader.init(link);
|
||||
// loader.generateSchematic(link);
|
||||
|
||||
|
||||
count=0;
|
||||
while(random.nextInt(4)!=1)
|
||||
//Create a link. If this is the first time, create a dungeon pocket and create a two-way link.
|
||||
//Otherwise, create a one-way link and connect to the destination of the first link.
|
||||
if (link == null)
|
||||
{
|
||||
i=chunkX*16-random.nextInt(16);
|
||||
k=chunkZ*16-random.nextInt(16);
|
||||
|
||||
j= world.getHeightValue(i, k);
|
||||
|
||||
if(world.isAirBlock(i, j+1, k))
|
||||
{
|
||||
|
||||
|
||||
|
||||
link = dimHelper.instance.createLink(link.locDimID,link.destDimID, i, j+1, k,link.destXCoord,link.destYCoord,link.destZCoord);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
link = new LinkData(world.provider.dimensionId, 0, x, y + 1, z, x, y + 1, z, true, random.nextInt(4));
|
||||
link = dimHelper.instance.createPocket(link, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
link = dimHelper.instance.createLink(link.locDimID, link.destDimID, x, y + 1, z, link.destXCoord, link.destYCoord, link.destZCoord);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
if(random.nextInt(540)==0)
|
||||
{
|
||||
i=chunkX*16-random.nextInt(16);
|
||||
k=chunkZ*16-random.nextInt(16);
|
||||
|
||||
j= world.getHeightValue(i, k);
|
||||
if(j>20&&world.getBlockId(i, j, k)==0)
|
||||
{
|
||||
//System.out.println(String.valueOf(i)+"x "+String.valueOf(j)+"y "+String.valueOf(k)+"z"+"med gen");
|
||||
|
||||
link = new LinkData(world.provider.dimensionId, 0, i, j+1, k, i, j+1, k, true,rand.nextInt(4));
|
||||
link = dimHelper.instance.createPocket(link,true, true);
|
||||
this.shouldSave=true;
|
||||
|
||||
|
||||
// SchematicLoader loader = new SchematicLoader();
|
||||
// loader.init(link);
|
||||
// loader.generateSchematic(link);
|
||||
count=0;
|
||||
|
||||
|
||||
while(random.nextInt(3)!=1)
|
||||
{
|
||||
i=chunkX*16-random.nextInt(16);
|
||||
k=chunkZ*16-random.nextInt(16);
|
||||
|
||||
j= world.getHeightValue(i, k);
|
||||
|
||||
if(world.isAirBlock(i, j+1, k))
|
||||
{
|
||||
|
||||
|
||||
|
||||
link = dimHelper.instance.createLink(link.locDimID,link.destDimID, i, j+1, k,link.destXCoord,link.destYCoord,link.destZCoord);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
**/
|
||||
|
||||
//Randomly decide whether to repeat the process and add another rift to the cluster
|
||||
while (random.nextInt(MAX_CLUSTER_GROWTH_CHANCE) < CLUSTER_GROWTH_CHANCE);
|
||||
}
|
||||
|
||||
if(random.nextInt(properties.DungeonRiftGenDensity)==0&&world.provider.getDimensionName()!="PocketDim"&&!world.isRemote && properties.WorldRiftGenerationEnabled)
|
||||
//Randomly decide whether to place a Rift Gateway here.
|
||||
//This only happens if a rift cluster was NOT generated.
|
||||
else if (random.nextInt(MAX_GATEWAY_GENERATION_CHANCE) < properties.GatewayGenerationChance)
|
||||
{
|
||||
// System.out.println("tryingToGen");
|
||||
int blockID=Block.stoneBrick.blockID;
|
||||
if(world.provider.dimensionId==properties.LimboDimensionID)
|
||||
//Pick a random point on the surface of the chunk
|
||||
x = chunkX * CHUNK_LENGTH - random.nextInt(CHUNK_LENGTH);
|
||||
z = chunkZ * CHUNK_LENGTH - random.nextInt(CHUNK_LENGTH);
|
||||
y = world.getHeightValue(x, z);
|
||||
|
||||
//Check if the point is within the acceptable altitude range, the block above that point is empty,
|
||||
//and at least one of the two blocks under that point are opaque
|
||||
if (y >= MIN_RIFT_Y && y <= MAX_RIFT_Y && world.isAirBlock(x, y + 1, z) &&
|
||||
world.isBlockOpaqueCube(x, y - 2, z) || world.isBlockOpaqueCube(x, y - 1, z))
|
||||
{
|
||||
blockID= properties.LimboBlockID;
|
||||
}
|
||||
i=chunkX*16-random.nextInt(16);
|
||||
k=chunkZ*16-random.nextInt(16);
|
||||
//Create a two-way link between the upper block of the gateway and a pocket dimension
|
||||
//That pocket dimension is where we'll start a dungeon!
|
||||
link = new LinkData(world.provider.dimensionId, 0, x, y + 1, z, x, y + 1, z, true, random.nextInt(4));
|
||||
link = dimHelper.instance.createPocket(link, true, true);
|
||||
|
||||
j= world.getHeightValue(i, k);
|
||||
if(j>20&&world.getBlockId(i, j, k)==0)
|
||||
{
|
||||
//System.out.println(String.valueOf(i)+"x "+String.valueOf(j)+"y "+String.valueOf(k)+"z"+"small gen");
|
||||
|
||||
count=0;
|
||||
|
||||
|
||||
if(world.isAirBlock(i, j+1, k))
|
||||
//If the current dimension isn't Limbo, build a Rift Gateway out of Stone Bricks
|
||||
if (world.provider.dimensionId != properties.LimboDimensionID)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
if(world.isBlockOpaqueCube(i, j-2, k)||world.isBlockOpaqueCube(i, j-1, k))
|
||||
blockID = Block.stoneBrick.blockID;
|
||||
|
||||
//Replace some of the ground around the gateway with bricks
|
||||
for (int xc = -GATEWAY_RADIUS; xc <= GATEWAY_RADIUS; xc++)
|
||||
{
|
||||
link = new LinkData(world.provider.dimensionId, 0, i, j+1, k, i, j+1, k, true,rand.nextInt(4));
|
||||
link =dimHelper.instance.createPocket(link,true, true);
|
||||
|
||||
for(int xc=-3;xc<4;xc++)
|
||||
for (int zc= -GATEWAY_RADIUS; zc <= GATEWAY_RADIUS; zc++)
|
||||
{
|
||||
for(int zc=-3;zc<4;zc++)
|
||||
//Check that the block is supported by an opaque block.
|
||||
//This prevents us from building over a cliff, on the peak of a mountain,
|
||||
//or the surface of the ocean or a frozen lake.
|
||||
if (world.isBlockOpaqueCube(x + xc, y - 2, z + zc))
|
||||
{
|
||||
for(int yc=0;yc<200;yc++)
|
||||
//Randomly choose whether to place bricks or not. The math is designed so that the
|
||||
//chances of placing a block decrease as we get farther from the gateway's center.
|
||||
if (Math.abs(xc) + Math.abs(zc) < random.nextInt(3) + 2)
|
||||
{
|
||||
if(yc==0&&world.isBlockOpaqueCube(i+xc, j-2,k +zc))
|
||||
{
|
||||
|
||||
if(Math.abs(xc)+Math.abs(zc)<rand.nextInt(3)+2)
|
||||
{
|
||||
world.setBlock(i+xc, j-1+yc, k+zc, blockID);
|
||||
}
|
||||
else if(Math.abs(xc)+Math.abs(zc)<rand.nextInt(3)+3)
|
||||
|
||||
{
|
||||
world.setBlock(i+xc, j-1+yc, k+zc, blockID,2,1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Place Stone Bricks
|
||||
world.setBlock(x + xc, y - 1, z + zc, blockID);
|
||||
}
|
||||
else if (Math.abs(xc) + Math.abs(zc) < random.nextInt(3) + 3)
|
||||
{
|
||||
//Place Cracked Stone Bricks
|
||||
world.setBlock(x + xc, y - 1, z + zc, blockID, 2, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ItemRiftBlade.placeDoorBlock(world, i, j+1, k, 0, mod_pocketDim.transientDoor);
|
||||
|
||||
{
|
||||
world.setBlock(i, j+1, k-1, blockID,0,1);
|
||||
world.setBlock(i, j+1, k+1, blockID,0,1);
|
||||
world.setBlock(i, j, k-1, blockID,0,1);
|
||||
world.setBlock(i, j, k+1, blockID,0,1);
|
||||
world.setBlock(i, j+2, k+1, blockID,3,1);
|
||||
world.setBlock(i, j+2, k-1, blockID,3,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this.shouldSave=true;
|
||||
|
||||
}
|
||||
|
||||
// dimData = dimHelper.instance.dimList.get(link.destDimID);
|
||||
|
||||
|
||||
// SchematicLoader loader = new SchematicLoader();
|
||||
// loader.init(link);
|
||||
// loader.generateSchematic(link);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Use Chiseled Stone Bricks to top off the pillars around the door
|
||||
world.setBlock(x, y + 2, z + 1, blockID, 3, 1);
|
||||
world.setBlock(x, y + 2, z - 1, blockID, 3, 1);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Build the gateway out of Unraveled Fabric. Since nearly all the blocks in Limbo are of
|
||||
//that type, there is no point replacing the ground. Just build the tops of the columns here.
|
||||
blockID = properties.LimboBlockID;
|
||||
world.setBlock(x, y + 2, z + 1, blockID, 0, 1);
|
||||
world.setBlock(x, y + 2, z - 1, blockID, 0, 1);
|
||||
}
|
||||
|
||||
//Place the shiny transient door into a dungeon
|
||||
ItemRiftBlade.placeDoorBlock(world, x, y + 1, z, 0, mod_pocketDim.transientDoor);
|
||||
|
||||
//Build the columns around the door
|
||||
world.setBlock(x, y + 1, z - 1, blockID, 0, 1);
|
||||
world.setBlock(x, y + 1, z + 1, blockID, 0, 1);
|
||||
world.setBlock(x, y, z - 1, blockID, 0, 1);
|
||||
world.setBlock(x, y, z + 1, blockID, 0, 1);
|
||||
}
|
||||
}
|
||||
if(this.shouldSave)
|
||||
{
|
||||
// dimHelper.instance.save();
|
||||
}
|
||||
|
||||
// mod_pocketDim.genTime=((System.nanoTime()-ntime)+mod_pocketDim.genTime);
|
||||
// System.out.println( mod_pocketDim.genTime);
|
||||
// System.out.println( (System.nanoTime()-ntime));
|
||||
|
||||
// ntime=0L;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
|
||||
public class CommandEndDungeonCreation extends CommandBase
|
||||
|
@ -34,14 +32,14 @@ public class CommandEndDungeonCreation extends CommandBase
|
|||
|
||||
if (!dungeonHelper.customDungeonStatus.containsKey(player.worldObj.provider.dimensionId))
|
||||
{
|
||||
if(var2.length<2)
|
||||
if (var2.length < 2)
|
||||
{
|
||||
player.sendChatToPlayer("Must have started dungeon creation, use argument OVERRIDE to export anyway");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
else if(!var2[1].contains("OVERRIDE"))
|
||||
else if (!var2[1].contains("OVERRIDE"))
|
||||
{
|
||||
player.sendChatToPlayer("Must have started dungeon creation, use argument OVERRIDE to export anyway");
|
||||
return;
|
||||
|
@ -63,14 +61,22 @@ public class CommandEndDungeonCreation extends CommandBase
|
|||
//Check that the dungeon name is valid to prevent directory traversal and other forms of abuse
|
||||
if (DungeonHelper.NamePattern.matcher(var2[0]).matches())
|
||||
{
|
||||
DungeonGenerator newDungeon = dungeonHelper.exportDungeon(player.worldObj, x, y, z, properties.CustomSchematicDirectory + "/" + var2[0] + ".schematic");
|
||||
player.sendChatToPlayer("created dungeon schematic in " + properties.CustomSchematicDirectory + "/" + var2[0]+".schematic");
|
||||
|
||||
if (dungeonHelper.customDungeonStatus.containsKey(player.worldObj.provider.dimensionId) && !player.worldObj.isRemote)
|
||||
String exportPath = properties.CustomSchematicDirectory + "/" + var2[0] + ".schematic";
|
||||
if (dungeonHelper.exportDungeon(player.worldObj, x, y, z, exportPath))
|
||||
{
|
||||
// mod_pocketDim.dungeonHelper.customDungeonStatus.remove(player.worldObj.provider.dimensionId);
|
||||
// dimHelper.instance.teleportToPocket(player.worldObj, mod_pocketDim.dungeonHelper.customDungeonStatus.get(player.worldObj.provider.dimensionId), player);
|
||||
|
||||
player.sendChatToPlayer("Saved dungeon schematic in " + exportPath);
|
||||
dungeonHelper.registerCustomDungeon(new File(exportPath));
|
||||
|
||||
if (dungeonHelper.customDungeonStatus.containsKey(player.worldObj.provider.dimensionId) && !player.worldObj.isRemote)
|
||||
{
|
||||
// mod_pocketDim.dungeonHelper.customDungeonStatus.remove(player.worldObj.provider.dimensionId);
|
||||
// dimHelper.instance.teleportToPocket(player.worldObj, mod_pocketDim.dungeonHelper.customDungeonStatus.get(player.worldObj.provider.dimensionId), player);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendChatToPlayer("Failed to save dungeon schematic!");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.io.FileOutputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -27,7 +26,6 @@ public class DungeonHelper
|
|||
{
|
||||
private static DungeonHelper instance = null;
|
||||
private static DDProperties properties = null;
|
||||
|
||||
public static final Pattern NamePattern = Pattern.compile("[A-Za-z0-9_]+");
|
||||
|
||||
private static final String SCHEMATIC_FILE_EXTENSION = ".schematic";
|
||||
|
@ -72,12 +70,11 @@ public class DungeonHelper
|
|||
|
||||
public ArrayList<Integer> metadataFlipList = new ArrayList<Integer>();
|
||||
public ArrayList<Integer> metadataNextList = new ArrayList<Integer>();
|
||||
|
||||
public DungeonGenerator defaultBreak = new DungeonGenerator(0, "/schematic/somethingBroke.schematic", true);
|
||||
public DungeonGenerator defaultUp = new DungeonGenerator(0, "/schematic/simpleStairsUp.schematic", true);
|
||||
|
||||
private HashSet<String> dungeonTypeChecker;
|
||||
private Hashtable<String, ArrayList<DungeonGenerator>> dungeonTypeMapping;
|
||||
private HashMap<String, ArrayList<DungeonGenerator>> dungeonTypeMapping;
|
||||
|
||||
private DungeonHelper()
|
||||
{
|
||||
|
@ -90,7 +87,7 @@ public class DungeonHelper
|
|||
}
|
||||
|
||||
//Add all the basic dungeon types to dungeonTypeMapping
|
||||
dungeonTypeMapping = new Hashtable<String, ArrayList<DungeonGenerator>>();
|
||||
dungeonTypeMapping = new HashMap<String, ArrayList<DungeonGenerator>>();
|
||||
dungeonTypeMapping.put(SIMPLE_HALL_DUNGEON_TYPE, simpleHalls);
|
||||
dungeonTypeMapping.put(COMPLEX_HALL_DUNGEON_TYPE, complexHalls);
|
||||
dungeonTypeMapping.put(HUB_DUNGEON_TYPE, hubs);
|
||||
|
@ -109,19 +106,16 @@ public class DungeonHelper
|
|||
private void initializeDungeons()
|
||||
{
|
||||
File file = new File(properties.CustomSchematicDirectory);
|
||||
String helpFile = "/mods/DimDoors/How_to_add_dungeons.txt";
|
||||
if (new File(helpFile).exists())
|
||||
if (file.exists() || file.mkdir())
|
||||
{
|
||||
copyfile.copyFile(helpFile, file + "/How_to_add_dungeons.txt");
|
||||
copyfile.copyFile("/mods/DimDoors/How_to_add_dungeons.txt", file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
||||
}
|
||||
file.mkdir();
|
||||
|
||||
registerFlipBlocks();
|
||||
importCustomDungeons(properties.CustomSchematicDirectory);
|
||||
registerBaseDungeons();
|
||||
}
|
||||
|
||||
public static DungeonHelper create()
|
||||
public static DungeonHelper initialize()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
|
@ -129,7 +123,7 @@ public class DungeonHelper
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Cannot create DungeonHelper twice");
|
||||
throw new IllegalStateException("Cannot initialize DungeonHelper twice");
|
||||
}
|
||||
|
||||
return instance;
|
||||
|
@ -141,7 +135,7 @@ public class DungeonHelper
|
|||
{
|
||||
//This is to prevent some frustrating bugs that could arise when classes
|
||||
//are loaded in the wrong order. Trust me, I had to squash a few...
|
||||
throw new IllegalStateException("Instance of DungeonHelper requested before creation");
|
||||
throw new IllegalStateException("Instance of DungeonHelper requested before initialization");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
@ -154,7 +148,6 @@ public class DungeonHelper
|
|||
if (dungeonData.length < 3 || dungeonData.length > 4)
|
||||
return false;
|
||||
|
||||
|
||||
//Check if the dungeon type is valid
|
||||
if (!dungeonTypeChecker.contains(dungeonData[0].toLowerCase()))
|
||||
return false;
|
||||
|
@ -355,7 +348,7 @@ public class DungeonHelper
|
|||
}
|
||||
}
|
||||
|
||||
public DungeonGenerator exportDungeon(World world, int xI, int yI, int zI, String file)
|
||||
public boolean exportDungeon(World world, int xI, int yI, int zI, String exportPath)
|
||||
{
|
||||
int xMin;
|
||||
int yMin;
|
||||
|
@ -369,9 +362,8 @@ public class DungeonHelper
|
|||
yMin=yMax=yI;
|
||||
zMin=zMax=zI;
|
||||
|
||||
for(int count=0;count<50;count++)
|
||||
for (int count = 0; count < 50; count++)
|
||||
{
|
||||
|
||||
if(world.getBlockId(xMin, yI, zI)!=properties.PermaFabricBlockID)
|
||||
{
|
||||
xMin--;
|
||||
|
@ -495,17 +487,16 @@ public class DungeonHelper
|
|||
CompoundTag schematicTag = new CompoundTag("Schematic", schematic);
|
||||
try
|
||||
{
|
||||
NBTOutputStream stream = new NBTOutputStream(new FileOutputStream(file));
|
||||
NBTOutputStream stream = new NBTOutputStream(new FileOutputStream(exportPath));
|
||||
stream.writeTag(schematicTag);
|
||||
stream.close();
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
this.registerCustomDungeon(new File(file));
|
||||
|
||||
return new DungeonGenerator(0, file, true);
|
||||
}
|
||||
|
||||
public void generateDungeonlink(LinkData incoming)
|
||||
|
@ -516,15 +507,16 @@ public class DungeonHelper
|
|||
|
||||
int depthWeight = rand.nextInt(depth)+rand.nextInt(depth)-2;
|
||||
|
||||
depth=depth-2;
|
||||
// DungeonGenerator
|
||||
depth = depth - 2;
|
||||
boolean flag = true;
|
||||
int count=10;
|
||||
int count = 10;
|
||||
try
|
||||
{
|
||||
if(dimHelper.dimList.get(incoming.destDimID)!=null&&dimHelper.dimList.get(incoming.destDimID).dungeonGenerator!=null)
|
||||
if (dimHelper.dimList.get(incoming.destDimID) != null&&dimHelper.dimList.get(incoming.destDimID).dungeonGenerator!=null)
|
||||
{
|
||||
mod_pocketDim.loader.init(incoming);
|
||||
//TODO: Check this!
|
||||
//What the hell? Isn't this line saying X = X..? ~SenseiKiwi
|
||||
dimHelper.dimList.get(incoming.destDimID).dungeonGenerator=dimHelper.dimList.get(incoming.destDimID).dungeonGenerator;
|
||||
return;
|
||||
}
|
||||
|
@ -653,13 +645,13 @@ public class DungeonHelper
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if (weightedDungeonGenList.size() > 0)
|
||||
{
|
||||
dungeon = weightedDungeonGenList.get(rand.nextInt(weightedDungeonGenList.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -9,29 +8,24 @@ import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
|||
|
||||
public class copyfile
|
||||
{
|
||||
|
||||
|
||||
public static boolean copyFile(String ori, String dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
InputStream in = (mod_pocketDim.class.getClass().getResourceAsStream(ori));
|
||||
OutputStream out = new FileOutputStream(dest);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
InputStream in = (mod_pocketDim.class.getClass().getResourceAsStream(ori));
|
||||
OutputStream out = new FileOutputStream(dest);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
@ -33,7 +32,6 @@ import StevenDimDoors.mod_pocketDim.commands.CommandPrintDimData;
|
|||
import StevenDimDoors.mod_pocketDim.commands.CommandPruneDims;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandStartDungeonCreation;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.copyfile;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemChaosDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemRiftBlade;
|
||||
|
@ -147,7 +145,7 @@ public class mod_pocketDim
|
|||
public void PreInit(FMLPreInitializationEvent event)
|
||||
{
|
||||
//This should be the FIRST thing that gets done.
|
||||
properties = DDProperties.create(event.getSuggestedConfigurationFile());
|
||||
properties = DDProperties.initialize(event.getSuggestedConfigurationFile());
|
||||
|
||||
//Now do other stuff
|
||||
MinecraftForge.EVENT_BUS.register(new EventHookContainer());
|
||||
|
@ -375,7 +373,7 @@ public class mod_pocketDim
|
|||
mod_pocketDim.blocksImmuneToRift.add(Block.blockLapis.blockID);
|
||||
mod_pocketDim.blocksImmuneToRift.add(Block.bedrock.blockID);
|
||||
|
||||
DungeonHelper.create();
|
||||
DungeonHelper.initialize();
|
||||
|
||||
proxy.loadTextures();
|
||||
proxy.registerRenderers();
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraftforge.event.terraingen.ChunkProviderEvent;
|
|||
|
||||
public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvider
|
||||
{
|
||||
public static final int MAX_MONOLITH_SPAWNING_CHANCE = 100;
|
||||
private static Random rand;
|
||||
|
||||
/** A NoiseGeneratorOctaves used in generating terrain */
|
||||
|
@ -108,7 +109,7 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi
|
|||
{
|
||||
// caveGenerator = TerrainGen.getModdedMapGen(caveGenerator, CAVE);
|
||||
}
|
||||
|
||||
|
||||
private static DDProperties properties = null;
|
||||
|
||||
public LimboGenerator(World par1World, long par2)
|
||||
|
@ -135,7 +136,7 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi
|
|||
this.mobSpawnerNoise = noiseGens[6];
|
||||
// TODO Auto-generated constructor stub
|
||||
this.worldObj=par1World;
|
||||
|
||||
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
}
|
||||
|
@ -177,49 +178,37 @@ public class LimboGenerator extends ChunkProviderGenerate implements IChunkProvi
|
|||
@Override
|
||||
public void populate(IChunkProvider var1, int var2, int var3)
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(rand.nextInt(properties.MonolithSpawnDensity)>1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rand.nextInt(MAX_MONOLITH_SPAWNING_CHANCE) < properties.MonolithSpawningChance)
|
||||
{
|
||||
int y =0;
|
||||
int x = var2*16 + rand.nextInt(16);
|
||||
int z = var3*16 + rand.nextInt(16);
|
||||
int yTest;
|
||||
do
|
||||
{
|
||||
|
||||
|
||||
x = var2*16 + rand.nextInt(16);
|
||||
z = var3*16 + rand.nextInt(16);
|
||||
|
||||
|
||||
while(this.worldObj.getBlockId(x, y, z)==0&&y<255)
|
||||
{
|
||||
y++;
|
||||
}
|
||||
y = yCoordHelper.getFirstUncovered(this.worldObj,x , y+2, z);
|
||||
|
||||
|
||||
Entity mob = new MobObelisk(this.worldObj);
|
||||
mob.setLocationAndAngles(x, y, z, 1, 1);
|
||||
|
||||
|
||||
yTest=yCoordHelper.getFirstUncovered(this.worldObj,x , y+5, z);
|
||||
if(yTest>245)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.worldObj.spawnEntityInWorld(mob);
|
||||
|
||||
|
||||
}
|
||||
while(yTest >y);
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
|
||||
while (yTest > y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,112 +15,115 @@ import cpw.mods.fml.relauncher.Side;
|
|||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class pocketProvider extends WorldProvider
|
||||
|
||||
{
|
||||
public int exitXCoord;
|
||||
public int exitYCoord;
|
||||
public int exitZCoord;
|
||||
public int exitDimID;
|
||||
public boolean hasNoSky = true;
|
||||
|
||||
|
||||
public boolean isSavingSchematic= false;
|
||||
public int dimToSave;
|
||||
private static DDProperties properties = null;
|
||||
|
||||
|
||||
public pocketProvider()
|
||||
{
|
||||
this.hasNoSky=true;
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void registerWorldChunkManager()
|
||||
{
|
||||
protected void registerWorldChunkManager()
|
||||
{
|
||||
super.worldChunkMgr = new WorldChunkManagerHell(mod_pocketDim.pocketBiome,1,1);
|
||||
//this.dimensionId = ConfigAtum.dimensionID;
|
||||
}
|
||||
//this.dimensionId = ConfigAtum.dimensionID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSaveFolder()
|
||||
{
|
||||
return (dimensionId == 0 ? null : "DimensionalDoors/pocketDimID" + dimensionId);
|
||||
}
|
||||
|
||||
{
|
||||
return (dimensionId == 0 ? null : "DimensionalDoors/pocketDimID" + dimensionId);
|
||||
}
|
||||
|
||||
public void saveAsSchematic(int id)
|
||||
{
|
||||
this.isSavingSchematic=true;
|
||||
this.dimensionId=id;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Vec3 getSkyColor(Entity cameraEntity, float partialTicks)
|
||||
{
|
||||
setCloudRenderer( new CloudRenderBlank());
|
||||
return this.worldObj.getWorldVec3Pool().getVecFromPool((double)0, (double)0, (double)0);
|
||||
setCloudRenderer( new CloudRenderBlank());
|
||||
return this.worldObj.getWorldVec3Pool().getVecFromPool((double)0, (double)0, (double)0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
|
||||
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public Vec3 getFogColor(float par1, float par2)
|
||||
{
|
||||
return this.worldObj.getWorldVec3Pool().getVecFromPool((double)0, (double)0, (double)0);
|
||||
{
|
||||
return this.worldObj.getWorldVec3Pool().getVecFromPool((double)0, (double)0, (double)0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public double getHorizon()
|
||||
{
|
||||
return worldObj.getHeight();
|
||||
}
|
||||
{
|
||||
return worldObj.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkProvider createChunkGenerator()
|
||||
{
|
||||
return new pocketGenerator(worldObj, dimensionId, false);
|
||||
}
|
||||
@Override
|
||||
public boolean canSnowAt(int x, int y, int z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public boolean canBlockFreeze(int x, int y, int z, boolean byWater)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSnowAt(int x, int y, int z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canBlockFreeze(int x, int y, int z, boolean byWater)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDimensionName()
|
||||
{
|
||||
//TODO: This should be a proper name. We need to show people proper names for things whenever possible.
|
||||
//The question is whether this should be "Pocket Dimension" or "Pocket Dimension #" -- I'm not going to change
|
||||
//it out of concern that it could break something. ~SenseiKiwi
|
||||
return "PocketDim " + this.dimensionId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getRespawnDimension(EntityPlayerMP player)
|
||||
{
|
||||
int respawnDim;
|
||||
|
||||
|
||||
if (properties.LimboEnabled)
|
||||
{
|
||||
respawnDim = properties.LimboDimensionID;
|
||||
}
|
||||
else
|
||||
{
|
||||
respawnDim= dimHelper.dimList.get(this.dimensionId).exitDimLink.destDimID;
|
||||
respawnDim = dimHelper.dimList.get(this.dimensionId).exitDimLink.destDimID;
|
||||
}
|
||||
|
||||
if (dimHelper.getWorld(respawnDim)==null)
|
||||
|
||||
if (dimHelper.getWorld(respawnDim) == null)
|
||||
{
|
||||
dimHelper.initDimension(respawnDim);
|
||||
}
|
||||
return respawnDim;
|
||||
}
|
||||
|
||||
public boolean canRespawnHere()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean canRespawnHere()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
14
mcmod.info
14
mcmod.info
|
@ -1,19 +1,17 @@
|
|||
[
|
||||
{
|
||||
"modid": "DimensionalDoors",
|
||||
"modid": "DimDoors",
|
||||
"name": "Dimensional Doors",
|
||||
"description": "Bend and twist reality itelf, creating pocket dimensions, rifts, and much more",
|
||||
"version": "1.4.0",
|
||||
"credits": "Created by StevenRS11, Coded by StevenRS11 and SenseiKiwi, logo and testing by Jaitsu",
|
||||
"description": "Bend and twist reality itself, creating pocket dimensions, rifts, and much more",
|
||||
"version": "1.5.2R1.4.0RC1",
|
||||
"credits": "Created by StevenRS11, Coded by StevenRS11 and SenseiKiwi, Logo and Testing by Jaitsu",
|
||||
"logoFile": "/dimdoors_logo.png",
|
||||
"mcversion": "",
|
||||
"url": "http://www.minecraftforum.net/topic/1650007-147smpssplan-dimensional-doors-v110-physics-what-physics-updated-with-fancy-opengl/",
|
||||
"updateUrl": "",
|
||||
"authors": [ "StevenRS11, SenseiKiwi" ],
|
||||
"authors": [ "StevenRS11", "SenseiKiwi" ],
|
||||
"parent":"",
|
||||
"screenshots": [],
|
||||
"dependencies": [
|
||||
"mod_MinecraftForge"
|
||||
]
|
||||
"dependencies": [ "mod_MinecraftForge" ]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -24,11 +24,11 @@ To name it, use the following format-
|
|||
|
||||
The dungeon types are ‘hub’, ‘simpleHall’, ‘complexHall’, ‘trap', ‘maze’, ‘exit’, and ‘deadEnd', see explanation further down.
|
||||
|
||||
isOpen determines if the dungeon is an open-air style pocket, or a closed in/walled it pocket that will spawn Monoliths. Correct arguments are 'open' or 'closed'.
|
||||
isOpen determines if the dungeon is an open-air style pocket, or a closed in / walled in pocket that will spawn Monoliths. Correct arguments are 'open' or 'closed'.
|
||||
|
||||
Spawn weight determines how frequently you want it to appear. The default is one, and it will have the same relative weight as all the others.
|
||||
Spawn weight determines how frequently you want it to appear. The default is 100, and it will have the same relative weight as all the others.
|
||||
|
||||
For example- hub_hallWith5Doors_1.schematic
|
||||
For example- hub_hallWith5Doors_open_1.schematic
|
||||
|
||||
|
||||
Congratulations! You have added your own dungeon. You can use the command /dimdoors-genDungeonRift <dungeonName> to gen it, or use /dimdoors-genDungeonRift list to list all avalible dungeons.
|
||||
|
@ -37,9 +37,9 @@ Congratulations! You have added your own dungeon. You can use the command /dimdo
|
|||
These tags are just guidelines, feel free to do whatever you feel like, but the generation algorithm is set up with these in mind-
|
||||
|
||||
|
||||
hub- Dungeons that have 4 or more iron doors in them should be labled as hubs, so they dont gen one after another.
|
||||
hub- Dungeons that have 4 or more iron doors in them should be labeled as hubs, so they don't generate one after another.
|
||||
|
||||
simpleHall- this dungeons contain a single iron door, (possibly two, but not three) and dont contain redstone traps/etc. These are the halls that separate rooms, and should generally be tagged with 'closed' as well.
|
||||
simpleHall - this dungeons contain a single iron door, (possibly two, but not three) and don't contain redstone traps/etc. These are the halls that separate rooms, and should generally be tagged with 'closed' as well.
|
||||
|
||||
complexHall- these dungeons are more like rooms, and can be open. They can have piston puzzles/locks, and up to three iron doors. In addition, they can contain wooden doors to link to the surface.
|
||||
|
||||
|
@ -49,5 +49,5 @@ maze- can contain up to 3 iron dim doors. They can be simple labryinths, or full
|
|||
|
||||
exit- primary purpose is to link back to overworld with a wooden door. Should never contain iron doors.
|
||||
|
||||
deadEnd- no doors, except enterace door. Usually contain some sort of treasure.
|
||||
deadEnd - no doors, except entrance door. Usually contain some sort of treasure.
|
||||
|
||||
|
|
Loading…
Reference in a new issue