Partial Dungeon Pack and Configurable Dungeon Chain Implementation #67
@@ -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);
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@ public class DungeonChainRule
|
||||
ArrayList<String> conditionNames = source.getCondition();
|
||||
ArrayList<WeightedContainer<String>> 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<WeightedContainer<DungeonType>>();
|
||||
products = new ArrayList<WeightedContainer<DungeonType>>(productNames.size());
|
||||
for (WeightedContainer<String> product : productNames)
|
||||
{
|
||||
products.add(new WeightedContainer<DungeonType>(nameToTypeMapping.get(product.getData()), product.itemWeight ));
|
||||
|
||||
@@ -166,7 +166,7 @@ public class DungeonPack
|
||||
//List which dungeons are allowed
|
||||
ArrayList<DungeonGenerator> candidates;
|
||||
ArrayList<DungeonGenerator> group = groupedDungeons.get(nextType.ID);
|
||||
if (excludedDungeons != null)
|
||||
if (excludedDungeons != null && !excludedDungeons.isEmpty())
|
||||
{
|
||||
candidates = new ArrayList<DungeonGenerator>(group.size());
|
||||
for (DungeonGenerator dungeon : group)
|
||||
|
||||
@@ -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<DungeonGenerator> history = new ArrayList<DungeonGenerator>();
|
||||
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)
|
||||
{
|
||||
//We've reached a dimension that doesn't belong to our pack. Stop the search here.
|
||||
break;
|
||||
//The initial dimension is already outside our pack. Return an empty list.
|
||||
return history;
|
||||
}
|
||||
history.add(dimData.dungeonGenerator);
|
||||
|
||||
history.add(tailDim.dungeonGenerator);
|
||||
if (count + 1 < maxSize)
|
||||
for (int count = 1; count < maxSize && found; count++)
|
||||
{
|
||||
found = false;
|
||||
for (LinkData link : tailDim.getLinksInDim())
|
||||
{
|
||||
DimData nextDim = dimHelper.instance.getDimData(link.destDimID);
|
||||
if (helper.getDimDepth(link.destDimID) == tailDim.depth + 1)
|
||||
DimData neighbor = dimHelper.instance.getDimData(link.destDimID);
|
||||
if (neighbor.depth == tailDim.depth - 1 && neighbor.dungeonGenerator != null &&
|
||||
neighbor.dungeonGenerator.getDungeonType().Owner == pack)
|
||||
{
|
||||
tailDim = nextDim;
|
||||
tailDim = neighbor;
|
||||
history.add(tailDim.dungeonGenerator);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return history;
|
||||
}
|
||||
|
||||
public static ArrayList<DungeonGenerator> 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<DungeonGenerator> dungeons = new ArrayList<DungeonGenerator>();
|
||||
DimData root = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID);
|
||||
HashSet<DimData> checked = new HashSet<DimData>();
|
||||
Queue<DimData> pendingDimensions = new LinkedList<DimData>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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<T>
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
33
schematics/ruins/rules.txt
Normal file
33
schematics/ruins/rules.txt
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user