diff --git a/StevenDimDoors/mod_pocketDim/SchematicLoader.java b/StevenDimDoors/mod_pocketDim/SchematicLoader.java index 00d1b6a..b1c796a 100644 --- a/StevenDimDoors/mod_pocketDim/SchematicLoader.java +++ b/StevenDimDoors/mod_pocketDim/SchematicLoader.java @@ -43,12 +43,15 @@ public class SchematicLoader if (dimList.get(destDimID).dungeonGenerator == null) { //The following initialization code is based on code from ChunkProviderGenerate. - //It makes our generation depend on the world seed. + //It makes our generation depend on the world seed. We have an additional seed here + //to prevent correlations between the selected dungeons and the locations of gateways. + //TODO: We should centralize RNG initialization and world-seed modifiers for each specific application. - Random random = new Random(world.getSeed()); - long factorA = random.nextLong() / 2L * 2L + 1L; - long factorB = random.nextLong() / 2L * 2L + 1L; - random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ world.getSeed()); + final long localSeed = world.getSeed() ^ 0x2F50DB9B4A8057E4L; + final Random random = new Random(); + final long factorA = random.nextLong() / 2L * 2L + 1L; + final long factorB = random.nextLong() / 2L * 2L + 1L; + random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ localSeed); dungeonHelper.generateDungeonLink(link, dungeonHelper.RuinsPack, random); } diff --git a/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonChainRule.java b/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonChainRule.java index 472f20b..17554dc 100644 --- a/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonChainRule.java +++ b/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonChainRule.java @@ -15,12 +15,13 @@ public class DungeonChainRule ArrayList conditionNames = source.getCondition(); ArrayList> productNames = source.getProducts(); + //Obtain the IDs of dungeon types in reverse order. Reverse order makes comparing against chain histories easy. condition = new int[conditionNames.size()]; - for (int k = 0; k < condition.length; k++) + for (int src = 0, dst = condition.length - 1; src < condition.length; src++, dst--) { - condition[k] = nameToTypeMapping.get(conditionNames.get(k)).ID; + condition[dst] = nameToTypeMapping.get(conditionNames.get(src)).ID; } - products = new ArrayList>(); + products = new ArrayList>(productNames.size()); for (WeightedContainer product : productNames) { products.add(new WeightedContainer(nameToTypeMapping.get(product.getData()), product.itemWeight )); diff --git a/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java b/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java index 9db777d..40bc2c7 100644 --- a/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java +++ b/StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java @@ -162,11 +162,11 @@ public class DungeonPack { excludedDungeons = new HashSet(history); } - + //List which dungeons are allowed ArrayList candidates; ArrayList group = groupedDungeons.get(nextType.ID); - if (excludedDungeons != null) + if (excludedDungeons != null && !excludedDungeons.isEmpty()) { candidates = new ArrayList(group.size()); for (DungeonGenerator dungeon : group) diff --git a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java index c364297..372979d 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java @@ -9,7 +9,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.Random; import java.util.regex.Pattern; @@ -423,32 +425,72 @@ public class DungeonHelper //manipulate the output of this function by setting up links to mislead our algorithm or by removing links. //Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi - dimHelper helper = dimHelper.instance; ArrayList history = new ArrayList(); - DimData tailDim = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID); + DimData tailDim = dimData; + boolean found = true; - for (int count = 0; count < maxSize; count++) + if (dimData.dungeonGenerator == null || dimData.dungeonGenerator.getDungeonType().Owner != pack || maxSize < 1) { - if (tailDim.dungeonGenerator == null || tailDim.dungeonGenerator.getDungeonType().Owner != pack) + //The initial dimension is already outside our pack. Return an empty list. + return history; + } + history.add(dimData.dungeonGenerator); + + for (int count = 1; count < maxSize && found; count++) + { + found = false; + for (LinkData link : tailDim.getLinksInDim()) { - //We've reached a dimension that doesn't belong to our pack. Stop the search here. - break; - } - - history.add(tailDim.dungeonGenerator); - if (count + 1 < maxSize) - { - for (LinkData link : tailDim.getLinksInDim()) + DimData neighbor = dimHelper.instance.getDimData(link.destDimID); + if (neighbor.depth == tailDim.depth - 1 && neighbor.dungeonGenerator != null && + neighbor.dungeonGenerator.getDungeonType().Owner == pack) { - DimData nextDim = dimHelper.instance.getDimData(link.destDimID); - if (helper.getDimDepth(link.destDimID) == tailDim.depth + 1) - { - tailDim = nextDim; - break; - } + tailDim = neighbor; + history.add(tailDim.dungeonGenerator); + found = true; + break; } } } return history; } + + public static ArrayList getFlatDungeonTree(DimData dimData, int maxSize) + { + //TODO: I've improved this code for the time being. However, searching across links is a flawed approach. A player could + //manipulate the output of this function by setting up links to mislead our algorithm or by removing links. + //Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi + + dimHelper helper = dimHelper.instance; + ArrayList dungeons = new ArrayList(); + DimData root = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID); + HashSet checked = new HashSet(); + Queue pendingDimensions = new LinkedList(); + + if (root.dungeonGenerator == null) + { + return dungeons; + } + pendingDimensions.add(root); + checked.add(root); + + while (dungeons.size() < maxSize && !pendingDimensions.isEmpty()) + { + DimData current = pendingDimensions.remove(); + for (LinkData link : current.getLinksInDim()) + { + DimData child = helper.getDimData(link.destDimID); + if (child.depth == current.depth + 1 && child.dungeonGenerator != null && checked.add(child)) + { + dungeons.add(child.dungeonGenerator); + pendingDimensions.add(child); + } + if (dungeons.size() == maxSize) + { + break; + } + } + } + return dungeons; + } } \ No newline at end of file diff --git a/StevenDimDoors/mod_pocketDim/util/BaseConfigurationProcessor.java b/StevenDimDoors/mod_pocketDim/util/BaseConfigurationProcessor.java new file mode 100644 index 0000000..8fe75a2 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/util/BaseConfigurationProcessor.java @@ -0,0 +1,52 @@ +package StevenDimDoors.mod_pocketDim.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +public abstract class BaseConfigurationProcessor +{ + public BaseConfigurationProcessor() { } + + public boolean canRead() + { + return true; + } + + public boolean canWrite() + { + return true; + } + + public T readFromFile(String path) throws FileNotFoundException, ConfigurationProcessingException + { + return readFromFile(new File(path)); + } + + public T readFromFile(File file) throws FileNotFoundException, ConfigurationProcessingException + { + return readFromStream(new FileInputStream(file)); + } + + public T readFromResource(String resourcePath) throws ConfigurationProcessingException + { + return readFromStream(this.getClass().getResourceAsStream(resourcePath)); + } + + public abstract T readFromStream(InputStream inputStream) throws ConfigurationProcessingException; + + public void writeToFile(File file, T data) throws FileNotFoundException, ConfigurationProcessingException + { + writeToStream(new FileOutputStream(file), data); + } + + public void writeToFile(String path, T data) throws FileNotFoundException, ConfigurationProcessingException + { + writeToFile(new File(path), data); + } + + public abstract void writeToStream(OutputStream outputStream, T data) throws ConfigurationProcessingException; +} diff --git a/StevenDimDoors/mod_pocketDim/util/ConfigurationProcessingException.java b/StevenDimDoors/mod_pocketDim/util/ConfigurationProcessingException.java new file mode 100644 index 0000000..1793f22 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/util/ConfigurationProcessingException.java @@ -0,0 +1,21 @@ +package StevenDimDoors.mod_pocketDim.util; + +public class ConfigurationProcessingException extends Exception +{ + private static final long serialVersionUID = -4525298050874891911L; + + public ConfigurationProcessingException() + { + super(); + } + + public ConfigurationProcessingException(String message) + { + super(message); + } + + public ConfigurationProcessingException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/schematics/ruins/rules.txt b/schematics/ruins/rules.txt new file mode 100644 index 0000000..086036a --- /dev/null +++ b/schematics/ruins/rules.txt @@ -0,0 +1,33 @@ +Version 1 +Types: +Hub +Trap +SimpleHall +ComplexHall +Exit +DeadEnd +Maze + +Settings: +AllowRepetitionsInBranch = false +AllowPackChangeOut = true +AllowPackChangeIn = true +PackWeight = 100 + +Rules: + +Exit -> DeadEnd Exit + +DeadEnd -> DeadEnd Exit + +? ? ? ? ? ? ? ? -> Trap#20 SimpleHall#40 ComplexHall#10 Exit#20 DeadEnd#10 + +? ? ? ? -> Trap#18 SimpleHall#40 ComplexHall#10 Exit#18 DeadEnd#10 Hub#4 + +? ? ? -> ComplexHall Hub Trap SimpleHall Maze + +? ? -> ComplexHall Hub Trap SimpleHall Maze + +? -> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10 + +-> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10 \ No newline at end of file