Schematic handler improvments

- Add netherProbability parameter to the random dungeon function, and set it to depth/50 for now (I'll make it non-linear in a future version)
 - Add a reusable weightedRandom method to MathUtils
 - Make config option to allow for random public pocket size, modify random template code to be able to add variations for "singular" templates
 - Load all pocket sizes but only create ones smaller than maxPocketSize naturally. This way an admin can still manually create a pocket larger than the max size using /dimpocket
 - Javadocs
 - Null checks for a few methods
 - Load schematics when plugin loads rather than when world loads
 does adding to groups work?
This commit is contained in:
Runemoro 2017-12-06 16:44:43 -05:00
parent c10646ad18
commit 59c47701f5
11 changed files with 208 additions and 219 deletions

View file

@ -60,7 +60,6 @@ public class DimDoors {
registerCommands(event);
RiftRegistry.INSTANCE.reset();
PocketRegistry.INSTANCE.reset();
SchematicHandler.INSTANCE.loadSchematics();
}
private void registerCommands(FMLServerStartingEvent event) {

View file

@ -44,6 +44,7 @@ public abstract class DDProxyCommon implements IDDProxy {
@Override
public void onInitialization(FMLInitializationEvent event) {
SchematicHandler.INSTANCE.loadSchematics();
}
public void updateDoorTE(BlockDimDoorBase door, World world, BlockPos pos) {

View file

@ -8,6 +8,7 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.util.RandomUtils;
import com.zixiken.dimdoors.shared.util.Schematic;
import com.zixiken.dimdoors.shared.world.DimDoorDimensions;
import java.util.ArrayList;
import java.util.HashMap;
@ -176,7 +177,7 @@ public class PocketRegistry {
}
public Pocket generateRandomPocketAt(EnumPocketType typeID, int depth, Location origRiftLocation) {
//Correcting the depth. Just in case...
// Correcting the depth. Just in case...
if (typeID == EnumPocketType.DUNGEON) {
if (depth <= 0) {
depth = 1;
@ -188,8 +189,19 @@ public class PocketRegistry {
}
// Fetch the pocket template
PocketTemplate pocketTemplate = getRandomPocketTemplate(typeID, depth, maxPocketSize);
PocketTemplate pocketTemplate;
switch (typeID) {
case DUNGEON:
pocketTemplate = SchematicHandler.INSTANCE.getDungeonTemplate(depth / 50, depth);
break;
case PUBLIC:
pocketTemplate = SchematicHandler.INSTANCE.getPublicPocketTemplate();
break;
case PRIVATE:
default:
pocketTemplate = SchematicHandler.INSTANCE.getPersonalPocketTemplate();
break;
}
return generatePocketAt(typeID, depth, origRiftLocation, pocketTemplate);
}
@ -250,17 +262,7 @@ public class PocketRegistry {
return new Location(dimID, x, y, z);
}
private PocketTemplate getRandomPocketTemplate(EnumPocketType typeID, int depth, int maxPocketSize) {
switch (typeID) {
case PRIVATE:
return SchematicHandler.INSTANCE.getPersonalPocketTemplate();
case PUBLIC:
return SchematicHandler.INSTANCE.getPublicPocketTemplate();
case DUNGEON:
default:
return SchematicHandler.INSTANCE.getRandomDungeonPocketTemplate(depth, maxPocketSize);
}
}
/*
private int getSimpleX(int ID) {
@ -337,6 +339,7 @@ public class PocketRegistry {
} else {
EnumPocketType type = DimDoorDimensions.getPocketType(location.getDimensionID());
Pocket pocket = pocketLists.get(type).get(pocketID);
if (pocket == null) return true; // TODO: why is this happening?
return pocket.isPlayerAllowedInPocket(player) && pocket.isLocationWithinPocketBounds(location, gridSize);
}
}

View file

@ -30,16 +30,17 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
private final int size;
private final EnumPocketType typeID;
//selection parameters
private final String directoryName;
private final String groupName;
private final String variantName;
private String variantType;
private final int minDepth;
private final int maxDepth;
private final int[] weights; //weights for chanced generation of dungeons per depth level | weights[0] is the weight for depth "minDepth"
//this class should contain the actual schematic info, as well as some of the Json info (placement of Rifts and stuff)
public PocketTemplate(String directoryName, String variantName, Schematic schematic, int size,
EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this.directoryName = directoryName;
public PocketTemplate(String groupName, String variantName, Schematic schematic, int size,
EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this.groupName = groupName;
this.variantName = variantName;
this.weights = weights; //chance that this Pocket will get generated
this.minDepth = minDepth; //pocket will only be generated from this Pocket-depth
@ -49,9 +50,9 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
this.typeID = typeID;
}
public PocketTemplate(String directoryName, String variantName, int size,
EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this(directoryName, variantName, null, size, typeID, minDepth, maxDepth, weights);
public PocketTemplate(String groupName, String variantName, int size,
EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this(groupName, variantName, null, size, typeID, minDepth, maxDepth, weights);
}
int getSize() {
@ -71,17 +72,21 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
if (index >= 0 && index < weights.length) {
return weights[index];
}
return 0; //do not generate
return weights[weights.length - 1]; // return last weight
}
String getDirName() {
return directoryName;
String getGroupName() {
return groupName;
}
public String getName() {
return variantName;
}
public String getType() {
return variantType;
}
Schematic getSchematic() {
return schematic;
}

View file

@ -5,6 +5,8 @@
*/
package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.util.MathUtils;
import com.zixiken.dimdoors.shared.util.RandomUtils;
import com.zixiken.dimdoors.shared.util.Schematic;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@ -19,152 +21,84 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.CompressedStreamTools;
import org.apache.commons.io.IOUtils;
import scala.tools.nsc.Global;
/**
*
* @author Robijnvogel
*/
public class SchematicHandler {
public static final SchematicHandler INSTANCE = new SchematicHandler();
private PocketTemplate personalPocketTemplate;
private PocketTemplate publicPocketTemplate;
private List<PocketTemplate> dungeonTemplates; //@todo should this be a Map? Does it need to? It gets reloaded from scratch on ServerStart every time, so...
final private Map<String, Map<String, Integer>> dungeonNameMap = new HashMap<>();
//@todo, sort templates by depth over here? that'd mean that that doesn't have to be done on pocket placement each and every time
PocketTemplate getRandomDungeonPocketTemplate(int depth, int maxPocketSize) { //@todo maxPocketSize is passed for no reason at all here; pockets exceeding maxPocketSize have not been loaded in the first place...
List<PocketTemplate> validTemplates = new ArrayList<>();
int totalWeight = 0;
for (PocketTemplate template : dungeonTemplates) {
if (depth >= template.getMinDepth() && depth <= template.getMaxDepth()) {
validTemplates.add(template);
totalWeight += template.getWeight(depth);
}
}
DimDoors.log(getClass(), "depth = " + depth + ". totalWeight = " + totalWeight);
private List<PocketTemplate> templates;
private Map<String, Map<String, Integer>> nameMap; // group -> name -> index in templates
Random random = new Random();
int chosenTemplatePointer = random.nextInt(totalWeight);
for (PocketTemplate template : validTemplates) {
chosenTemplatePointer -= template.getWeight(depth);
if (chosenTemplatePointer < 0) {
return template;
}
}
DimDoors.warn(getClass(), "No valid dungeon could be chosen for this depth. What have you done to make this happen? Now crashing:");
return null;
}
// LOADING CODE STARTS HERE <editor-fold>
public void loadSchematics() {
personalPocketTemplate = loadTemplatesFromJson("default_private", PocketRegistry.INSTANCE.getPrivatePocketSize()).get(0);
publicPocketTemplate = loadTemplatesFromJson("default_public", PocketRegistry.INSTANCE.getPublicPocketSize()).get(0);
dungeonTemplates = new ArrayList<>();
List<String> dungeonSchematicNameStrings = DDConfig.getDungeonSchematicNames();
int maxPocketSize = PocketRegistry.INSTANCE.getMaxPocketSize();
for (String nameString : dungeonSchematicNameStrings) {
List<PocketTemplate> templates = loadTemplatesFromJson(nameString, maxPocketSize);
if (templates != null) {
for (PocketTemplate template : templates) {
if (template != null && template.getSchematic() != null) {
dungeonTemplates.add(template);
}
}
templates = new ArrayList<>();
String[] names = {"default_dungeon_normal", "default_dungeon_nether", "default_private", "default_public"}; // TODO: don't hardcode
for (String name : names) {
try {
URL resource = DimDoors.class.getResource("/assets/dimdoors/pockets/json/" + name + ".json");
String jsonString = IOUtils.toString(resource, StandardCharsets.UTF_8);
templates.addAll(loadTemplatesFromJson(jsonString));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
constructDungeonNameMap();
// Schematic.tempGenerateDefaultSchematics();
}
private void constructDungeonNameMap() {
//init
dungeonNameMap.clear();
//to prevent having to use too many getters
String bufferedDirectory = null;
Map<String, Integer> bufferedMap = null;
for (PocketTemplate template : dungeonTemplates) {
String dirName = template.getDirName();
if (dirName != null && dirName.equals(bufferedDirectory)) { //null check not needed
bufferedMap.put(template.getName(), dungeonTemplates.indexOf(template));
} else {
bufferedDirectory = dirName;
if (dungeonNameMap.containsKey(dirName)) { //this will only happen if you have two json files referring to the same directory being loaded non-consecutively
bufferedMap = dungeonNameMap.get(dirName);
bufferedMap.put(template.getName(), dungeonTemplates.indexOf(template));
} else {
bufferedMap = new HashMap<>();
bufferedMap.put(template.getName(), dungeonTemplates.indexOf(template));
dungeonNameMap.put(dirName, bufferedMap);
}
}
}
}
private static List<PocketTemplate> loadTemplatesFromJson(String nameString, int maxPocketSize) { //depending on the "jSonType" value in the jSon, this might load several variations of a pocket at once, hence loadTemplate -->s<--
InputStream jsonJarStream = DimDoors.class.getResourceAsStream("/assets/dimdoors/pockets/json/" + nameString + ".json");
String schematicJarDirectory = "/assets/dimdoors/pockets/schematic/";
//init jsons config folder
File jsonFolder = new File(DDConfig.configurationFolder, "/Jsons");
// Load config jsons
File jsonFolder = new File(DDConfig.configurationFolder, "/jsons");
if (!jsonFolder.exists()) {
jsonFolder.mkdirs();
}
File jsonFile = new File(jsonFolder, "/" + nameString + ".json"); //@todo this could probably be moved a few lines down
//init schematics config folder
File schematicFolder = new File(DDConfig.configurationFolder, "/Schematics");
// Init schematics config folder
File schematicFolder = new File(DDConfig.configurationFolder, "/schematics");
if (!schematicFolder.exists()) {
schematicFolder.mkdirs();
}
//load the json and convert it to a JsonObject
String jsonString;
if (jsonJarStream != null) {
StringWriter writer = new StringWriter();
for (File file : jsonFolder.listFiles()) {
try {
IOUtils.copy(jsonJarStream, writer, StandardCharsets.UTF_8);
} catch (IOException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Json-file " + nameString + ".json did not load correctly from jar. Skipping loading of this template.", ex);
return new ArrayList<>();
String jsonString = IOUtils.toString(file.toURI(), StandardCharsets.UTF_8);
templates.addAll(loadTemplatesFromJson(jsonString));
} catch (IOException e) {
DimDoors.warn("Error reading file " + file.toURI() + ". The following exception occured: ");
}
jsonString = writer.toString();
} else if (jsonFile.exists()) {
DimDoors.log(SchematicHandler.class, "Json-file " + nameString + ".json was not found in the jar. Loading from config directory instead.");
try {
jsonString = readFile(jsonFile.getAbsolutePath(), StandardCharsets.UTF_8);
} catch (IOException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Json-file " + nameString + ".json did not load correctly from config folder. Skipping loading of this template.", ex);
return new ArrayList<>();
}
} else {
DimDoors.warn(SchematicHandler.class, "Json-file " + nameString + ".json was not found in the jar or config directory. Skipping loading of this template.");
return new ArrayList<>();
}
DimDoors.log("Loaded " + templates.size() + " templates.");
constructNameMap();
// Schematic.tempGenerateDefaultSchematics();
}
private static List<PocketTemplate> loadTemplatesFromJson(String jsonString) {
String schematicJarDirectory = "/assets/dimdoors/pockets/schematic/";
File schematicFolder = new File(DDConfig.configurationFolder, "/schematics");
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(jsonString);
JsonObject jsonTemplate = jsonElement.getAsJsonObject();
//DimDoors.log(SchematicHandler.class, "Checkpoint 1 reached");
//Generate and get templates (without a schematic) of all variations that are valid for the current "maxPocketSize"
List<PocketTemplate> validTemplates = getAllValidVariations(jsonTemplate, maxPocketSize);
List<PocketTemplate> validTemplates = getAllValidVariations(jsonTemplate);
//DimDoors.log(SchematicHandler.class, "Checkpoint 4 reached; " + validTemplates.size() + " templates were loaded");
String subDirectory = jsonTemplate.get("directory").getAsString(); //get the subfolder in which the schematics are stored
String subDirectory = jsonTemplate.get("group").getAsString(); //get the subfolder in which the schematics are stored
for (PocketTemplate template : validTemplates) { //it's okay to "tap" this for-loop, even if validTemplates is empty.
String extendedTemplatelocation = subDirectory.equals("") ? template.getName() : subDirectory + "/" + template.getName(); //transform the filename accordingly
@ -223,58 +157,23 @@ public class SchematicHandler {
if (schematic != null
&& (schematic.getWidth() > (template.getSize() + 1) * 16 || schematic.getLength() > (template.getSize() + 1) * 16)) {
schematic = null;
DimDoors.log(SchematicHandler.class, "Schematic " + template.getName() + " was bigger than specified in " + nameString + ".json and therefore wasn't loaded");
DimDoors.log(SchematicHandler.class, "Schematic " + template.getName() + " was bigger than specified in its json file and therefore wasn't loaded");
}
template.setSchematic(schematic);
}
return validTemplates;
}
static String readFile(String path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
private static List<PocketTemplate> getAllValidVariations(JsonObject jsonTemplate) {
List<PocketTemplate> pocketTemplates = new ArrayList<>();
private static List<PocketTemplate> getAllValidVariations(JsonObject jsonTemplate, int maxPocketSize) {
final String directory = jsonTemplate.get("directory").getAsString();
final String jsonType = jsonTemplate.get("jsonType").getAsString();
final String directory = jsonTemplate.get("group").getAsString();
final EnumPocketType pocketType = EnumPocketType.getFromInt(jsonTemplate.get("pocketType").getAsInt());
final JsonArray variations = jsonTemplate.getAsJsonArray("variations");
List<PocketTemplate> pocketTemplates = new ArrayList<>();
JsonObject chosenVariation = null; //only applicable if jsonType == "Singular"
int chosenVariationSize = -1; //only applicable if jsonType == "Singular"
List<JsonObject> validVariations = new ArrayList<>();
//put all valid variation JsonObjects into an array list
for (int i = 0; i < variations.size(); i++) {
JsonObject variation = variations.get(i).getAsJsonObject();
int variationSize = variation.get("size").getAsInt();
if (variationSize > maxPocketSize) {
//DimDoors.log(SchematicHandler.class, "Checkpoint 2 reached; Variation size " + variationSize + " is bigger than maxPocketSize " + maxPocketSize + ".");
//do not add it
} else if (jsonType.equals("Singular")) {
if (variationSize > chosenVariationSize) {
chosenVariationSize = variationSize;
chosenVariation = variation;
if (variationSize == maxPocketSize) {
break; //this one gets chosen
}
}
} else if (jsonType.equals("Multiple")) {
validVariations.add(variation);
} else { //@todo more options?
DimDoors.log(SchematicHandler.class, "JsonType " + jsonType + " is not a valid JsonType. Json was not loaded.");
}
}
if (chosenVariation != null) {
validVariations.add(chosenVariation);
}
//DimDoors.log(SchematicHandler.class, "Checkpoint 3 reached; " + validVariations.size() + " variations were selected.");
//convert the valid variations arraylist to a list of pocket templates
for (JsonObject variation : validVariations) {
//convert the variations arraylist to a list of pocket templates
for (JsonElement variationElement : variations) {
JsonObject variation = variationElement.getAsJsonObject();
String variantName = variation.get("variantName").getAsString();
int variationSize = variation.get("size").getAsInt();
int minDepth = variation.get("minDepth").getAsInt();
@ -291,45 +190,114 @@ public class SchematicHandler {
return pocketTemplates;
}
private void constructNameMap() {
nameMap = new HashMap<String, Map<String, Integer>>();
//to prevent having to use too many getters
String bufferedDirectory = null;
Map<String, Integer> bufferedMap = null;
for (PocketTemplate template : templates) {
String dirName = template.getGroupName();
if (dirName != null && dirName.equals(bufferedDirectory)) { //null check not needed
bufferedMap.put(template.getName(), templates.indexOf(template));
} else {
bufferedDirectory = dirName;
if (nameMap.containsKey(dirName)) { //this will only happen if you have two json files referring to the same directory being loaded non-consecutively
bufferedMap = nameMap.get(dirName);
bufferedMap.put(template.getName(), templates.indexOf(template));
} else {
bufferedMap = new HashMap<>();
bufferedMap.put(template.getName(), templates.indexOf(template));
nameMap.put(dirName, bufferedMap);
}
}
}
}
// LOADING CODE ENDS HERE </editor-fold>
public ArrayList<String> getTemplateGroups() {
return new ArrayList<>(nameMap.keySet());
}
public ArrayList<String> getTemplateNames(String group) {
return new ArrayList<>(nameMap.get(group).keySet());
}
/**
* @return the personalPocketTemplate
* Gets a loaded PocketTemplate by its group and name.
*
* @param group Template group
* @param name Template name
* @return The dungeon template with that group and name, or null if it wasn't found
*/
public PocketTemplate getTemplate(String group, String name) {
Map<String, Integer> groupMap = nameMap.get(group);
if(groupMap == null) return null;
Integer index = groupMap.get(name);
if(index == null) return null;
return templates.get(index);
}
/**
* Gets a random template matching certain criteria.
*
* @param groupWeights
* @param depth
* @param maxSize
* @param getLargest
* @return A random template matching those criteria, or null if none were found
*/
public PocketTemplate getRandomTemplate(Map<String, Integer> groupWeights, int depth, int maxSize, boolean getLargest) { // TODO: useful?
String group = MathUtils.weightedRandom(groupWeights);
return getRandomTemplate(group, depth, maxSize, getLargest);
}
/**
* Gets a random template matching certain criteria.
*
* @param group
* @param depth
* @param maxSize Maximum size the template can be.
* @param getLargest Setting this to true will always get the largest template size in that group, but still randomly out of the templates with that size (ex. for private pockets)
* @return A random template matching those criteria, or null if none were found
*/
public PocketTemplate getRandomTemplate(String group, int depth, int maxSize, boolean getLargest) {
// TODO: cache this for faster calls:
Map<PocketTemplate, Integer> weightedTemplates = new HashMap<>();
int largestSize = 0;
for (PocketTemplate template : templates) {
if (template.getGroupName().equals(group)
&& (depth == -1 || depth >= template.getMinDepth() && (depth <= template.getMaxDepth() || template.getMaxDepth() == -1))
&& (maxSize == -1 || template.getSize() < maxSize)) {
if (getLargest && template.getSize() > largestSize) {
weightedTemplates = new HashMap<>();
largestSize = template.getSize();
}
weightedTemplates.put(template, template.getWeight(depth));
}
}
if (weightedTemplates.size() == 0) {
DimDoors.warn("getRandomTemplate failed, no templates matching those criteria were found.");
return null; // TODO: switch to exception system
}
return MathUtils.weightedRandom(weightedTemplates);
}
public PocketTemplate getPersonalPocketTemplate() {
return personalPocketTemplate;
return getRandomTemplate("private", -1, DDConfig.getMaxPocketsSize(), true); // TODO: config option for getLargest
}
/**
* @return the publicPocketTemplate
*/
public PocketTemplate getPublicPocketTemplate() {
return publicPocketTemplate;
return getRandomTemplate("private", -1, DDConfig.getMaxPocketsSize(), true); // TODO: config option for getLargest
}
/**
* @param directory file directory of the template schematic
* @param name filename of the template schematic
* @return the dungeonTemplate that was loaded from folder {@code directory}
* with filename {@code name}
*/
public PocketTemplate getDungeonTemplate(String directory, String name) {
//@todo nullcheck on the parameters
int index = dungeonNameMap.get(directory).get(name);
return dungeonTemplates.get(index);
}
public ArrayList<String> getDungeonTemplateGroups() {
return new ArrayList<>(dungeonNameMap.keySet());
}
public ArrayList<String> getDungeonTemplateNames(String directory) {
return new ArrayList<>(dungeonNameMap.get(directory).keySet());
}
/**
* @return the dungeonTemplates
*/
public List<PocketTemplate> getDungeonTemplates() {
return dungeonTemplates;
public PocketTemplate getDungeonTemplate(float netherProbability, int depth) {
Random random = new Random();
String group = (random.nextFloat() < netherProbability) ? "nether" : "ruins";
return getRandomTemplate(group, depth, DDConfig.getMaxPocketsSize(), false);
}
public void saveSchematic(Schematic schematic, String name) {

View file

@ -60,7 +60,7 @@ public class PocketCommand extends CommandBase {
origLoc = oldPocket.getDepthZeroLocation();
}
PocketTemplate template = SchematicHandler.INSTANCE.getDungeonTemplate(args[0], args[1]);
PocketTemplate template = SchematicHandler.INSTANCE.getTemplate(args[0], args[1]);
Pocket pocket = PocketRegistry.INSTANCE.generatePocketAt(EnumPocketType.DUNGEON, 1, origLoc, template);
int entranceDoorID = pocket.getEntranceDoorID();
RiftRegistry.INSTANCE.setLastGeneratedEntranceDoorID(entranceDoorID);
@ -74,10 +74,10 @@ public class PocketCommand extends CommandBase {
public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) {
List<String> list = new ArrayList<>();
if (args.length < 2) { //counts an empty ("") argument as an argument as well...
list = SchematicHandler.INSTANCE.getDungeonTemplateGroups();
list = SchematicHandler.INSTANCE.getTemplateGroups();
list = StringUtils.getMatchingStrings(args[0], list, false);
} else if (args.length == 2) {
list = SchematicHandler.INSTANCE.getDungeonTemplateNames(args[0]);
list = SchematicHandler.INSTANCE.getTemplateNames(args[0]);
list = StringUtils.getMatchingStrings(args[1], list, false);
}
return list;
@ -91,10 +91,10 @@ public class PocketCommand extends CommandBase {
DimDoors.chat(player, "Too many arguments.");
return false;
} else { //exactly 2 arguments
if (!SchematicHandler.INSTANCE.getDungeonTemplateGroups().contains(args[0])) {
if (!SchematicHandler.INSTANCE.getTemplateGroups().contains(args[0])) {
DimDoors.chat(player, "Group not found.");
return false;
} else if (!SchematicHandler.INSTANCE.getDungeonTemplateNames(args[0]).contains(args[1])) {
} else if (!SchematicHandler.INSTANCE.getTemplateNames(args[0]).contains(args[1])) {
DimDoors.chat(player, "Schematic not found.");
return false;
} else {

View file

@ -5,6 +5,9 @@
*/
package com.zixiken.dimdoors.shared.util;
import java.util.Map;
import java.util.Random;
/**
*
* @author Robijnvogel
@ -60,4 +63,18 @@ public class MathUtils {
}
return r;
}
public static <T> T weightedRandom(Map<T, Integer> weights) {
int totalWeight = 0;
for (Integer weight : weights.values()) {
totalWeight += weight;
}
Random random = new Random();
int i = random.nextInt(totalWeight);
for (Map.Entry<T, Integer> e : weights.entrySet()) {
i -= e.getValue();
if (i < 0) return e.getKey();
}
return null;
}
}

View file

@ -1,6 +1,5 @@
{
"directory": "nether",
"jsonType": "Multiple",
"group": "nether",
"pocketType" : 2,
"variations": [
{

View file

@ -1,6 +1,5 @@
{
"directory": "ruins",
"jsonType": "Multiple",
"group": "ruins",
"pocketType" : 2,
"variations": [
{

View file

@ -1,6 +1,5 @@
{
"directory": "private",
"jsonType": "Singular",
"group": "private",
"pocketType" : 0,
"variations": [
{

View file

@ -1,6 +1,5 @@
{
"directory": "public",
"jsonType": "Singular",
"group": "public",
"pocketType" : 1,
"variations": [
{