Basic Configurable Dungeon Chains
Completed a basic version of configurable dungeon chains. Almost all of the final funcionality is present. However, the configuration is hardcoded at the moment, not read from a file. This was done for testing purposes. I'll add reading from config files soon. Dungeon packs are partially implemented. Built-in and custom dungeons are currently thrown into the default pack, Ruins. The next step is to generalize the dungeon registration code in DungeonHelper so that we can detect dungeon packs, read their config files, and register dungeons with their corresponding pack. dd-export will need to support packs as well. dd-rift will have issues dealing with duplicate dungeon names across packs, but this isn't a major concern and can be dealt with in the long term.
This commit is contained in:
parent
35329f9024
commit
f372b9ccb5
7 changed files with 180 additions and 28 deletions
|
@ -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 ));
|
||||
|
|
|
@ -162,11 +162,11 @@ public class DungeonPack
|
|||
{
|
||||
excludedDungeons = new HashSet<DungeonGenerator>(history);
|
||||
}
|
||||
|
||||
|
||||
//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)
|
||||
//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<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
|
Loading…
Reference in a new issue