Progress on Implementing Dungeon Packs
Started implementing our support for dungeon packs. The code is not usable yet and the mod is not functional at this stage. A few additional changes should make it testable. A significant obstacle to implementing dungeon packs easily is that DungeonGenerator doesn't have some necessary information and shouldn't be modified. Even if it is modified, old serialized instances wouldn't have the new fields initialized. I'm having to create workarounds until we implement the new save format. DungeonPack handles all of the logic of selecting a dungeon and verifying whether its type is valid. It relies on DungeonChainRule and OptimizedRule to check which dungeons should be generated next given a list of the dungeons in a chain. DungeonType maps types in packs to ID numbers and provides a reference to the pack that owns the type. DungeonPackConfig will carry config information to be passed to the DungeonPack constructor.
This commit is contained in:
@@ -13,15 +13,12 @@ public class DungeonGenerator implements Serializable
|
|||||||
public String schematicPath;
|
public String schematicPath;
|
||||||
public ArrayList<HashMap> sideRifts = new ArrayList<HashMap>();
|
public ArrayList<HashMap> sideRifts = new ArrayList<HashMap>();
|
||||||
public LinkData exitLink;
|
public LinkData exitLink;
|
||||||
public static Random rand = new Random();
|
|
||||||
public boolean isOpen;
|
public boolean isOpen;
|
||||||
|
|
||||||
public int sideDoorsSoFar=0;
|
public int sideDoorsSoFar=0;
|
||||||
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)
|
||||||
{
|
{
|
||||||
this.weight=weight;
|
this.weight=weight;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package StevenDimDoors.mod_pocketDim;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
||||||
@@ -27,14 +28,32 @@ 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;
|
||||||
|
World world;
|
||||||
|
|
||||||
if (dimList.containsKey(destDimID))
|
if (dimList.containsKey(destDimID))
|
||||||
{
|
{
|
||||||
|
dimList.get(destDimID).hasBeenFilled = true;
|
||||||
|
if (dimHelper.getWorld(destDimID) == null)
|
||||||
|
{
|
||||||
|
dimHelper.initDimension(destDimID);
|
||||||
|
}
|
||||||
|
world = dimHelper.getWorld(destDimID);
|
||||||
|
|
||||||
if (dimList.get(destDimID).dungeonGenerator == null)
|
if (dimList.get(destDimID).dungeonGenerator == null)
|
||||||
{
|
{
|
||||||
DungeonHelper.instance().generateDungeonLink(link);
|
//The following initialization code is based on code from ChunkProviderGenerate.
|
||||||
|
//It makes our generation depend on the world seed.
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
//TODO: FIX THIS LINE OR SADNESS WILL FOLLOW. Add a reference to the dungeon pack.
|
||||||
|
//DungeonHelper.instance().generateDungeonLink(link, ???, random);
|
||||||
}
|
}
|
||||||
schematicPath = dimList.get(destDimID).dungeonGenerator.schematicPath;
|
schematicPath = dimList.get(destDimID).dungeonGenerator.schematicPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -77,13 +96,6 @@ public class SchematicLoader
|
|||||||
dungeon.applyImportFilters(properties);
|
dungeon.applyImportFilters(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
dimList.get(destDimID).hasBeenFilled = true;
|
|
||||||
if (dimHelper.getWorld(destDimID) == null)
|
|
||||||
{
|
|
||||||
dimHelper.initDimension(destDimID);
|
|
||||||
}
|
|
||||||
World world = dimHelper.getWorld(destDimID);
|
|
||||||
|
|
||||||
//Adjust the height at which the dungeon is placed to prevent vertical clipping
|
//Adjust the height at which the dungeon is placed to prevent vertical clipping
|
||||||
int fixedY = adjustDestinationY(world, link.destYCoord, dungeon);
|
int fixedY = adjustDestinationY(world, link.destYCoord, dungeon);
|
||||||
if (fixedY != link.destYCoord)
|
if (fixedY != link.destYCoord)
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class DungeonChainRule
|
||||||
|
{
|
||||||
|
|
||||||
|
public OptimizedRule optimize(HashMap<String, DungeonType> nameToTypeMapping) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
247
StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java
Normal file
247
StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonPack.java
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.util.WeightedRandom;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DungeonGenerator;
|
||||||
|
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||||
|
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||||
|
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
||||||
|
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||||
|
|
||||||
|
public class DungeonPack
|
||||||
|
{
|
||||||
|
//Why final? I just felt like it, honestly. ~SenseiKiwi
|
||||||
|
|
||||||
|
private static final DungeonType WILDCARD_TYPE = new DungeonType(null, "?", 0);
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final HashMap<String, DungeonType> nameToTypeMapping;
|
||||||
|
private final ArrayList<ArrayList<DungeonGenerator>> groupedDungeons;
|
||||||
|
private final ArrayList<DungeonGenerator> allDungeons;
|
||||||
|
private final DungeonPackConfig config;
|
||||||
|
private final int maxRuleLength;
|
||||||
|
private final ArrayList<OptimizedRule> rules;
|
||||||
|
|
||||||
|
public DungeonPack(DungeonPackConfig config)
|
||||||
|
{
|
||||||
|
config.validate();
|
||||||
|
this.config = config.clone(); //Store a clone of the config so that the caller can't change it externally later
|
||||||
|
this.name = config.getName();
|
||||||
|
|
||||||
|
int index;
|
||||||
|
int maxLength = 0;
|
||||||
|
int typeCount = config.getTypeNames().size();
|
||||||
|
this.allDungeons = new ArrayList<DungeonGenerator>();
|
||||||
|
this.nameToTypeMapping = new HashMap<String, DungeonType>(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.nameToTypeMapping.put(WILDCARD_TYPE.Name, WILDCARD_TYPE);
|
||||||
|
|
||||||
|
index = 1;
|
||||||
|
for (String typeName : config.getTypeNames())
|
||||||
|
{
|
||||||
|
String standardName = typeName.toUpperCase();
|
||||||
|
this.nameToTypeMapping.put(standardName, new DungeonType(this, standardName, index));
|
||||||
|
this.groupedDungeons.add(new ArrayList<DungeonGenerator>());
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Construct optimized rules from config rules
|
||||||
|
ArrayList<DungeonChainRule> chainRules = config.getRules();
|
||||||
|
this.rules = new ArrayList<OptimizedRule>(chainRules.size());
|
||||||
|
for (DungeonChainRule rule : chainRules)
|
||||||
|
{
|
||||||
|
OptimizedRule optimized = rule.optimize(nameToTypeMapping);
|
||||||
|
this.rules.add(optimized);
|
||||||
|
if (maxLength < optimized.length())
|
||||||
|
{
|
||||||
|
maxLength = optimized.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.maxRuleLength = maxLength;
|
||||||
|
|
||||||
|
//Remove the reference to the non-optimized rules to free up memory - we won't need them here
|
||||||
|
this.config.setRules(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
return allDungeons.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DungeonType getType(String typeName)
|
||||||
|
{
|
||||||
|
DungeonType result = nameToTypeMapping.get(typeName.toUpperCase());
|
||||||
|
if (result != WILDCARD_TYPE)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isKnownType(String typeName)
|
||||||
|
{
|
||||||
|
return (this.getType(typeName) != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DungeonGenerator getNextDungeon(LinkData inbound, Random random)
|
||||||
|
{
|
||||||
|
if (allDungeons.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Retrieve a list of the previous dungeons in this chain. Restrict the length of the
|
||||||
|
//search to the length of the longest rule. Getting more data is useless.
|
||||||
|
dimHelper helper = dimHelper.instance;
|
||||||
|
|
||||||
|
//TODO: Add dungeon pack parameter! We can't use dungeon types from other packs.
|
||||||
|
ArrayList<DungeonGenerator> history = DungeonHelper.getDungeonChainHistory(helper.getDimData(inbound.locDimID), maxRuleLength);
|
||||||
|
return getNextDungeon(history, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DungeonGenerator getNextDungeon(ArrayList<DungeonGenerator> history, Random random)
|
||||||
|
{
|
||||||
|
//Extract the dungeon types that have been used from history and convert them into an array of IDs
|
||||||
|
int index;
|
||||||
|
int[] typeHistory = new int[history.size()];
|
||||||
|
HashSet<DungeonGenerator> excludedDungeons = null;
|
||||||
|
for (index = 0; index < typeHistory.length; index++)
|
||||||
|
{
|
||||||
|
typeHistory[index] = getDungeonType(history.get(index)).ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (OptimizedRule rule : rules)
|
||||||
|
{
|
||||||
|
if (rule.evaluate(typeHistory))
|
||||||
|
{
|
||||||
|
//Pick a random dungeon type to be generated next based on the rule's products
|
||||||
|
ArrayList<WeightedContainer<DungeonType>> products = rule.products();
|
||||||
|
DungeonType nextType;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nextType = getRandomDungeonType(random, products, groupedDungeons);
|
||||||
|
if (nextType != null)
|
||||||
|
{
|
||||||
|
//Initialize the set of excluded dungeons if needed
|
||||||
|
if (excludedDungeons == null && config.allowDuplicatesInChain())
|
||||||
|
{
|
||||||
|
//TODO: Finish implementing this!
|
||||||
|
}
|
||||||
|
|
||||||
|
//List which dungeons are allowed
|
||||||
|
ArrayList<DungeonGenerator> candidates;
|
||||||
|
ArrayList<DungeonGenerator> group = groupedDungeons.get(nextType.ID);
|
||||||
|
if (excludedDungeons != null)
|
||||||
|
{
|
||||||
|
candidates = new ArrayList<DungeonGenerator>(group.size());
|
||||||
|
for (DungeonGenerator dungeon : group)
|
||||||
|
{
|
||||||
|
if (!excludedDungeons.contains(dungeon))
|
||||||
|
{
|
||||||
|
candidates.add(dungeon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
candidates = group;
|
||||||
|
}
|
||||||
|
if (!candidates.isEmpty())
|
||||||
|
{
|
||||||
|
return getRandomDungeon(random, candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (nextType != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//None of the rules were applicable. Simply return a random dungeon.
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!allDungeons.isEmpty())
|
||||||
|
{
|
||||||
|
return getRandomDungeon(random, allDungeons);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DungeonType getRandomDungeonType(Random random, Collection<WeightedContainer<DungeonType>> types,
|
||||||
|
ArrayList<ArrayList<DungeonGenerator>> groupedDungeons)
|
||||||
|
{
|
||||||
|
//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
|
||||||
|
|
||||||
|
//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())
|
||||||
|
{
|
||||||
|
//Pick a random dungeon type
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
WeightedContainer<DungeonType> resultContainer = (WeightedContainer<DungeonType>) WeightedRandom.getRandomItem(random, types);
|
||||||
|
|
||||||
|
//Check if there are any dungeons of that type
|
||||||
|
DungeonType selectedType = resultContainer.getData();
|
||||||
|
if (!groupedDungeons.get(selectedType.ID).isEmpty())
|
||||||
|
{
|
||||||
|
//Choose this type
|
||||||
|
return selectedType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//We can't use this type because there are no dungeons of this type
|
||||||
|
//Remove it from the list of types and try again
|
||||||
|
types.remove(resultContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//We have run out of types to try
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DungeonGenerator getRandomDungeon(Random random, Collection<DungeonGenerator> dungeons)
|
||||||
|
{
|
||||||
|
//Use Minecraft's WeightedRandom to select our dungeon. =D
|
||||||
|
ArrayList<WeightedContainer<DungeonGenerator>> weights =
|
||||||
|
new ArrayList<WeightedContainer<DungeonGenerator>>(dungeons.size());
|
||||||
|
for (DungeonGenerator dungeon : dungeons)
|
||||||
|
{
|
||||||
|
weights.add(new WeightedContainer<DungeonGenerator>(dungeon, dungeon.weight));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
WeightedContainer<DungeonGenerator> resultContainer = (WeightedContainer<DungeonGenerator>) WeightedRandom.getRandomItem(random, weights);
|
||||||
|
return (resultContainer != null) ? resultContainer.getData() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DungeonPackConfig
|
||||||
|
{
|
||||||
|
public DungeonPackConfig() { }
|
||||||
|
|
||||||
|
private DungeonPackConfig(DungeonPackConfig source)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DungeonPackConfig clone()
|
||||||
|
{
|
||||||
|
return new DungeonPackConfig(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTypeNames()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allowDuplicatesInChain()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRules(Object object) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<DungeonChainRule> getRules() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonType.java
Normal file
45
StevenDimDoors/mod_pocketDim/dungeon/pack/DungeonType.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||||
|
|
||||||
|
public class DungeonType implements Comparable<DungeonType>
|
||||||
|
{
|
||||||
|
public final DungeonPack Owner;
|
||||||
|
public final String Name;
|
||||||
|
public final int ID;
|
||||||
|
|
||||||
|
public DungeonType(DungeonPack owner, String name, int id)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
Name = name;
|
||||||
|
this.ID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(DungeonType other)
|
||||||
|
{
|
||||||
|
return this.ID - other.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other)
|
||||||
|
{
|
||||||
|
return equals((DungeonType) other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(DungeonType other)
|
||||||
|
{
|
||||||
|
if (this == other)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (this == null || other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (this.ID == other.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
final int prime = 2039;
|
||||||
|
return prime * ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
StevenDimDoors/mod_pocketDim/dungeon/pack/OptimizedRule.java
Normal file
25
StevenDimDoors/mod_pocketDim/dungeon/pack/OptimizedRule.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,7 +13,6 @@ import java.util.List;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.minecraft.util.WeightedRandom;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
import StevenDimDoors.mod_pocketDim.DimData;
|
import StevenDimDoors.mod_pocketDim.DimData;
|
||||||
@@ -21,8 +20,8 @@ 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.DungeonPack;
|
||||||
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
import StevenDimDoors.mod_pocketDim.items.itemDimDoor;
|
||||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
|
||||||
|
|
||||||
public class DungeonHelper
|
public class DungeonHelper
|
||||||
{
|
{
|
||||||
@@ -65,8 +64,6 @@ public class DungeonHelper
|
|||||||
MAZE_DUNGEON_TYPE
|
MAZE_DUNGEON_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
private Random rand = new Random();
|
|
||||||
|
|
||||||
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>();
|
||||||
|
|
||||||
@@ -354,157 +351,29 @@ public class DungeonHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateDungeonLink(LinkData incoming)
|
public void generateDungeonLink(LinkData inbound, DungeonPack pack, Random random)
|
||||||
{
|
{
|
||||||
DungeonGenerator dungeon;
|
DungeonGenerator selection;
|
||||||
int depth = dimHelper.instance.getDimDepth(incoming.locDimID);
|
|
||||||
int depthWeight = rand.nextInt(depth + 2) + rand.nextInt(depth + 2) - 2;
|
|
||||||
|
|
||||||
int count = 10;
|
|
||||||
boolean flag = true;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
selection = pack.getNextDungeon(inbound, random);
|
||||||
if (incoming.destYCoord > 15)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
count--;
|
|
||||||
flag = true;
|
|
||||||
//Select a dungeon at random, taking into account its weight
|
|
||||||
dungeon = getRandomDungeon(rand, registeredDungeons);
|
|
||||||
|
|
||||||
if (depth <= 1)
|
|
||||||
{
|
|
||||||
if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = complexHalls.get(rand.nextInt(complexHalls.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = hubs.get(rand.nextInt(hubs.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = hubs.get(rand.nextInt(hubs.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(deadEnds.contains(dungeon)||exits.contains(dungeon))
|
|
||||||
{
|
|
||||||
flag=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (depth <= 3 && (deadEnds.contains(dungeon) || exits.contains(dungeon) || rand.nextBoolean()))
|
|
||||||
{
|
|
||||||
if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = hubs.get(rand.nextInt(hubs.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = mazes.get(rand.nextInt(mazes.size()));
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = pistonTraps.get(rand.nextInt(pistonTraps.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rand.nextInt(3) == 0 && !complexHalls.contains(dungeon))
|
|
||||||
{
|
|
||||||
if (rand.nextInt(3) == 0)
|
|
||||||
{
|
|
||||||
dungeon = simpleHalls.get(rand.nextInt(simpleHalls.size()));
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = pistonTraps.get(rand.nextInt(pistonTraps.size()));
|
|
||||||
}
|
|
||||||
else if (depth < 4)
|
|
||||||
{
|
|
||||||
dungeon = hubs.get(rand.nextInt(hubs.size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (depthWeight - depthWeight / 2 > depth -4 && (deadEnds.contains(dungeon) || exits.contains(dungeon)))
|
|
||||||
{
|
|
||||||
if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = simpleHalls.get(rand.nextInt(simpleHalls.size()));
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = complexHalls.get(rand.nextInt(complexHalls.size()));
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = pistonTraps.get(rand.nextInt(pistonTraps.size()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (depthWeight > 7 && hubs.contains(dungeon))
|
|
||||||
{
|
|
||||||
if(rand.nextInt(12)+5<depthWeight)
|
|
||||||
{
|
|
||||||
if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = exits.get(rand.nextInt(exits.size()));
|
|
||||||
}
|
|
||||||
else if(rand.nextBoolean())
|
|
||||||
{
|
|
||||||
dungeon = deadEnds.get(rand.nextInt(deadEnds.size()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dungeon = pistonTraps.get(rand.nextInt(pistonTraps.size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (depth > 10 && hubs.contains(dungeon))
|
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getDungeonDataInChain(dimHelper.instance.getDimData(incoming.locDimID)).contains(dungeon))
|
|
||||||
{
|
|
||||||
flag=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (!flag && count > 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dungeon = defaultUp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
System.err.println("An exception occurred while selecting a dungeon:");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
if (registeredDungeons.size() > 0)
|
|
||||||
|
if (!pack.isEmpty())
|
||||||
{
|
{
|
||||||
//Select a random dungeon
|
selection = pack.getRandomDungeon(random);
|
||||||
dungeon = getRandomDungeon(rand, registeredDungeons);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return;
|
selection = defaultError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dimHelper.instance.getDimData(incoming.destDimID).dungeonGenerator = dungeon;
|
dimHelper.instance.getDimData(inbound.destDimID).dungeonGenerator = selection;
|
||||||
//dimHelper.instance.getDimData(incoming.destDimID).dungeonGenerator = defaultUp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> getDungeonNames() {
|
public Collection<String> getDungeonNames() {
|
||||||
@@ -539,50 +408,33 @@ public class DungeonHelper
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DungeonGenerator getRandomDungeon(Random random, Collection<DungeonGenerator> dungeons)
|
public static ArrayList<DungeonGenerator> getDungeonChainHistory(DimData dimData, int maxSize)
|
||||||
{
|
{
|
||||||
//Use Minecraft's WeightedRandom to select our dungeon. =D
|
//TODO: I've improved this code for the time being. However, searching across links is a flawed approach. A player could
|
||||||
ArrayList<WeightedContainer<DungeonGenerator>> weights =
|
//manipulate the output of this function by setting up links to mislead our algorithm or by removing links.
|
||||||
new ArrayList<WeightedContainer<DungeonGenerator>>(dungeons.size());
|
//Dimensions MUST have built-in records of their parent dimensions in the future. ~SenseiKiwi
|
||||||
for (DungeonGenerator dungeon : dungeons)
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (int count = 0; count < maxSize && tailDim.dungeonGenerator != null; count++)
|
||||||
{
|
{
|
||||||
weights.add(new WeightedContainer<DungeonGenerator>(dungeon, dungeon.weight));
|
history.add(tailDim.dungeonGenerator);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
if (count + 1 < maxSize)
|
||||||
WeightedContainer<DungeonGenerator> resultContainer = (WeightedContainer<DungeonGenerator>) WeightedRandom.getRandomItem(random, weights);
|
|
||||||
return (resultContainer != null) ? resultContainer.getData() : null;
|
|
||||||
}
|
|
||||||
public static ArrayList<DungeonGenerator> getDungeonDataInChain(DimData dimData)
|
|
||||||
{
|
|
||||||
DimData startingDim = dimHelper.instance.getDimData(dimHelper.instance.getLinkDataFromCoords(dimData.exitDimLink.destXCoord, dimData.exitDimLink.destYCoord, dimData.exitDimLink.destZCoord, dimData.exitDimLink.destDimID).destDimID);
|
|
||||||
|
|
||||||
return getDungeonDataBelow(startingDim);
|
|
||||||
}
|
|
||||||
private static ArrayList<DungeonGenerator> getDungeonDataBelow(DimData dimData)
|
|
||||||
{
|
|
||||||
ArrayList<DungeonGenerator> dungeonData = new ArrayList<DungeonGenerator>();
|
|
||||||
if(dimData.dungeonGenerator!=null)
|
|
||||||
{
|
|
||||||
dungeonData.add(dimData.dungeonGenerator);
|
|
||||||
|
|
||||||
for(LinkData link : dimData.getLinksInDim())
|
|
||||||
{
|
{
|
||||||
if(dimHelper.dimList.containsKey(link.destDimID))
|
for (LinkData link : tailDim.getLinksInDim())
|
||||||
{
|
{
|
||||||
if(dimHelper.instance.getDimData(link.destDimID).dungeonGenerator!=null&&dimHelper.instance.getDimDepth(link.destDimID)==dimData.depth+1)
|
DimData nextDim = dimHelper.instance.getDimData(link.destDimID);
|
||||||
|
if (helper.getDimDepth(link.destDimID) == tailDim.depth + 1)
|
||||||
{
|
{
|
||||||
for(DungeonGenerator dungeonGen :getDungeonDataBelow(dimHelper.instance.getDimData(link.destDimID)) )
|
tailDim = nextDim;
|
||||||
{
|
break;
|
||||||
if(!dungeonData.contains(dungeonGen))
|
|
||||||
{
|
|
||||||
dungeonData.add(dungeonGen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dungeonData;
|
return history;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1320,17 +1320,9 @@ public class dimHelper extends DimensionManager
|
|||||||
{
|
{
|
||||||
return dimHelper.instance.getDimData(world.provider.dimensionId);
|
return dimHelper.instance.getDimData(world.provider.dimensionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DimData getDimData(int dimID)
|
public DimData getDimData(int dimID)
|
||||||
{
|
{
|
||||||
if(dimHelper.dimList.containsKey(dimID))
|
return dimHelper.dimList.get(dimID);
|
||||||
{
|
|
||||||
return dimHelper.dimList.get(dimID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user