From fa6d32cf0c45c95b2210766f8ec16a5303eddfa3 Mon Sep 17 00:00:00 2001 From: Mathijs Riezebos Date: Mon, 1 May 2017 20:18:00 +0200 Subject: [PATCH] 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. --- .../com/zixiken/dimdoors/shared/Pocket.java | 2 +- .../dimdoors/shared/PocketRegistry.java | 4 ++ .../dimdoors/shared/PocketTemplate.java | 15 +++-- .../zixiken/dimdoors/shared/RiftRegistry.java | 7 ++ .../dimdoors/shared/SchematicHandler.java | 67 +++++++++++++++++-- .../shared/commands/PocketCommand.java | 59 ++++++++++++++-- .../dimdoors/shared/util/Schematic.java | 14 ++-- 7 files changed, 142 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/zixiken/dimdoors/shared/Pocket.java b/src/main/java/com/zixiken/dimdoors/shared/Pocket.java index 8d18a34a..67500798 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/Pocket.java +++ b/src/main/java/com/zixiken/dimdoors/shared/Pocket.java @@ -61,7 +61,7 @@ public class Pocket { return z; } - int getEntranceDoorID() { + public int getEntranceDoorID() { if (riftIDs.isEmpty()) { return -1; } else if (riftIDs.size() == 1) { diff --git a/src/main/java/com/zixiken/dimdoors/shared/PocketRegistry.java b/src/main/java/com/zixiken/dimdoors/shared/PocketRegistry.java index aa90ea64..358be45f 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/PocketRegistry.java +++ b/src/main/java/com/zixiken/dimdoors/shared/PocketRegistry.java @@ -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(); diff --git a/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java b/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java index 9ac2ee27..789fbb18 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java +++ b/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java @@ -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; } diff --git a/src/main/java/com/zixiken/dimdoors/shared/RiftRegistry.java b/src/main/java/com/zixiken/dimdoors/shared/RiftRegistry.java index fe3f434a..6aba351f 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/RiftRegistry.java +++ b/src/main/java/com/zixiken/dimdoors/shared/RiftRegistry.java @@ -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; + } } diff --git a/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java b/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java index d2e23770..2f110ec4 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java +++ b/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java @@ -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 dungeonTemplates; + private List dungeonTemplates; //@todo should this be a Map? Does it need to? It gets reloaded from scratch on ServerStart every time, so... + final private Map> 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 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 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 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 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 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 getDungeonTemplateGroups() { + return new ArrayList(dungeonNameMap.keySet()); + } + + public ArrayList getDungeonTemplateNames(String directory) { + return new ArrayList(dungeonNameMap.get(directory).keySet()); + } + /** * @return the dungeonTemplates */ diff --git a/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java b/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java index ced8caf0..2a739b2e 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java +++ b/src/main/java/com/zixiken/dimdoors/shared/commands/PocketCommand.java @@ -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 "; + return "dimpocket "; } @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 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 list = new ArrayList(); + list.add("Remove_this"); + return list; + } else { + List 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; + } + } } } diff --git a/src/main/java/com/zixiken/dimdoors/shared/util/Schematic.java b/src/main/java/com/zixiken/dimdoors/shared/util/Schematic.java index ef395b3f..d6566651 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/util/Schematic.java +++ b/src/main/java/com/zixiken/dimdoors/shared/util/Schematic.java @@ -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};