Partial Dungeon Pack and Configurable Dungeon Chain Implementation #67
@@ -1,14 +1,22 @@
|
|||||||
package StevenDimDoors.mod_pocketDim;
|
package StevenDimDoors.mod_pocketDim;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||||
|
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class DungeonGenerator implements Serializable
|
public class DungeonGenerator implements Serializable
|
||||||
{
|
{
|
||||||
|
//This static field is hax so that I don't have to add an instance field to DungeonGenerator to support DungeonType.
|
||||||
|
//Otherwise it would have to be serializable and all sorts of problems would arise.
|
||||||
|
private static final HashMap<DungeonGenerator, DungeonType> dungeonTypes = new HashMap<DungeonGenerator, DungeonType>();
|
||||||
|
|
||||||
public int weight;
|
public int weight;
|
||||||
public String schematicPath;
|
public String schematicPath;
|
||||||
public ArrayList<HashMap> sideRifts = new ArrayList<HashMap>();
|
public ArrayList<HashMap> sideRifts = new ArrayList<HashMap>();
|
||||||
@@ -19,10 +27,54 @@ public class DungeonGenerator implements Serializable
|
|||||||
public int exitDoorsSoFar=0;
|
public int exitDoorsSoFar=0;
|
||||||
public int deadEndsSoFar=0;
|
public int deadEndsSoFar=0;
|
||||||
|
|
||||||
public DungeonGenerator(int weight, String schematicPath, Boolean isOpen)
|
public DungeonGenerator(int weight, String schematicPath, boolean isOpen, DungeonType dungeonType)
|
||||||
{
|
{
|
||||||
this.weight=weight;
|
this.weight = weight;
|
||||||
this.schematicPath=schematicPath;
|
this.schematicPath = schematicPath;
|
||||||
this.isOpen=isOpen;
|
this.isOpen = isOpen;
|
||||||
|
|
||||||
|
dungeonTypes.put(this, dungeonType); //Hax...
|
||||||
|
}
|
||||||
|
|
||||||
|
public DungeonType getDungeonType()
|
||||||
|
{
|
||||||
|
DungeonType type = dungeonTypes.get(this);
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
//Infer the dungeon's type from its file name
|
||||||
|
//There is minimal risk of us applying this to untagged dungeons and this'll be phased out
|
||||||
|
//when we get the new save format.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File file = new File(schematicPath);
|
||||||
|
String typeName = file.getName().split("_")[0];
|
||||||
|
type = DungeonHelper.instance().RuinsPack.getType(typeName);
|
||||||
|
}
|
||||||
|
catch (Exception e) { }
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
type = DungeonType.UNKNOWN_TYPE;
|
||||||
|
}
|
||||||
|
dungeonTypes.put(this, type);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return (schematicPath != null) ? schematicPath.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other)
|
||||||
|
{
|
||||||
|
return equals((DungeonGenerator) other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(DungeonGenerator other)
|
||||||
|
{
|
||||||
|
return ((this.schematicPath != null && this.schematicPath.equals(other.schematicPath)) ||
|
||||||
|
(this.schematicPath == other.schematicPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,7 @@ public class SchematicLoader
|
|||||||
int originDimID = link.locDimID;
|
int originDimID = link.locDimID;
|
||||||
int destDimID = link.destDimID;
|
int destDimID = link.destDimID;
|
||||||
HashMap<Integer, DimData> dimList = dimHelper.dimList;
|
HashMap<Integer, DimData> dimList = dimHelper.dimList;
|
||||||
|
DungeonHelper dungeonHelper = DungeonHelper.instance();
|
||||||
World world;
|
World world;
|
||||||
|
|
||||||
if (dimList.containsKey(destDimID))
|
if (dimList.containsKey(destDimID))
|
||||||
@@ -49,8 +50,7 @@ public class SchematicLoader
|
|||||||
long factorB = random.nextLong() / 2L * 2L + 1L;
|
long factorB = random.nextLong() / 2L * 2L + 1L;
|
||||||
random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ world.getSeed());
|
random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ world.getSeed());
|
||||||
|
|
||||||
//TODO: FIX THIS LINE OR SADNESS WILL FOLLOW. Add a reference to the dungeon pack.
|
dungeonHelper.generateDungeonLink(link, dungeonHelper.RuinsPack, random);
|
||||||
//DungeonHelper.instance().generateDungeonLink(link, ???, random);
|
|
||||||
}
|
}
|
||||||
schematicPath = dimList.get(destDimID).dungeonGenerator.schematicPath;
|
schematicPath = dimList.get(destDimID).dungeonGenerator.schematicPath;
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ public class SchematicLoader
|
|||||||
//TODO: In the future, remove this dungeon from the generation lists altogether.
|
//TODO: In the future, remove this dungeon from the generation lists altogether.
|
||||||
//That will have to wait until our code is updated to support that more easily.
|
//That will have to wait until our code is updated to support that more easily.
|
||||||
System.err.println("The dungeon will not be loaded.");
|
System.err.println("The dungeon will not be loaded.");
|
||||||
DungeonGenerator defaultError = DungeonHelper.instance().getDefaultErrorDungeon();
|
DungeonGenerator defaultError = dungeonHelper.getDefaultErrorDungeon();
|
||||||
dimList.get(destDimID).dungeonGenerator = defaultError;
|
dimList.get(destDimID).dungeonGenerator = defaultError;
|
||||||
dungeon = checkSourceAndLoad(defaultError.schematicPath);
|
dungeon = checkSourceAndLoad(defaultError.schematicPath);
|
||||||
dungeon.applyImportFilters(properties);
|
dungeon.applyImportFilters(properties);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class CommandExportDungeon extends DDCommandBase
|
|||||||
if (command[1].equalsIgnoreCase("override"))
|
if (command[1].equalsIgnoreCase("override"))
|
||||||
{
|
{
|
||||||
//Check that the schematic name is a legal name
|
//Check that the schematic name is a legal name
|
||||||
if (DungeonHelper.SchematicNamePattern.matcher(command[0]).matches())
|
if (DungeonHelper.SCHEMATIC_NAME_PATTERN.matcher(command[0]).matches())
|
||||||
{
|
{
|
||||||
//Export the schematic
|
//Export the schematic
|
||||||
return exportDungeon(sender, command[0]);
|
return exportDungeon(sender, command[0]);
|
||||||
@@ -85,7 +85,7 @@ public class CommandExportDungeon extends DDCommandBase
|
|||||||
{
|
{
|
||||||
return new DDCommandResult("Error: Invalid dungeon type. Please use one of the existing types.");
|
return new DDCommandResult("Error: Invalid dungeon type. Please use one of the existing types.");
|
||||||
}
|
}
|
||||||
if (!DungeonHelper.DungeonNamePattern.matcher(command[1]).matches())
|
if (!DungeonHelper.DUNGEON_NAME_PATTERN.matcher(command[1]).matches())
|
||||||
{
|
{
|
||||||
return new DDCommandResult("Error: Invalid dungeon name. Please use only letters, numbers, and dashes.");
|
return new DDCommandResult("Error: Invalid dungeon name. Please use only letters, numbers, and dashes.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,66 @@
|
|||||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||||
|
|
||||||
public class DungeonChainRule
|
public class DungeonChainRule
|
||||||
{
|
{
|
||||||
|
private final int[] condition;
|
||||||
|
private final ArrayList<WeightedContainer<DungeonType>> products;
|
||||||
|
|
||||||
public OptimizedRule optimize(HashMap<String, DungeonType> nameToTypeMapping) {
|
public DungeonChainRule(DungeonChainRuleDefinition source, HashMap<String, DungeonType> nameToTypeMapping)
|
||||||
// TODO Auto-generated method stub
|
{
|
||||||
return null;
|
ArrayList<String> conditionNames = source.getCondition();
|
||||||
|
ArrayList<WeightedContainer<String>> productNames = source.getProducts();
|
||||||
|
|
||||||
|
condition = new int[conditionNames.size()];
|
||||||
|
for (int k = 0; k < condition.length; k++)
|
||||||
|
{
|
||||||
|
condition[k] = nameToTypeMapping.get(conditionNames.get(k)).ID;
|
||||||
|
}
|
||||||
|
products = new ArrayList<WeightedContainer<DungeonType>>();
|
||||||
|
for (WeightedContainer<String> product : productNames)
|
||||||
|
{
|
||||||
|
products.add(new WeightedContainer<DungeonType>(nameToTypeMapping.get(product.getData()), product.itemWeight ));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int length()
|
||||||
|
{
|
||||||
|
return condition.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean evaluate(int[] typeHistory)
|
||||||
|
{
|
||||||
|
if (typeHistory.length >= condition.length)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < condition.length; k++)
|
||||||
|
{
|
||||||
|
if (condition[k] != 0 && typeHistory[k] != condition[k])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<WeightedContainer<DungeonType>> products()
|
||||||
|
{
|
||||||
|
//Create a deep copy of the internal list of products. That way, if the list is modified externally,
|
||||||
|
//it won't affect the reference copy inside this rule.
|
||||||
|
ArrayList<WeightedContainer<DungeonType>> copy = new ArrayList<WeightedContainer<DungeonType>>(products.size());
|
||||||
|
for (WeightedContainer<DungeonType> container : products)
|
||||||
|
{
|
||||||
|
copy.add(container.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import net.minecraft.util.WeightedRandom;
|
import net.minecraft.util.WeightedRandom;
|
||||||
@@ -16,9 +15,11 @@ import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
|||||||
|
|
||||||
public class DungeonPack
|
public class DungeonPack
|
||||||
{
|
{
|
||||||
//Why final? I just felt like it, honestly. ~SenseiKiwi
|
//There is no precaution against having a dungeon type removed from a config file after dungeons of that type
|
||||||
|
//have been generated. That would likely cause one or two problems. It's hard to guard against when I don't know
|
||||||
private static final DungeonType WILDCARD_TYPE = new DungeonType(null, "?", 0);
|
//what the save format will be like completely. How should this class behave if it finds a "disowned" type?
|
||||||
|
//The ID numbers would be a problem since it couldn't have a valid number, since it wasn't initialized by the pack instance.
|
||||||
|
//FIXME: Do not release this code as an update without dealing with disowned types!
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final HashMap<String, DungeonType> nameToTypeMapping;
|
private final HashMap<String, DungeonType> nameToTypeMapping;
|
||||||
@@ -26,7 +27,7 @@ public class DungeonPack
|
|||||||
private final ArrayList<DungeonGenerator> allDungeons;
|
private final ArrayList<DungeonGenerator> allDungeons;
|
||||||
private final DungeonPackConfig config;
|
private final DungeonPackConfig config;
|
||||||
private final int maxRuleLength;
|
private final int maxRuleLength;
|
||||||
private final ArrayList<OptimizedRule> rules;
|
private final ArrayList<DungeonChainRule> rules;
|
||||||
|
|
||||||
public DungeonPack(DungeonPackConfig config)
|
public DungeonPack(DungeonPackConfig config)
|
||||||
{
|
{
|
||||||
@@ -42,7 +43,7 @@ public class DungeonPack
|
|||||||
this.groupedDungeons = new ArrayList<ArrayList<DungeonGenerator>>(typeCount);
|
this.groupedDungeons = new ArrayList<ArrayList<DungeonGenerator>>(typeCount);
|
||||||
|
|
||||||
this.groupedDungeons.add(allDungeons); //Make sure the list of all dungeons is placed at index 0
|
this.groupedDungeons.add(allDungeons); //Make sure the list of all dungeons is placed at index 0
|
||||||
this.nameToTypeMapping.put(WILDCARD_TYPE.Name, WILDCARD_TYPE);
|
this.nameToTypeMapping.put(DungeonType.WILDCARD_TYPE.Name, DungeonType.WILDCARD_TYPE);
|
||||||
|
|
||||||
index = 1;
|
index = 1;
|
||||||
for (String typeName : config.getTypeNames())
|
for (String typeName : config.getTypeNames())
|
||||||
@@ -53,22 +54,23 @@ public class DungeonPack
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Construct optimized rules from config rules
|
//Construct optimized rules from definitions
|
||||||
ArrayList<DungeonChainRule> chainRules = config.getRules();
|
ArrayList<DungeonChainRuleDefinition> definitions = config.getRules();
|
||||||
this.rules = new ArrayList<OptimizedRule>(chainRules.size());
|
this.rules = new ArrayList<DungeonChainRule>(definitions.size());
|
||||||
for (DungeonChainRule rule : chainRules)
|
for (DungeonChainRuleDefinition definition : definitions)
|
||||||
{
|
{
|
||||||
OptimizedRule optimized = rule.optimize(nameToTypeMapping);
|
DungeonChainRule rule = new DungeonChainRule(definition, nameToTypeMapping);
|
||||||
this.rules.add(optimized);
|
this.rules.add(rule);
|
||||||
if (maxLength < optimized.length())
|
if (maxLength < rule.length())
|
||||||
{
|
{
|
||||||
maxLength = optimized.length();
|
maxLength = rule.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.maxRuleLength = maxLength;
|
this.maxRuleLength = maxLength;
|
||||||
|
|
||||||
//Remove the reference to the non-optimized rules to free up memory - we won't need them here
|
//Remove unnecessary references to save a little memory - we won't need them here
|
||||||
this.config.setRules(null);
|
this.config.setRules(null);
|
||||||
|
this.config.setTypeNames(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
@@ -84,7 +86,7 @@ public class DungeonPack
|
|||||||
public DungeonType getType(String typeName)
|
public DungeonType getType(String typeName)
|
||||||
{
|
{
|
||||||
DungeonType result = nameToTypeMapping.get(typeName.toUpperCase());
|
DungeonType result = nameToTypeMapping.get(typeName.toUpperCase());
|
||||||
if (result != WILDCARD_TYPE)
|
if (result.Owner == this) //Filter out the wildcard dungeon type
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -99,6 +101,21 @@ public class DungeonPack
|
|||||||
return (this.getType(typeName) != null);
|
return (this.getType(typeName) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDungeon(DungeonGenerator generator)
|
||||||
|
{
|
||||||
|
//Make sure this dungeon really belongs in this pack
|
||||||
|
DungeonType type = generator.getDungeonType();
|
||||||
|
if (type.Owner == this)
|
||||||
|
{
|
||||||
|
allDungeons.add(generator);
|
||||||
|
groupedDungeons.get(type.ID).add(generator);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("The dungeon type of generator must belong to this instance of DungeonPack.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public DungeonGenerator getNextDungeon(LinkData inbound, Random random)
|
public DungeonGenerator getNextDungeon(LinkData inbound, Random random)
|
||||||
{
|
{
|
||||||
if (allDungeons.isEmpty())
|
if (allDungeons.isEmpty())
|
||||||
@@ -106,12 +123,14 @@ public class DungeonPack
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Retrieve a list of the previous dungeons in this chain. Restrict the length of the
|
//Retrieve a list of the previous dungeons in this chain.
|
||||||
//search to the length of the longest rule. Getting more data is useless.
|
//If we're not going to check for duplicates in chains, restrict the length of the history to the length
|
||||||
dimHelper helper = dimHelper.instance;
|
//of the longest rule we have. Getting any more data would be useless. This optimization could be significant
|
||||||
|
//for dungeon packs that can extend arbitrarily deep. We should probably set a reasonable limit anyway.
|
||||||
|
|
||||||
//TODO: Add dungeon pack parameter! We can't use dungeon types from other packs.
|
int maxSearchLength = config.allowDuplicatesInChain() ? maxRuleLength : 1337;
|
||||||
ArrayList<DungeonGenerator> history = DungeonHelper.getDungeonChainHistory(helper.getDimData(inbound.locDimID), maxRuleLength);
|
ArrayList<DungeonGenerator> history = DungeonHelper.getDungeonChainHistory(
|
||||||
|
dimHelper.instance.getDimData(inbound.locDimID), this, maxSearchLength);
|
||||||
return getNextDungeon(history, random);
|
return getNextDungeon(history, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,10 +142,10 @@ public class DungeonPack
|
|||||||
HashSet<DungeonGenerator> excludedDungeons = null;
|
HashSet<DungeonGenerator> excludedDungeons = null;
|
||||||
for (index = 0; index < typeHistory.length; index++)
|
for (index = 0; index < typeHistory.length; index++)
|
||||||
{
|
{
|
||||||
typeHistory[index] = getDungeonType(history.get(index)).ID;
|
typeHistory[index] = history.get(index).getDungeonType().ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (OptimizedRule rule : rules)
|
for (DungeonChainRule rule : rules)
|
||||||
{
|
{
|
||||||
if (rule.evaluate(typeHistory))
|
if (rule.evaluate(typeHistory))
|
||||||
{
|
{
|
||||||
@@ -139,9 +158,9 @@ public class DungeonPack
|
|||||||
if (nextType != null)
|
if (nextType != null)
|
||||||
{
|
{
|
||||||
//Initialize the set of excluded dungeons if needed
|
//Initialize the set of excluded dungeons if needed
|
||||||
if (excludedDungeons == null && config.allowDuplicatesInChain())
|
if (excludedDungeons == null && !config.allowDuplicatesInChain())
|
||||||
{
|
{
|
||||||
//TODO: Finish implementing this!
|
excludedDungeons = new HashSet<DungeonGenerator>(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
//List which dungeons are allowed
|
//List which dungeons are allowed
|
||||||
@@ -166,6 +185,8 @@ public class DungeonPack
|
|||||||
{
|
{
|
||||||
return getRandomDungeon(random, candidates);
|
return getRandomDungeon(random, candidates);
|
||||||
}
|
}
|
||||||
|
//If we've reached this point, then a dungeon was not selected. Discard the type and try again.
|
||||||
|
products.remove(nextType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (nextType != null);
|
while (nextType != null);
|
||||||
@@ -176,16 +197,6 @@ public class DungeonPack
|
|||||||
return getRandomDungeon(random);
|
return getRandomDungeon(random);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DungeonType getDungeonType(DungeonGenerator generator)
|
|
||||||
{
|
|
||||||
//This function is a workaround for DungeonGenerator not having a dungeon type or pack field.
|
|
||||||
//I really don't want to go messing around with that serializable type.
|
|
||||||
//TODO: Remove this function once we transition to using the new save format. ~SenseiKiwi
|
|
||||||
|
|
||||||
//TODO: Finish implementing this!
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DungeonGenerator getRandomDungeon(Random random)
|
public DungeonGenerator getRandomDungeon(Random random)
|
||||||
{
|
{
|
||||||
if (!allDungeons.isEmpty())
|
if (!allDungeons.isEmpty())
|
||||||
@@ -202,7 +213,7 @@ public class DungeonPack
|
|||||||
ArrayList<ArrayList<DungeonGenerator>> groupedDungeons)
|
ArrayList<ArrayList<DungeonGenerator>> groupedDungeons)
|
||||||
{
|
{
|
||||||
//TODO: Make this faster? This algorithm runs in quadratic time in the worst case because of the random-selection
|
//TODO: Make this faster? This algorithm runs in quadratic time in the worst case because of the random-selection
|
||||||
//process and the removal search. Should be okay for normal use, though. ~SenseiKiwi
|
//process and the removal search. Might be okay for normal use, though. ~SenseiKiwi
|
||||||
|
|
||||||
//Pick a random dungeon type based on weights. Repeat this process until a non-empty group is found or all groups are checked.
|
//Pick a random dungeon type based on weights. Repeat this process until a non-empty group is found or all groups are checked.
|
||||||
while (!types.isEmpty())
|
while (!types.isEmpty())
|
||||||
|
|||||||
@@ -1,22 +1,36 @@
|
|||||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DungeonPackConfig
|
public class DungeonPackConfig
|
||||||
{
|
{
|
||||||
|
private String name;
|
||||||
|
private ArrayList<String> typeNames;
|
||||||
|
private boolean allowDuplicatesInChain;
|
||||||
|
private ArrayList<DungeonChainRuleDefinition> rules;
|
||||||
|
|
||||||
public DungeonPackConfig() { }
|
public DungeonPackConfig() { }
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private DungeonPackConfig(DungeonPackConfig source)
|
private DungeonPackConfig(DungeonPackConfig source)
|
||||||
{
|
{
|
||||||
|
this.name = source.name;
|
||||||
|
this.typeNames = (ArrayList<String>) source.typeNames.clone();
|
||||||
|
this.allowDuplicatesInChain = source.allowDuplicatesInChain;
|
||||||
|
this.rules = (ArrayList<DungeonChainRuleDefinition>) source.rules.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validate()
|
public void validate()
|
||||||
{
|
{
|
||||||
|
if (this.name == null)
|
||||||
|
throw new NullPointerException("name cannot be null");
|
||||||
|
if (this.typeNames == null)
|
||||||
|
throw new NullPointerException("typeNames cannot be null");
|
||||||
|
if (this.rules == null)
|
||||||
|
throw new NullPointerException("rules cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DungeonPackConfig clone()
|
public DungeonPackConfig clone()
|
||||||
{
|
{
|
||||||
return new DungeonPackConfig(this);
|
return new DungeonPackConfig(this);
|
||||||
@@ -24,26 +38,41 @@ public class DungeonPackConfig
|
|||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
return null;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getTypeNames()
|
public void setName(String name)
|
||||||
{
|
{
|
||||||
return null;
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getTypeNames()
|
||||||
|
{
|
||||||
|
return typeNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeNames(ArrayList<String> typeNames)
|
||||||
|
{
|
||||||
|
this.typeNames = typeNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allowDuplicatesInChain()
|
public boolean allowDuplicatesInChain()
|
||||||
{
|
{
|
||||||
return false;
|
return allowDuplicatesInChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRules(Object object) {
|
public void setAllowDuplicatesInChain(boolean value)
|
||||||
// TODO Auto-generated method stub
|
{
|
||||||
|
allowDuplicatesInChain = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<DungeonChainRule> getRules() {
|
public void setRules(ArrayList<DungeonChainRuleDefinition> rules)
|
||||||
// TODO Auto-generated method stub
|
{
|
||||||
return null;
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<DungeonChainRuleDefinition> getRules()
|
||||||
|
{
|
||||||
|
return rules;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
|||||||
|
|
||||||
public class DungeonType implements Comparable<DungeonType>
|
public class DungeonType implements Comparable<DungeonType>
|
||||||
{
|
{
|
||||||
|
public static final DungeonType WILDCARD_TYPE = new DungeonType(null, "?", 0);
|
||||||
|
public static final DungeonType UNKNOWN_TYPE = new DungeonType(null, "!", -1);
|
||||||
|
|
||||||
public final DungeonPack Owner;
|
public final DungeonPack Owner;
|
||||||
public final String Name;
|
public final String Name;
|
||||||
public final int ID;
|
public final int ID;
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
|
||||||
|
|
||||||
public class OptimizedRule
|
|
||||||
{
|
|
||||||
|
|
||||||
public int length() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean evaluate(int[] typeHistory) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<WeightedContainer<DungeonType>> products() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -5,9 +5,9 @@ import java.io.File;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -20,15 +20,20 @@ import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
|||||||
import StevenDimDoors.mod_pocketDim.LinkData;
|
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonChainRuleDefinition;
|
||||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPackConfig;
|
||||||
|
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||||
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||||
|
|
||||||
public class DungeonHelper
|
public class DungeonHelper
|
||||||
{
|
{
|
||||||
private static DungeonHelper instance = null;
|
private static DungeonHelper instance = null;
|
||||||
private static DDProperties properties = null;
|
private static DDProperties properties = null;
|
||||||
public static final Pattern SchematicNamePattern = Pattern.compile("[A-Za-z0-9_\\-]+");
|
|
||||||
public static final Pattern DungeonNamePattern = Pattern.compile("[A-Za-z0-9\\-]+");
|
public static final Pattern SCHEMATIC_NAME_PATTERN = Pattern.compile("[A-Za-z0-9_\\-]+");
|
||||||
|
public static final Pattern DUNGEON_NAME_PATTERN = Pattern.compile("[A-Za-z0-9\\-]+");
|
||||||
|
|
||||||
private static final String DEFAULT_UP_SCHEMATIC_PATH = "/schematics/core/simpleStairsUp.schematic";
|
private static final String DEFAULT_UP_SCHEMATIC_PATH = "/schematics/core/simpleStairsUp.schematic";
|
||||||
private static final String DEFAULT_DOWN_SCHEMATIC_PATH = "/schematics/core/simpleStairsDown.schematic";
|
private static final String DEFAULT_DOWN_SCHEMATIC_PATH = "/schematics/core/simpleStairsDown.schematic";
|
||||||
@@ -44,70 +49,22 @@ public class DungeonHelper
|
|||||||
public static final short MAX_DUNGEON_HEIGHT = MAX_DUNGEON_WIDTH;
|
public static final short MAX_DUNGEON_HEIGHT = MAX_DUNGEON_WIDTH;
|
||||||
public static final short MAX_DUNGEON_LENGTH = MAX_DUNGEON_WIDTH;
|
public static final short MAX_DUNGEON_LENGTH = MAX_DUNGEON_WIDTH;
|
||||||
|
|
||||||
private static final String HUB_DUNGEON_TYPE = "Hub";
|
|
||||||
private static final String TRAP_DUNGEON_TYPE = "Trap";
|
|
||||||
private static final String SIMPLE_HALL_DUNGEON_TYPE = "SimpleHall";
|
|
||||||
private static final String COMPLEX_HALL_DUNGEON_TYPE = "ComplexHall";
|
|
||||||
private static final String EXIT_DUNGEON_TYPE = "Exit";
|
|
||||||
private static final String DEAD_END_DUNGEON_TYPE = "DeadEnd";
|
|
||||||
private static final String MAZE_DUNGEON_TYPE = "Maze";
|
|
||||||
|
|
||||||
//The list of dungeon types will be kept as an array for now. If we allow new
|
|
||||||
//dungeon types in the future, then this can be changed to an ArrayList.
|
|
||||||
private static final String[] DUNGEON_TYPES = new String[] {
|
|
||||||
HUB_DUNGEON_TYPE,
|
|
||||||
TRAP_DUNGEON_TYPE,
|
|
||||||
SIMPLE_HALL_DUNGEON_TYPE,
|
|
||||||
COMPLEX_HALL_DUNGEON_TYPE,
|
|
||||||
EXIT_DUNGEON_TYPE,
|
|
||||||
DEAD_END_DUNGEON_TYPE,
|
|
||||||
MAZE_DUNGEON_TYPE
|
|
||||||
};
|
|
||||||
|
|
||||||
private ArrayList<DungeonGenerator> untaggedDungeons = new ArrayList<DungeonGenerator>();
|
private ArrayList<DungeonGenerator> untaggedDungeons = new ArrayList<DungeonGenerator>();
|
||||||
private ArrayList<DungeonGenerator> registeredDungeons = new ArrayList<DungeonGenerator>();
|
private ArrayList<DungeonGenerator> registeredDungeons = new ArrayList<DungeonGenerator>();
|
||||||
|
|
||||||
private ArrayList<DungeonGenerator> simpleHalls = new ArrayList<DungeonGenerator>();
|
public DungeonPack RuinsPack;
|
||||||
private ArrayList<DungeonGenerator> complexHalls = new ArrayList<DungeonGenerator>();
|
|
||||||
private ArrayList<DungeonGenerator> deadEnds = new ArrayList<DungeonGenerator>();
|
|
||||||
private ArrayList<DungeonGenerator> hubs = new ArrayList<DungeonGenerator>();
|
|
||||||
private ArrayList<DungeonGenerator> mazes = new ArrayList<DungeonGenerator>();
|
|
||||||
private ArrayList<DungeonGenerator> pistonTraps = new ArrayList<DungeonGenerator>();
|
|
||||||
private ArrayList<DungeonGenerator> exits = new ArrayList<DungeonGenerator>();
|
|
||||||
|
|
||||||
private DungeonGenerator defaultUp;
|
private DungeonGenerator defaultUp;
|
||||||
private DungeonGenerator defaultDown;
|
private DungeonGenerator defaultDown;
|
||||||
private DungeonGenerator defaultError;
|
private DungeonGenerator defaultError;
|
||||||
|
|
||||||
private HashSet<String> dungeonTypeChecker;
|
|
||||||
private HashMap<String, ArrayList<DungeonGenerator>> dungeonTypeMapping;
|
|
||||||
|
|
||||||
private DungeonHelper()
|
private DungeonHelper()
|
||||||
{
|
{
|
||||||
//Load the dungeon type checker with the list of all types in lowercase.
|
|
||||||
//Capitalization matters for matching in a hash set.
|
|
||||||
dungeonTypeChecker = new HashSet<String>();
|
|
||||||
for (String dungeonType : DUNGEON_TYPES)
|
|
||||||
{
|
|
||||||
dungeonTypeChecker.add(dungeonType.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add all the basic dungeon types to dungeonTypeMapping
|
|
||||||
//Dungeon type names must be passed in lowercase to make matching easier.
|
|
||||||
dungeonTypeMapping = new HashMap<String, ArrayList<DungeonGenerator>>();
|
|
||||||
dungeonTypeMapping.put(SIMPLE_HALL_DUNGEON_TYPE.toLowerCase(), simpleHalls);
|
|
||||||
dungeonTypeMapping.put(COMPLEX_HALL_DUNGEON_TYPE.toLowerCase(), complexHalls);
|
|
||||||
dungeonTypeMapping.put(HUB_DUNGEON_TYPE.toLowerCase(), hubs);
|
|
||||||
dungeonTypeMapping.put(EXIT_DUNGEON_TYPE.toLowerCase(), exits);
|
|
||||||
dungeonTypeMapping.put(DEAD_END_DUNGEON_TYPE.toLowerCase(), deadEnds);
|
|
||||||
dungeonTypeMapping.put(MAZE_DUNGEON_TYPE.toLowerCase(), mazes);
|
|
||||||
dungeonTypeMapping.put(TRAP_DUNGEON_TYPE.toLowerCase(), pistonTraps);
|
|
||||||
|
|
||||||
//Load our reference to the DDProperties singleton
|
//Load our reference to the DDProperties singleton
|
||||||
if (properties == null)
|
if (properties == null)
|
||||||
properties = DDProperties.instance();
|
properties = DDProperties.instance();
|
||||||
|
|
||||||
registerCustomDungeons();
|
registerDungeons();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DungeonHelper initialize()
|
public static DungeonHelper initialize()
|
||||||
@@ -135,15 +92,67 @@ public class DungeonHelper
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCustomDungeons()
|
private void registerDungeons()
|
||||||
{
|
{
|
||||||
File file = new File(properties.CustomSchematicDirectory);
|
File file = new File(properties.CustomSchematicDirectory);
|
||||||
if (file.exists() || file.mkdir())
|
if (file.exists() || file.mkdir())
|
||||||
{
|
{
|
||||||
copyfile.copyFile(DUNGEON_CREATION_GUIDE_SOURCE_PATH, file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
copyfile.copyFile(DUNGEON_CREATION_GUIDE_SOURCE_PATH, file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuinsPack = new DungeonPack(createRuinsConfig());
|
||||||
|
|
||||||
registerBundledDungeons();
|
registerBundledDungeons();
|
||||||
importCustomDungeons(properties.CustomSchematicDirectory);
|
registerCustomDungeons(properties.CustomSchematicDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DungeonPackConfig createRuinsConfig()
|
||||||
|
{
|
||||||
|
//This is a temporarily function for testing dungeon packs.
|
||||||
|
//It'll be removed later when we read dungeon configurations from files.
|
||||||
|
|
||||||
|
ArrayList<DungeonChainRuleDefinition> rules = new ArrayList<DungeonChainRuleDefinition>();
|
||||||
|
rules.add(parseDefinitionUnsafe("? ? ? -> DeadEnd Exit"));
|
||||||
|
rules.add(parseDefinitionUnsafe("Trap -> ?"));
|
||||||
|
rules.add(parseDefinitionUnsafe("Hub -> Trap"));
|
||||||
|
rules.add(parseDefinitionUnsafe("? -> Hub"));
|
||||||
|
rules.add(parseDefinitionUnsafe("-> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10"));
|
||||||
|
|
||||||
|
String[] typeNames = "Hub Trap Maze Exit DeadEnd SimpleHall ComplexHall".toUpperCase().split(" ");
|
||||||
|
|
||||||
|
DungeonPackConfig config = new DungeonPackConfig();
|
||||||
|
config.setName("ruins");
|
||||||
|
config.setAllowDuplicatesInChain(false);
|
||||||
|
config.setRules(rules);
|
||||||
|
config.setTypeNames(new ArrayList<String>(Arrays.asList(typeNames)));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DungeonChainRuleDefinition parseDefinitionUnsafe(String definition)
|
||||||
|
{
|
||||||
|
//This is an improvised parsing function for rule definitions. Only for testing!!!
|
||||||
|
definition = definition.toUpperCase();
|
||||||
|
String[] parts = definition.split("->");
|
||||||
|
ArrayList<String> condition = new ArrayList<String>();
|
||||||
|
ArrayList<WeightedContainer<String>> products = new ArrayList<WeightedContainer<String>>();
|
||||||
|
|
||||||
|
for (String conditionPart : parts[0].split(" "))
|
||||||
|
{
|
||||||
|
if (!conditionPart.isEmpty())
|
||||||
|
condition.add(conditionPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String product : parts[1].split(" "))
|
||||||
|
{
|
||||||
|
if (!product.isEmpty())
|
||||||
|
{
|
||||||
|
String[] productParts = product.split("#");
|
||||||
|
String productType = productParts[0];
|
||||||
|
int weight = (productParts.length > 1) ? Integer.parseInt(productParts[1]) : 100;
|
||||||
|
products.add(new WeightedContainer<String>(productType, weight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new DungeonChainRuleDefinition(condition, products);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DungeonGenerator> getRegisteredDungeons()
|
public List<DungeonGenerator> getRegisteredDungeons()
|
||||||
@@ -186,7 +195,7 @@ public class DungeonHelper
|
|||||||
public boolean validateDungeonType(String type)
|
public boolean validateDungeonType(String type)
|
||||||
{
|
{
|
||||||
//Check if the dungeon type is valid
|
//Check if the dungeon type is valid
|
||||||
return dungeonTypeChecker.contains(type.toLowerCase());
|
return RuinsPack.isKnownType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateSchematicName(String name)
|
public boolean validateSchematicName(String name)
|
||||||
@@ -203,11 +212,11 @@ public class DungeonHelper
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Check if the dungeon type is valid
|
//Check if the dungeon type is valid
|
||||||
if (!dungeonTypeChecker.contains(dungeonData[0].toLowerCase()))
|
if (!validateDungeonType(dungeonData[0]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Check if the name is valid
|
//Check if the name is valid
|
||||||
if (!SchematicNamePattern.matcher(dungeonData[1]).matches())
|
if (!SCHEMATIC_NAME_PATTERN.matcher(dungeonData[1]).matches())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Check if the open/closed flag is present
|
//Check if the open/closed flag is present
|
||||||
@@ -246,14 +255,14 @@ public class DungeonHelper
|
|||||||
//Strip off the file extension while splitting the file name
|
//Strip off the file extension while splitting the file name
|
||||||
String[] dungeonData = name.substring(0, name.length() - SCHEMATIC_FILE_EXTENSION.length()).split("_");
|
String[] dungeonData = name.substring(0, name.length() - SCHEMATIC_FILE_EXTENSION.length()).split("_");
|
||||||
|
|
||||||
String dungeonType = dungeonData[0].toLowerCase();
|
DungeonType dungeonType = RuinsPack.getType(dungeonData[0]);
|
||||||
boolean isOpen = dungeonData[2].equalsIgnoreCase("open");
|
boolean isOpen = dungeonData[2].equalsIgnoreCase("open");
|
||||||
int weight = (dungeonData.length == 4) ? Integer.parseInt(dungeonData[3]) : DEFAULT_DUNGEON_WEIGHT;
|
int weight = (dungeonData.length == 4) ? Integer.parseInt(dungeonData[3]) : DEFAULT_DUNGEON_WEIGHT;
|
||||||
|
|
||||||
//Add this custom dungeon to the list corresponding to its type
|
//Add this custom dungeon to the list corresponding to its type
|
||||||
DungeonGenerator generator = new DungeonGenerator(weight, path, isOpen);
|
DungeonGenerator generator = new DungeonGenerator(weight, path, isOpen, dungeonType);
|
||||||
|
|
||||||
dungeonTypeMapping.get(dungeonType).add(generator);
|
RuinsPack.addDungeon(generator);
|
||||||
registeredDungeons.add(generator);
|
registeredDungeons.add(generator);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
@@ -266,7 +275,7 @@ public class DungeonHelper
|
|||||||
{
|
{
|
||||||
System.out.println("Could not parse dungeon filename, not adding dungeon to generation lists");
|
System.out.println("Could not parse dungeon filename, not adding dungeon to generation lists");
|
||||||
}
|
}
|
||||||
untaggedDungeons.add(new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, path, true));
|
untaggedDungeons.add(new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, path, true, DungeonType.UNKNOWN_TYPE));
|
||||||
System.out.println("Registered untagged dungeon: " + name);
|
System.out.println("Registered untagged dungeon: " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +286,7 @@ public class DungeonHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void importCustomDungeons(String path)
|
private void registerCustomDungeons(String path)
|
||||||
{
|
{
|
||||||
File directory = new File(path);
|
File directory = new File(path);
|
||||||
File[] schematicNames = directory.listFiles();
|
File[] schematicNames = directory.listFiles();
|
||||||
@@ -298,9 +307,9 @@ public class DungeonHelper
|
|||||||
{
|
{
|
||||||
//Register the core schematics
|
//Register the core schematics
|
||||||
//These are used for debugging and in case of unusual errors while loading dungeons
|
//These are used for debugging and in case of unusual errors while loading dungeons
|
||||||
defaultUp = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_UP_SCHEMATIC_PATH, true);
|
defaultUp = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_UP_SCHEMATIC_PATH, true, DungeonType.UNKNOWN_TYPE);
|
||||||
defaultDown = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_DOWN_SCHEMATIC_PATH, true);
|
defaultDown = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_DOWN_SCHEMATIC_PATH, true, DungeonType.UNKNOWN_TYPE);
|
||||||
defaultError = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_ERROR_SCHEMATIC_PATH, true);
|
defaultError = new DungeonGenerator(DEFAULT_DUNGEON_WEIGHT, DEFAULT_ERROR_SCHEMATIC_PATH, true, DungeonType.UNKNOWN_TYPE);
|
||||||
|
|
||||||
//Open the list of dungeons packaged with our mod and register their schematics
|
//Open the list of dungeons packaged with our mod and register their schematics
|
||||||
InputStream listStream = this.getClass().getResourceAsStream(BUNDLED_DUNGEONS_LIST_PATH);
|
InputStream listStream = this.getClass().getResourceAsStream(BUNDLED_DUNGEONS_LIST_PATH);
|
||||||
@@ -408,7 +417,7 @@ public class DungeonHelper
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<DungeonGenerator> getDungeonChainHistory(DimData dimData, int maxSize)
|
public static ArrayList<DungeonGenerator> getDungeonChainHistory(DimData dimData, DungeonPack pack, int maxSize)
|
||||||
{
|
{
|
||||||
//TODO: I've improved this code for the time being. However, searching across links is a flawed approach. A player could
|
//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.
|
//manipulate the output of this function by setting up links to mislead our algorithm or by removing links.
|
||||||
@@ -418,10 +427,15 @@ public class DungeonHelper
|
|||||||
ArrayList<DungeonGenerator> history = new ArrayList<DungeonGenerator>();
|
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 = helper.getDimData(helper.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID);
|
||||||
|
|
||||||
for (int count = 0; count < maxSize && tailDim.dungeonGenerator != null; count++)
|
for (int count = 0; count < maxSize; count++)
|
||||||
{
|
{
|
||||||
history.add(tailDim.dungeonGenerator);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
history.add(tailDim.dungeonGenerator);
|
||||||
if (count + 1 < maxSize)
|
if (count + 1 < maxSize)
|
||||||
{
|
{
|
||||||
for (LinkData link : tailDim.getLinksInDim())
|
for (LinkData link : tailDim.getLinksInDim())
|
||||||
|
|||||||
@@ -17,11 +17,15 @@ public class WeightedContainer<T> extends WeightedRandomItem {
|
|||||||
{
|
{
|
||||||
super(weight);
|
super(weight);
|
||||||
this.data = data;
|
this.data = data;
|
||||||
super.itemWeight = weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T getData()
|
public T getData()
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WeightedContainer<T> clone()
|
||||||
|
{
|
||||||
|
return new WeightedContainer<T>(data, itemWeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user