Schematic generation command

-Completed command to force-generate Dungeon Pocket Schematics using
their directory (/group) and name
-Schematics now inherrit their name from their file name if it's not set
in their NBT

Warning:
-Quite a few of the pockets themselves show errouneous behaviour when
you try to generate them.
This commit is contained in:
Mathijs Riezebos 2017-05-01 20:18:00 +02:00
parent 13296ffdb9
commit fa6d32cf0c
7 changed files with 142 additions and 26 deletions

View file

@ -61,7 +61,7 @@ public class Pocket {
return z;
}
int getEntranceDoorID() {
public int getEntranceDoorID() {
if (riftIDs.isEmpty()) {
return -1;
} else if (riftIDs.size() == 1) {

View file

@ -195,6 +195,10 @@ public class PocketRegistry {
//Fetching the pocket template
PocketTemplate pocketTemplate = getRandomPocketTemplate(typeID, depth, maxPocketSize);
return generatePocketAt(typeID, depth, origRiftLocation, pocketTemplate);
}
public Pocket generatePocketAt(EnumPocketType typeID, int depth, Location origRiftLocation, PocketTemplate pocketTemplate) {
//Getting the physical grid-location and the Overworld coordinates
Location shortenedLocation = getGenerationlocation(nextUnusedIDs.get(typeID), typeID);
int shortenedX = shortenedLocation.getPos().getX();

View file

@ -30,14 +30,16 @@ 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 variantName;
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 variantName, Schematic schematic, int size, EnumPocketType typeID,
int minDepth, int maxDepth, int[] weights) {
public PocketTemplate(String directoryName, String variantName, Schematic schematic, int size,
EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this.directoryName = directoryName;
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
@ -47,8 +49,9 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
this.typeID = typeID;
}
public PocketTemplate(String variantName, int size, EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) {
this(variantName, null, size, typeID, minDepth, maxDepth, weights);
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);
}
int getSize() {
@ -71,6 +74,10 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
return 0; //do not generate
}
String getDirName() {
return directoryName;
}
public String getName() {
return variantName;
}

View file

@ -432,4 +432,11 @@ public class RiftRegistry {
DDTileEntityBase rift = (DDTileEntityBase) rifts.get(riftID).getTileEntity();
return rift.getPocketID();
}
/**
* @param ID the lastGeneratedEntranceDoorID to set
*/
public void setLastGeneratedEntranceDoorID(int ID) {
this.lastGeneratedEntranceDoorID = ID;
}
}

View file

@ -25,8 +25,11 @@ 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.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.nbt.NBTTagCompound;
@ -42,7 +45,8 @@ public class SchematicHandler {
public static final SchematicHandler INSTANCE = new SchematicHandler();
private PocketTemplate personalPocketTemplate;
private PocketTemplate publicPocketTemplate;
private List<PocketTemplate> dungeonTemplates;
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) {
@ -86,9 +90,36 @@ public class SchematicHandler {
}
}
}
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/";
@ -136,8 +167,9 @@ public class SchematicHandler {
List<PocketTemplate> validTemplates = getAllValidVariations(jsonTemplate, maxPocketSize);
//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
for (PocketTemplate template : validTemplates) { //it's okay to "tap" this for-loop, even if validTemplates is empty.
String subDirectory = jsonTemplate.get("directory").getAsString(); //get the subfolder in which the schematics are stored
String extendedTemplatelocation = subDirectory.equals("") ? template.getName() : subDirectory + "/" + template.getName(); //transform the filename accordingly
//Initialising the possible locations/formats for the schematic file
@ -172,7 +204,7 @@ public class SchematicHandler {
Schematic schematic = null;
try {
schematicNBT = CompressedStreamTools.readCompressed(schematicDataStream);
schematic = Schematic.loadFromNBT(schematicNBT);
schematic = Schematic.loadFromNBT(schematicNBT, template.getName());
schematicDataStream.close();
} catch (IOException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file for " + template.getName() + " could not be read as a valid schematic NBT file.", ex);
@ -201,9 +233,10 @@ public class SchematicHandler {
}
private static List<PocketTemplate> getAllValidVariations(JsonObject jsonTemplate, int maxPocketSize) {
String jsonType = jsonTemplate.get("jsonType").getAsString();
EnumPocketType pocketType = EnumPocketType.getFromInt(jsonTemplate.get("pocketType").getAsInt());
JsonArray variations = jsonTemplate.getAsJsonArray("variations");
final String directory = jsonTemplate.get("directory").getAsString();
final String jsonType = jsonTemplate.get("jsonType").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"
@ -247,7 +280,7 @@ public class SchematicHandler {
for (int j = 0; j < weightsJsonArray.size(); j++) {
weights[j] = weightsJsonArray.get(j).getAsInt();
}
PocketTemplate pocketTemplate = new PocketTemplate(variantName, variationSize, pocketType, minDepth, maxDepth, weights);
PocketTemplate pocketTemplate = new PocketTemplate(directory, variantName, variationSize, pocketType, minDepth, maxDepth, weights);
pocketTemplates.add(pocketTemplate);
}
@ -268,6 +301,26 @@ public class SchematicHandler {
return publicPocketTemplate;
}
/**
* @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
*/

View file

@ -1,7 +1,9 @@
package com.zixiken.dimdoors.shared.commands;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.*;
import com.zixiken.dimdoors.shared.tileentities.TileEntityDimDoor;
import com.zixiken.dimdoors.shared.util.Location;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
@ -13,7 +15,6 @@ import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class PocketCommand extends CommandBase {
@ -32,7 +33,7 @@ public class PocketCommand extends CommandBase {
@Override
public String getUsage(ICommandSender sender) {
return "dimpocket <name>";
return "dimpocket <group> <name>";
}
@Override
@ -43,16 +44,60 @@ public class PocketCommand extends CommandBase {
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
if(sender instanceof EntityPlayerMP) {
if (sender instanceof EntityPlayerMP) {
EntityPlayerMP player = getCommandSenderAsPlayer(sender);
BlockPos pos = player.getPosition();
World world = player.world;
if (areArgumentsValid(args, player)) {
DimDoors.log(this.getClass(), "Executing command");
TileEntityDimDoor newRift = (TileEntityDimDoor) world.getTileEntity(pos);
BlockPos pos = player.getPosition();
World world = player.world;
Location playerLoc = new Location(world, pos);
PocketTemplate template = SchematicHandler.INSTANCE.getDungeonTemplate(args[0], args[1]);
Pocket pocket = PocketRegistry.INSTANCE.generatePocketAt(EnumPocketType.DUNGEON, 1, playerLoc, template);
int entranceDoorID = pocket.getEntranceDoorID();
RiftRegistry.INSTANCE.setLastGeneratedEntranceDoorID(entranceDoorID);
}
} else {
DimDoors.log(this.getClass(), "Not executing command, because it wasn't sent by a player.");
}
}
@Override
public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos pos) {
return SchematicHandler.INSTANCE.getDungeonTemplates().stream().map(PocketTemplate::getName).collect(Collectors.toList());
if (args == null || args.length < 2) { //counts an empty ("") argument as an argument as well...
return SchematicHandler.INSTANCE.getDungeonTemplateGroups();
} else if (args.length == 2) {
return SchematicHandler.INSTANCE.getDungeonTemplateNames(args[0]);
} else if (args.length == 3) {
List<String> list = new ArrayList();
list.add("Remove_this");
return list;
} else {
List<String> list = new ArrayList();
list.add("No_seriously");
return list;
}
}
private boolean areArgumentsValid(String[] args, EntityPlayerMP player) {
if (args.length < 2) {
DimDoors.chat(player, "Too few arguments.");
return false;
} else if (args.length > 2) {
DimDoors.chat(player, "Too many arguments.");
return false;
} else { //exactly 2 arguments
if (!SchematicHandler.INSTANCE.getDungeonTemplateGroups().contains(args[0])) {
DimDoors.chat(player, "Group not found.");
return false;
} else if (!SchematicHandler.INSTANCE.getDungeonTemplateNames(args[0]).contains(args[1])) {
DimDoors.chat(player, "Schematic not found.");
return false;
} else {
DimDoors.chat(player, "Generating schematic " + args[1]);
return true;
}
}
}
}

View file

@ -56,9 +56,9 @@ public class Schematic {
private Schematic() {
}
public static Schematic loadFromNBT(NBTTagCompound nbt) {
public static Schematic loadFromNBT(NBTTagCompound nbt, String parName) {
if (!nbt.hasKey("Version")) {
return loadOldDimDoorSchematicFromNBT(nbt);
return loadOldDimDoorSchematicFromNBT(nbt, parName);
}
Schematic schematic = new Schematic();
@ -70,9 +70,9 @@ public class Schematic {
if (nbt.hasKey("Author")) { //Author is not required
schematic.author = metadataCompound.getString("Author");
}
if (nbt.hasKey("Name")) { //Name is not required
schematic.schematicName = metadataCompound.getString("Name");
}
//Name is not required (may be null)
schematic.schematicName = (parName == null || parName.equals("")) && nbt.hasKey("Name") ? metadataCompound.getString("Name") : parName;
if (nbt.hasKey("Date")) { //Date is not required
schematic.creationDate = metadataCompound.getLong("Date");
}
@ -308,12 +308,12 @@ public class Schematic {
return tileEntities;
}
public static Schematic loadOldDimDoorSchematicFromNBT(NBTTagCompound nbt) { //@todo, maybe make this a separate class, so values can be final so they HAVE TO be set in a newly designed constructor?
public static Schematic loadOldDimDoorSchematicFromNBT(NBTTagCompound nbt, String parName) { //@todo, maybe make this a separate class, so values can be final so they HAVE TO be set in a newly designed constructor?
Schematic schematic = new Schematic();
//schematic.version = 1; //already the default value
//schematic.author = "DimDoors"; //already the default value
schematic.schematicName = "This schematic was converted from an MC 1.7.10 DimDoors schematic";
schematic.schematicName = parName.equals("") ? "Auto-converted-DimDoors-for-MC-1.7.10-schematic" : parName;
schematic.creationDate = System.currentTimeMillis();
schematic.requiredMods = new String[]{DimDoors.MODID};