Fixed Rotation in Schematic Loader and Partially Overhauled Commands #32

Merged
SenseiKiwi merged 9 commits from master into master 2013-06-26 04:51:57 +00:00
18 changed files with 651 additions and 418 deletions

View File

@@ -200,19 +200,9 @@ public class DimData implements Serializable
this.dimY=new HashMap<Integer, HashMap<Integer, LinkData>>(); this.dimY=new HashMap<Integer, HashMap<Integer, LinkData>>();
} }
this.dimX.remove(locationXCoord); this.dimX.remove(locationXCoord);
this.dimY.put(locationYCoord, dimX); this.dimY.put(locationYCoord, dimX);
this.linksInThisDim.put(locationZCoord, dimY); this.linksInThisDim.put(locationZCoord, dimY);
} }
public LinkData findLinkAtCoords(int locationXCoord, int locationYCoord, int locationZCoord) public LinkData findLinkAtCoords(int locationXCoord, int locationYCoord, int locationZCoord)
@@ -239,40 +229,29 @@ public class DimData implements Serializable
{ {
return null; return null;
} }
return null; return null;
} }
public ArrayList<LinkData> printAllLinkData() public ArrayList<LinkData> printAllLinkData()
{ {
ArrayList links = new ArrayList(); //TODO: We might want to modify this function, but I'm afraid of breaking something right now.
//To begin with, the name is wrong. This doesn't print anything! >_o ~SenseiKiwi
ArrayList<LinkData> links = new ArrayList<LinkData>();
if (this.linksInThisDim == null) if (this.linksInThisDim == null)
{ {
return links; return links;
} }
for (HashMap<Integer, HashMap<Integer, LinkData>> first : this.linksInThisDim.values()) for (HashMap<Integer, HashMap<Integer, LinkData>> first : this.linksInThisDim.values())
{ {
for (HashMap<Integer, LinkData> second : first.values()) for (HashMap<Integer, LinkData> second : first.values())
{ {
for (LinkData linkData : second.values()) for (LinkData linkData : second.values())
{ {
links.add(linkData); links.add(linkData);
} }
} }
} }
return links; return links;
} }
} }

View File

@@ -16,9 +16,6 @@ public class LinkData implements Serializable
public boolean isLocPocket; public boolean isLocPocket;
public int linkOrientation; public int linkOrientation;
public int destDimID; public int destDimID;
public int locDimID; public int locDimID;
@@ -43,7 +40,6 @@ public class LinkData implements Serializable
public LinkData(int locationDimID, int destinationDimID, int locationXCoord, int locationYCoord, int locationZCoord, int destinationXCoord, int destinationYCoord, int destinationZCoord, boolean isPocket,int orientation) public LinkData(int locationDimID, int destinationDimID, int locationXCoord, int locationYCoord, int locationZCoord, int destinationXCoord, int destinationYCoord, int destinationZCoord, boolean isPocket,int orientation)
{ {
this.exists = true; this.exists = true;
this.locXCoord=locationXCoord; this.locXCoord=locationXCoord;
this.locYCoord=locationYCoord; this.locYCoord=locationYCoord;
@@ -57,20 +53,16 @@ public class LinkData implements Serializable
this.locDimID=locationDimID; this.locDimID=locationDimID;
this.isLocPocket=isPocket; this.isLocPocket=isPocket;
this.linkOrientation=orientation; this.linkOrientation=orientation;
} }
public String printLinkData() public String printLinkData()
{ {
//TODO: Rewrite this to make it prettier. @_@ I'm afraid of changing it to ToString() on the off
//chance it'll cause explosions and sadness. Damn serialization! ~SenseiKiwi
String linkInfo; String linkInfo;
linkInfo = String.valueOf(this.locDimID) + "locDimID "+String.valueOf(this.locXCoord)+":locXCoord "+String.valueOf(this.locYCoord)+":locYCoord "+String.valueOf(this.locZCoord)+":locZCoord "; linkInfo = String.valueOf(this.locDimID) + "locDimID "+String.valueOf(this.locXCoord)+":locXCoord "+String.valueOf(this.locYCoord)+":locYCoord "+String.valueOf(this.locZCoord)+":locZCoord ";
linkInfo.concat("\n"+ String.valueOf(this.destDimID)+"DestDimID "+String.valueOf(this.destXCoord)+":destXCoord "+String.valueOf(this.destYCoord)+":destYCoord "+String.valueOf(this.destZCoord)+":destZCoord "); linkInfo.concat("\n"+ String.valueOf(this.destDimID)+"DestDimID "+String.valueOf(this.destXCoord)+":destXCoord "+String.valueOf(this.destYCoord)+":destYCoord "+String.valueOf(this.destZCoord)+":destZCoord ");
return linkInfo; return linkInfo;
} }
} }

View File

@@ -907,41 +907,37 @@ public class SchematicLoader
} }
} }
//determines necessary rotation, reflection, and translation to build the .schematic by finding the difference between the //Compute the Y-axis translation that places our structure correctly
//.schematic incomingLink location which is relative to the .schematic only, and comparing it with the world incoming link coordinates yCooe = incY - incomingLink.getY();
//must also factor in the orientation of the incoming door.
if(orientation==0) //TODO currently broken, only orientation 3 works atm
{
xCooe=-incomingLink.getX()+incX;
yCooe=-incomingLink.getY()+incY;
zCooe=-incomingLink.getZ()+incZ;
} //Loop to actually place the blocks
if(orientation==1)//TODO currently broken, only orientation 3 works atm for ( x = 0; x < width; x++)
{ {
xCooe=-incomingLink.getX()+incX; for ( z = 0; z < length; z++)
yCooe=-incomingLink.getY()+incY;
zCooe=-incomingLink.getZ()+incZ;
}
if(orientation==2)//TODO currently broken, only orientation 3 works atm
{ {
xCooe=-incomingLink.getX()+incX; //Compute the X-axis and Z-axis translations that will shift
yCooe=-incomingLink.getY()+incY; //and rotate our structure properly.
zCooe=-incomingLink.getZ()+incZ; switch (orientation)
}
if(orientation==3)//TODO this only works because it is the default orientation of the pocket dim
{ {
case 0:
xCooe = -incomingLink.getX() + incX; xCooe = -incomingLink.getX() + incX;
yCooe=-incomingLink.getY()+incY;
zCooe = -incomingLink.getZ() + incZ; zCooe = -incomingLink.getZ() + incZ;
break;
case 1:
xCooe = -incomingLink.getX() + incX;
zCooe = -incomingLink.getZ() + incZ;
break;
case 2:
xCooe = -incomingLink.getX() + incX;
zCooe = -incomingLink.getZ() + incZ;
break;
case 3:
xCooe = -incomingLink.getX() + incX;
zCooe = -incomingLink.getZ() + incZ;
break;
} }
//loop to actually place the blocks for ( y = 0; y < height; y++)
for ( x = 0; x < width; ++x)
{
for ( y = 0; y < height; ++y)
{
for ( z = 0; z < length; ++z)
{ {
int index = y * width * length + z * width + x; int index = y * width * length + z * width + x;

View File

@@ -1,9 +1,9 @@
package StevenDimDoors.mod_pocketDim.commands; package StevenDimDoors.mod_pocketDim.commands;
import java.io.File;
import java.util.Collection; import java.util.Collection;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.MathHelper;
import StevenDimDoors.mod_pocketDim.DungeonGenerator; import StevenDimDoors.mod_pocketDim.DungeonGenerator;
import StevenDimDoors.mod_pocketDim.LinkData; import StevenDimDoors.mod_pocketDim.LinkData;
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
@@ -15,7 +15,7 @@ public class CommandCreateDungeonRift extends DDCommandBase
private CommandCreateDungeonRift() private CommandCreateDungeonRift()
{ {
super("dd-rift"); super("dd-rift", "<dungeon name | 'list' | 'random'>");
} }
public static CommandCreateDungeonRift instance() public static CommandCreateDungeonRift instance()
@@ -27,71 +27,101 @@ public class CommandCreateDungeonRift extends DDCommandBase
} }
@Override @Override
public void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
DungeonHelper dungeonHelper = DungeonHelper.instance(); DungeonHelper dungeonHelper = DungeonHelper.instance();
if(command==null||sender.worldObj.isRemote) if (sender.worldObj.isRemote)
{ {
return; return DDCommandResult.SUCCESS;
}
if (command.length == 0)
{
return DDCommandResult.TOO_FEW_ARGUMENTS;
}
if (command.length > 1)
{
return DDCommandResult.TOO_MANY_ARGUMENTS;
} }
LinkData link = new LinkData(sender.worldObj.provider.dimensionId, 0, if (command[0].equals("list"))
(int) sender.posX,
(int) sender.posY + 1,
(int) sender.posZ,
(int) sender.posX,
(int) sender.posY + 1,
(int) sender.posZ,true,3);
if(command.length!=0&&command[0].equals("random"))
{
sender.sendChatToPlayer("Created dungeon rift");
dimHelper.instance.createLink(link);
link = dimHelper.instance.createPocket(link,true, true);
}
else if (command.length != 0 && command[0].equals("list"))
{ {
Collection<String> dungeonNames = dungeonHelper.getDungeonNames(); Collection<String> dungeonNames = dungeonHelper.getDungeonNames();
for (String name : dungeonNames) for (String name : dungeonNames)
{ {
getCommandSenderAsPlayer(sender).sendChatToPlayer(name); sender.sendChatToPlayer(name);
}
}
else if(command.length!=0)
{
for(DungeonGenerator dungeonGen : dungeonHelper.registeredDungeons)
{
String dungeonName =dungeonGen.schematicPath.toLowerCase();
if(dungeonName.contains(command[0].toLowerCase()))
{
link = dimHelper.instance.createPocket(link,true, true);
dimHelper.dimList.get(link.destDimID).dungeonGenerator=dungeonGen;
sender.sendChatToPlayer("Genned dungeon " +dungeonName);
return;
}
}
for(DungeonGenerator dungeonGen : dungeonHelper.customDungeons)
{
String dungeonName =dungeonGen.schematicPath.toLowerCase();
if(dungeonName.contains(command[0].toLowerCase()))
{
link = dimHelper.instance.createPocket(link,true, true);
dimHelper.dimList.get(link.destDimID).dungeonGenerator=dungeonGen;
sender.sendChatToPlayer("Genned dungeon " +dungeonName);
return;
}
}
if(command!=null&&!command[0].equals("random"))
{
sender.sendChatToPlayer("could not find dungeon, 'list' for list of dungeons");
} }
sender.sendChatToPlayer("");
} }
else else
{ {
sender.sendChatToPlayer("invalid arguments- 'random' for random dungeon, or 'list' for dungeon names"); DungeonGenerator result;
int x = (int) sender.posX;
int y = (int) sender.posY;
int z = (int) sender.posZ;
LinkData link = new LinkData(sender.worldObj.provider.dimensionId, 0, x, y + 1, z, x, y + 1, z, true, 3);
if (command[0].equals("random"))
{
dimHelper.instance.createLink(link);
link = dimHelper.instance.createPocket(link, true, true);
sender.sendChatToPlayer("Created a rift to a random dungeon (Dimension ID = " + link.destDimID + ").");
}
else
{
result = findDungeonByPartialName(command[0], dungeonHelper.registeredDungeons);
if (result == null)
{
result = findDungeonByPartialName(command[0], dungeonHelper.customDungeons);
}
//Check if we found any matches
if (result != null)
{
//Create a rift to our selected dungeon and notify the player
link = dimHelper.instance.createPocket(link, true, true);
dimHelper.dimList.get(link.destDimID).dungeonGenerator = result;
sender.sendChatToPlayer("Created a rift to \"" + getSchematicName(result) + "\" dungeon (Dimension ID = " + link.destDimID + ").");
}
else
{
//No matches!
return new DDCommandResult("Error: The specified dungeon was not found. Use 'list' to see a list of the available dungeons.");
} }
} }
} }
return DDCommandResult.SUCCESS;
}
private DungeonGenerator findDungeonByPartialName(String query, Collection<DungeonGenerator> dungeons)
{
//Search for the shortest dungeon name that contains the lowercase query string.
String dungeonName;
String normalQuery = query.toLowerCase();
DungeonGenerator bestMatch = null;
int matchLength = Integer.MAX_VALUE;
for (DungeonGenerator dungeon : dungeons)
{
//We need to extract the file's name. Comparing against schematicPath could
//yield false matches if the query string is contained within the path.
dungeonName = getSchematicName(dungeon).toLowerCase();
if (dungeonName.length() < matchLength && dungeonName.contains(normalQuery))
{
matchLength = dungeonName.length();
bestMatch = dungeon;
}
}
return bestMatch;
}
private static String getSchematicName(DungeonGenerator dungeon)
{
//TODO: Move this to DungeonHelper and use it for all schematic name parsing.
//In the future, we really should include the schematic's name as part of DungeonGenerator
//to avoid redoing this work constantly.
File schematic = new File(dungeon.schematicPath);
String fileName = schematic.getName();
return fileName.substring(0, fileName.length() - DungeonHelper.SCHEMATIC_FILE_EXTENSION.length());
}
}

View File

@@ -14,7 +14,7 @@ public class CommandDeleteAllLinks extends DDCommandBase
private CommandDeleteAllLinks() private CommandDeleteAllLinks()
{ {
super("dd-deletelinks"); super("dd-deletelinks", "FIXME");
} }
public static CommandDeleteAllLinks instance() public static CommandDeleteAllLinks instance()
@@ -26,7 +26,7 @@ public class CommandDeleteAllLinks extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
int linksRemoved=0; int linksRemoved=0;
int targetDim; int targetDim;
@@ -80,5 +80,6 @@ public class CommandDeleteAllLinks extends DDCommandBase
sender.sendChatToPlayer("Removed " + linksRemoved + " links."); sender.sendChatToPlayer("Removed " + linksRemoved + " links.");
} }
} }
return DDCommandResult.SUCCESS; //TEMPORARY HACK
} }
} }

View File

@@ -14,7 +14,7 @@ public class CommandDeleteDimensionData extends DDCommandBase
private CommandDeleteDimensionData() private CommandDeleteDimensionData()
{ {
super("dd-deletedimension"); super("dd-deletedimension", "FIXME");
} }
public static CommandDeleteDimensionData instance() public static CommandDeleteDimensionData instance()
@@ -26,7 +26,7 @@ public class CommandDeleteDimensionData extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
int linksRemoved=0; int linksRemoved=0;
int targetDim; int targetDim;
@@ -90,5 +90,6 @@ public class CommandDeleteDimensionData extends DDCommandBase
sender.sendChatToPlayer("Error- dimension "+targetDim+" not registered with dimDoors"); sender.sendChatToPlayer("Error- dimension "+targetDim+" not registered with dimDoors");
} }
} }
return DDCommandResult.SUCCESS; //TEMPORARY HACK
} }
} }

View File

@@ -15,7 +15,7 @@ public class CommandDeleteRifts extends DDCommandBase
private CommandDeleteRifts() private CommandDeleteRifts()
{ {
super("dd-???"); super("dd-???", "FIXME");
} }
public static CommandDeleteRifts instance() public static CommandDeleteRifts instance()
@@ -27,7 +27,7 @@ public class CommandDeleteRifts extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
int linksRemoved=0; int linksRemoved=0;
int targetDim; int targetDim;
@@ -84,5 +84,6 @@ public class CommandDeleteRifts extends DDCommandBase
sender.sendChatToPlayer("Removed "+linksRemoved+" rifts."); sender.sendChatToPlayer("Removed "+linksRemoved+" rifts.");
} }
} }
return DDCommandResult.SUCCESS; //TEMPORARY HACK
} }
} }

View File

@@ -12,7 +12,9 @@ public class CommandEndDungeonCreation extends DDCommandBase
private CommandEndDungeonCreation() private CommandEndDungeonCreation()
{ {
super("dd-export"); super("dd-export", new String[] {
"<dungeon type> <dungeon name> <'open' | 'closed'> [weight] ['override']",
"<schematic name> override" } );
} }
public static CommandEndDungeonCreation instance() public static CommandEndDungeonCreation instance()
@@ -24,57 +26,160 @@ public class CommandEndDungeonCreation extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
DungeonHelper dungeonHelper = DungeonHelper.instance(); /*
DDProperties properties = DDProperties.instance(); * There are two versions of this command. One version takes 3 to 5 arguments consisting
* of the information needed for a proper schematic name and an optional override argument.
* The override argument only allows the user to export any dimension, even if it wasn't
* meant for custom dungeon creation. It does not allow the user to export a dungeon with
* invalid tags.
*
* If the user wishes to name his schematic in a different format, then he will have to use
* the 2-argument version of this command, which accepts a schematic name and a mandatory
* override argument.
*/
DungeonHelper dungeonHelper = DungeonHelper.instance();
if (!dungeonHelper.isCustomDungeon(sender.worldObj.provider.dimensionId))
{
if (command.length < 2) if (command.length < 2)
{ {
sender.sendChatToPlayer("Must have started dungeon creation, use argument OVERRIDE to export anyway"); return DDCommandResult.TOO_FEW_ARGUMENTS;
return; }
if (command.length > 5)
{
return DDCommandResult.TOO_MANY_ARGUMENTS;
} }
else if (!command[1].contains("OVERRIDE")) //Check if we received the 2-argument version
if (command.length == 2)
{ {
sender.sendChatToPlayer("Must have started dungeon creation, use argument OVERRIDE to export anyway"); if (command[1].equalsIgnoreCase("override"))
return; {
//Check that the schematic name is a legal name
if (DungeonHelper.SchematicNamePattern.matcher(command[0]).matches())
{
//Export the schematic
return exportDungeon(sender, command[0]);
}
else
{
//The schematic name contains illegal characters. Inform the user.
return new DDCommandResult("Error: Invalid schematic name. Please use only letters, numbers, dashes, and underscores.");
}
}
else
{
//The command is malformed in some way. Assume that the user meant to use
//the 3-argument version and report an error.
return DDCommandResult.TOO_FEW_ARGUMENTS;
}
} }
//The user must have used the 3-argument version of this command
//Check if the current dimension is a pocket for building custom dungeons or if the override argument was used.
if (!dungeonHelper.isCustomDungeon(sender.worldObj.provider.dimensionId) ||
!command[command.length - 1].equalsIgnoreCase("override"))
{
//This dimension may not be exported without overriding!
return new DDCommandResult("Error: The current dimension was not made for dungeon creation. Use the 'override' argument to export anyway.");
} }
int x = (int) sender.posX; //TODO: Why do we check remoteness here but not before? And why not for the other export case?
int y = (int) sender.posY; //Something feels wrong... ~SenseiKiwi
int z = (int) sender.posZ;
if (command.length == 0) if (!sender.worldObj.isRemote)
{ {
sender.sendChatToPlayer("Must name file"); //TODO: This validation should be in DungeonHelper or in another class. We should move it
//once the during the save file format rewrite. ~SenseiKiwi
if (!dungeonHelper.validateDungeonType(command[0]))
{
return new DDCommandResult("Error: Invalid dungeon type. Please use one of the existing types.");
} }
else if(!sender.worldObj.isRemote) if (!DungeonHelper.DungeonNamePattern.matcher(command[1]).matches())
{ {
//Check that the dungeon name is valid to prevent directory traversal and other forms of abuse return new DDCommandResult("Error: Invalid dungeon name. Please use only letters, numbers, and dashes.");
if (DungeonHelper.NamePattern.matcher(command[0]).matches()) }
if (!command[2].equalsIgnoreCase("open") && !command[2].equalsIgnoreCase("closed"))
{ {
String exportPath = properties.CustomSchematicDirectory + "/" + command[0] + ".schematic"; return new DDCommandResult("Error: Please specify whether the dungeon is 'open' or 'closed'.");
if (dungeonHelper.exportDungeon(sender.worldObj, x, y, z, exportPath)) }
//If there are no more argument, export the dungeon.
if (command.length == 3)
{ {
sender.sendChatToPlayer("Saved dungeon schematic in " + exportPath); return exportDungeon(sender, join(command, "_", 0, 3));
}
//Validate the 4th argument, which might be the weight or might be "override".
try
{
int weight = Integer.parseInt(command[3]);
if (weight >= 0 && weight <= DungeonHelper.MAX_DUNGEON_WEIGHT)
{
return exportDungeon(sender, join(command, "_", 0, 4));
}
}
catch (Exception e)
{
//The 4th argument could be "override", but only if it's the last argument.
//In that case, we assume the default dungeon weight.
if (command.length == 4 && command[3].equalsIgnoreCase("override"))
{
return exportDungeon(sender, join(command, "_", 0, 3));
}
}
//If we've reached this point, then we must have an invalid weight.
return new DDCommandResult("Invalid dungeon weight. Please specify a weight between 0 and " + DungeonHelper.MAX_DUNGEON_WEIGHT + ", inclusive.");
}
return DDCommandResult.SUCCESS;
}
private static DDCommandResult exportDungeon(EntityPlayer player, String name)
{
DDProperties properties = DDProperties.instance();
DungeonHelper dungeonHelper = DungeonHelper.instance();
int x = (int) player.posX;
int y = (int) player.posY;
int z = (int) player.posZ;
String exportPath = properties.CustomSchematicDirectory + File.separator + name + ".schematic";
if (dungeonHelper.exportDungeon(player.worldObj, x, y, z, exportPath))
{
player.sendChatToPlayer("Saved dungeon schematic in " + exportPath);
dungeonHelper.registerCustomDungeon(new File(exportPath)); dungeonHelper.registerCustomDungeon(new File(exportPath));
return DDCommandResult.SUCCESS;
} }
else else
{ {
sender.sendChatToPlayer("Failed to save dungeon schematic!"); return new DDCommandResult("Error: Failed to save dungeon schematic!");
} }
} }
else
private static String join(String[] source, String delimiter, int start, int end)
{ {
sender.sendChatToPlayer("Invalid schematic name. Please use only letters, numbers, and underscores."); //TODO: This function should be moved to a helper, but we have several single-function helpers as is.
} //I find that to be worse than keeping this private. ~SenseiKiwi
}
int index;
int length = 0;
StringBuilder buffer;
for (index = start; index < end; index++)
{
length += source[index].length();
}
length += (end - start - 1) * delimiter.length();
buffer = new StringBuilder(length);
buffer.append(source[start]);
for (index = start + 1; index < end; index++)
{
buffer.append(delimiter);
buffer.append(source[index]);
}
return buffer.toString();
} }
} }

View File

@@ -1,7 +1,6 @@
package StevenDimDoors.mod_pocketDim.commands; package StevenDimDoors.mod_pocketDim.commands;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import StevenDimDoors.mod_pocketDim.DimData; import StevenDimDoors.mod_pocketDim.DimData;
@@ -14,7 +13,7 @@ public class CommandPrintDimensionData extends DDCommandBase
private CommandPrintDimensionData() private CommandPrintDimensionData()
{ {
super("dd-dimensiondata"); super("dd-dimensiondata", "[dimension number]");
} }
public static CommandPrintDimensionData instance() public static CommandPrintDimensionData instance()
@@ -26,10 +25,10 @@ public class CommandPrintDimensionData extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
int targetDim; int targetDim;
boolean shouldGo= true; DimData dimData;
if (command.length == 0) if (command.length == 0)
{ {
@@ -37,34 +36,34 @@ public class CommandPrintDimensionData extends DDCommandBase
} }
else if (command.length == 1) else if (command.length == 1)
{ {
targetDim = parseInt(sender, command[0]); try
if(!dimHelper.dimList.containsKey(targetDim))
{ {
sender.sendChatToPlayer("Error- dim "+targetDim+" not registered"); targetDim = Integer.parseInt(command[0]);
shouldGo=false; }
catch (Exception ex)
{
return DDCommandResult.INVALID_DIMENSION_ID;
} }
} }
else else
{ {
targetDim=0; return DDCommandResult.TOO_MANY_ARGUMENTS;
shouldGo=false;
sender.sendChatToPlayer("Error-Invalid argument, print_dim_data <targetDimID> or blank for current dim");
} }
if(shouldGo) dimData = dimHelper.dimList.get(targetDim);
if (dimData == null)
{ {
if(dimHelper.dimList.containsKey(targetDim)) return DDCommandResult.UNREGISTERED_DIMENSION;
{ }
DimData dimData = dimHelper.dimList.get(targetDim);
Collection<LinkData> links = new ArrayList<LinkData>();
links.addAll( dimData.printAllLinkData());
ArrayList<LinkData> links = dimData.printAllLinkData();
sender.sendChatToPlayer("Dimension ID = " + dimData.dimID);
sender.sendChatToPlayer("Dimension Depth = " + dimData.depth);
for (LinkData link : links) for (LinkData link : links)
{ {
sender.sendChatToPlayer(link.printLinkData()); sender.sendChatToPlayer(link.printLinkData());
} }
sender.sendChatToPlayer("DimID= "+dimData.dimID+"Dim depth = "+dimData.depth); return DDCommandResult.SUCCESS;
}
}
} }
} }

View File

@@ -2,6 +2,8 @@ package StevenDimDoors.mod_pocketDim.commands;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import StevenDimDoors.mod_pocketDim.DimData; import StevenDimDoors.mod_pocketDim.DimData;
@@ -14,7 +16,7 @@ public class CommandPruneDimensions extends DDCommandBase
private CommandPruneDimensions() private CommandPruneDimensions()
{ {
super("dd-prune"); super("dd-prune", "['delete']");
} }
public static CommandPruneDimensions instance() public static CommandPruneDimensions instance()
@@ -26,38 +28,46 @@ public class CommandPruneDimensions extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
int numRemoved=0; if (command.length > 1)
ArrayList<Integer> dimsWithLinks = new ArrayList<Integer>(); {
return DDCommandResult.TOO_MANY_ARGUMENTS;
}
if (command.length == 1 && !command[0].equalsIgnoreCase("delete"))
{
return DDCommandResult.INVALID_ARGUMENTS;
}
int removedCount = 0;
boolean deleteFolders = (command.length == 1);
Set<Integer> linkedDimensions = new HashSet<Integer>();
Collection<DimData> allDims = new ArrayList<DimData>(); Collection<DimData> allDims = new ArrayList<DimData>();
allDims.addAll(dimHelper.dimList.values()); allDims.addAll(dimHelper.dimList.values());
for (DimData data : allDims) for (DimData data : allDims)
{ {
for (LinkData link : data.printAllLinkData()) for (LinkData link : data.printAllLinkData())
{ {
if(!dimsWithLinks.contains(link.destDimID)) linkedDimensions.add(link.destDimID);
{
dimsWithLinks.add(link.destDimID);
}
} }
} }
for (LinkData link : dimHelper.instance.interDimLinkList.values()) for (LinkData link : dimHelper.instance.interDimLinkList.values())
{ {
if(!dimsWithLinks.contains(link.destDimID)) linkedDimensions.add(link.destDimID);
{
dimsWithLinks.add(link.destDimID);
}
} }
for (DimData data : allDims) for (DimData data : allDims)
{ {
if(!dimsWithLinks.contains(data.dimID)) if (!linkedDimensions.contains(data.dimID))
{ {
dimHelper.dimList.remove(data.dimID); if (dimHelper.instance.pruneDimension(data, deleteFolders))
numRemoved++; {
removedCount++;
}
} }
} }
dimHelper.instance.save(); dimHelper.instance.save();
sender.sendChatToPlayer("Removed " + numRemoved + " unreachable pocket dims."); sender.sendChatToPlayer("Removed " + removedCount + " unreachable pocket dims.");
return DDCommandResult.SUCCESS;
} }
} }

View File

@@ -1,43 +0,0 @@
package StevenDimDoors.mod_pocketDim.commands;
import java.io.File;
import net.minecraft.entity.player.EntityPlayer;
import StevenDimDoors.mod_pocketDim.DDProperties;
import StevenDimDoors.mod_pocketDim.DimData;
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
public class CommandRegenPocket extends DDCommandBase
{
private static CommandRegenPocket instance = null;
private CommandRegenPocket()
{
super("dd-regenDungeons");
}
public static CommandRegenPocket instance()
{
if (instance == null)
instance = new CommandRegenPocket();
return instance;
}
@Override
protected void processCommand(EntityPlayer sender, String[] command)
{
DungeonHelper dungeonHelper = DungeonHelper.instance();
DDProperties properties = DDProperties.instance();
for(DimData data : dimHelper.dimList.values())
{
if(data.isDimRandomRift)
{
dimHelper.instance.regenPocket(data);
}
}
}
}

View File

@@ -0,0 +1,51 @@
package StevenDimDoors.mod_pocketDim.commands;
import net.minecraft.entity.player.EntityPlayer;
import StevenDimDoors.mod_pocketDim.DimData;
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
public class CommandResetDungeons extends DDCommandBase
{
private static CommandResetDungeons instance = null;
private CommandResetDungeons()
{
super("dd-resetdungeons", "");
}
public static CommandResetDungeons instance()
{
if (instance == null)
instance = new CommandResetDungeons();
return instance;
}
@Override
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{
if (command.length > 0)
{
return DDCommandResult.TOO_FEW_ARGUMENTS;
}
int dungeonCount = 0;
int resetCount = 0;
for (DimData data : dimHelper.dimList.values())
{
if (data.isDimRandomRift)
{
dungeonCount++;
if (dimHelper.instance.resetPocket(data))
{
resetCount++;
}
}
}
//Notify the user of the results
sender.sendChatToPlayer("Reset complete. " + resetCount + " out of " + dungeonCount + " dungeons were reset.");
return DDCommandResult.SUCCESS;
}
}

View File

@@ -10,7 +10,7 @@ public class CommandStartDungeonCreation extends DDCommandBase
private CommandStartDungeonCreation() private CommandStartDungeonCreation()
{ {
super("dd-create"); super("dd-create", "");
} }
public static CommandStartDungeonCreation instance() public static CommandStartDungeonCreation instance()
@@ -22,10 +22,18 @@ public class CommandStartDungeonCreation extends DDCommandBase
} }
@Override @Override
protected void processCommand(EntityPlayer sender, String[] command) protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
{ {
//TODO: Some commands have isRemote checks, some do not. Why? Can commands even run locally anyway?
//What does it mean when you run a command locally? ~SenseiKiwi
if (!sender.worldObj.isRemote) if (!sender.worldObj.isRemote)
{ {
if (command.length > 0)
{
return DDCommandResult.TOO_MANY_ARGUMENTS;
}
//Place a door leading to a pocket dimension where the player is standing. //Place a door leading to a pocket dimension where the player is standing.
//The pocket dimension will be serve as a room for the player to build a dungeon. //The pocket dimension will be serve as a room for the player to build a dungeon.
int x = (int) sender.posX; int x = (int) sender.posX;
@@ -34,7 +42,8 @@ public class CommandStartDungeonCreation extends DDCommandBase
LinkData link = DungeonHelper.instance().createCustomDungeonDoor(sender.worldObj, x, y, z); LinkData link = DungeonHelper.instance().createCustomDungeonDoor(sender.worldObj, x, y, z);
//Notify the player //Notify the player
sender.sendChatToPlayer("Created a door to a pocket dimension (ID = " + link.destDimID + "). Please build your dungeon there."); sender.sendChatToPlayer("Created a door to a pocket dimension (Dimension ID = " + link.destDimID + "). Please build your dungeon there.");
} }
return DDCommandResult.SUCCESS;
} }
} }

View File

@@ -12,16 +12,25 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent;
public abstract class DDCommandBase extends CommandBase public abstract class DDCommandBase extends CommandBase
{ {
private String name; private String name;
private String[] formats;
public DDCommandBase(String name) public DDCommandBase(String name, String format)
{ {
this.name = name; this.name = name;
this.formats = new String[] { format };
}
public DDCommandBase(String name, String[] formats)
{
this.name = name;
this.formats = formats;
} }
/* /*
* When overridden in a derived class, processes the command sent by the server. * When overridden in a derived class, processes the command sent by the server
* and returns a status code and message for the result of the operation.
*/ */
protected abstract void processCommand(EntityPlayer sender, String[] command); protected abstract DDCommandResult processCommand(EntityPlayer sender, String[] command);
public final String getCommandName() public final String getCommandName()
{ {
@@ -43,6 +52,21 @@ public abstract class DDCommandBase extends CommandBase
public final void processCommand(ICommandSender sender, String[] command) public final void processCommand(ICommandSender sender, String[] command)
{ {
//Forward the command //Forward the command
processCommand(getCommandSenderAsPlayer(sender), command); EntityPlayer player = getCommandSenderAsPlayer(sender);
DDCommandResult result = processCommand(player, command);
//If the command failed, send the player a status message.
if (result.failed())
{
if (result.shouldPrintUsage())
{
//Send the argument formats for this command
for (String format : formats)
{
player.sendChatToPlayer("Usage: " + name + " " + format);
}
}
player.sendChatToPlayer(result.getMessage());
}
} }
} }

View File

@@ -0,0 +1,55 @@
package StevenDimDoors.mod_pocketDim.commands;
public class DDCommandResult {
public static final DDCommandResult SUCCESS = new DDCommandResult(0, "", false);
public static final DDCommandResult TOO_FEW_ARGUMENTS = new DDCommandResult(1, "Error: Too few arguments passed to the command", true);
public static final DDCommandResult TOO_MANY_ARGUMENTS = new DDCommandResult(2, "Error: Too many arguments passed to the command", true);
public static final DDCommandResult INVALID_DIMENSION_ID = new DDCommandResult(3, "Error: Invalid dimension ID", true);
public static final DDCommandResult UNREGISTERED_DIMENSION = new DDCommandResult(4, "Error: Dimension is not registered", false);
public static final DDCommandResult INVALID_ARGUMENTS = new DDCommandResult(5, "Error: Invalid arguments passed to the command.", true);
public static final int CUSTOM_ERROR_CODE = -1;
private int code;
private String message;
private boolean printUsage;
private DDCommandResult(int code, String message, boolean printUsage)
{
this.code = code;
this.message = message;
this.printUsage = printUsage;
}
public DDCommandResult(String message)
{
this(CUSTOM_ERROR_CODE, message, false);
}
public DDCommandResult(String message, boolean printUsage)
{
this(CUSTOM_ERROR_CODE, message, printUsage);
}
public boolean failed()
{
return (code != 0);
}
public int getCode()
{
return code;
}
public String getMessage()
{
return message;
}
public boolean shouldPrintUsage()
{
return printUsage;
}
}

View File

@@ -31,11 +31,12 @@ 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 NamePattern = Pattern.compile("[A-Za-z0-9_\\-]+"); public static final Pattern SchematicNamePattern = Pattern.compile("[A-Za-z0-9_\\-]+");
public static final Pattern DungeonNamePattern = Pattern.compile("[A-Za-z0-9\\-]+");
private static final String SCHEMATIC_FILE_EXTENSION = ".schematic"; public static final String SCHEMATIC_FILE_EXTENSION = ".schematic";
private static final int DEFAULT_DUNGEON_WEIGHT = 100; private static final int DEFAULT_DUNGEON_WEIGHT = 100;
private static final int MAX_DUNGEON_WEIGHT = 10000; //Used to prevent overflows and math breaking down public static final int MAX_DUNGEON_WEIGHT = 10000; //Used to prevent overflows and math breaking down
private static final String HUB_DUNGEON_TYPE = "Hub"; private static final String HUB_DUNGEON_TYPE = "Hub";
private static final String TRAP_DUNGEON_TYPE = "Trap"; private static final String TRAP_DUNGEON_TYPE = "Trap";
@@ -166,6 +167,12 @@ public class DungeonHelper
return customDungeonStatus.containsKey(dimensionID); return customDungeonStatus.containsKey(dimensionID);
} }
public boolean validateDungeonType(String type)
{
//Check if the dungeon type is valid
return dungeonTypeChecker.contains(type.toLowerCase());
}
public boolean validateSchematicName(String name) public boolean validateSchematicName(String name)
{ {
String[] dungeonData; String[] dungeonData;
@@ -184,7 +191,7 @@ public class DungeonHelper
return false; return false;
//Check if the name is valid //Check if the name is valid
if (!NamePattern.matcher(dungeonData[1]).matches()) if (!SchematicNamePattern.matcher(dungeonData[1]).matches())
return false; return false;
//Check if the open/closed flag is present //Check if the open/closed flag is present

View File

@@ -38,6 +38,7 @@ import StevenDimDoors.mod_pocketDim.DimData;
import StevenDimDoors.mod_pocketDim.LinkData; import StevenDimDoors.mod_pocketDim.LinkData;
import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream; import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream;
import StevenDimDoors.mod_pocketDim.PacketHandler; import StevenDimDoors.mod_pocketDim.PacketHandler;
import StevenDimDoors.mod_pocketDim.Point3D;
import StevenDimDoors.mod_pocketDim.TileEntityRift; import StevenDimDoors.mod_pocketDim.TileEntityRift;
import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.mod_pocketDim;
import StevenDimDoors.mod_pocketDim.world.LimboProvider; import StevenDimDoors.mod_pocketDim.world.LimboProvider;
@@ -64,7 +65,7 @@ public class dimHelper extends DimensionManager
* ArrayList containing any blocks in limbo that have been placed by the player. Cycled through in the common tick manager * ArrayList containing any blocks in limbo that have been placed by the player. Cycled through in the common tick manager
* @Return * @Return
*/ */
public static ArrayList blocksToDecay= new ArrayList(); public static ArrayList<Point3D> blocksToDecay = new ArrayList<Point3D>();
/** /**
* instance of the dimHelper * instance of the dimHelper
@@ -812,13 +813,14 @@ public class dimHelper extends DimensionManager
} }
} }
public void regenPocket(DimData dimData) public boolean resetPocket(DimData dimData)
{ {
if(this.getWorld(dimData.dimID)!=null ||!dimData.isPocket) //TODO: Should we add a check to see if the dimension is currently loaded? How could we check that? ~SenseiKiwi
if (!dimData.isPocket || getWorld(dimData.dimID) != null)
{ {
return; return false;
} }
File save = new File( this.getCurrentSaveRootDirectory()+"/DimensionalDoors/pocketDimID" + dimData.dimID); File save = new File(getCurrentSaveRootDirectory() + "/DimensionalDoors/pocketDimID" + dimData.dimID);
DeleteFolder.deleteFolder(save); DeleteFolder.deleteFolder(save);
dimData.hasBeenFilled = false; dimData.hasBeenFilled = false;
dimData.hasDoor = false; dimData.hasDoor = false;
@@ -829,16 +831,30 @@ public class dimHelper extends DimensionManager
if (linkOut != null) if (linkOut != null)
{ {
linkOut.hasGennedDoor = false; linkOut.hasGennedDoor = false;
} }
} }
return true;
} }
public boolean pruneDimension(DimData dimData, boolean deleteFolder)
{
//TODO: Should we add a check to see if the dimension is currently loaded? How could we check that? ~SenseiKiwi
//TODO: All the logic for checking that this is an isolated pocket should be moved in here.
if (!dimData.isPocket || getWorld(dimData.dimID) != null)
{
return false;
}
dimList.remove(dimData.dimID);
if (deleteFolder)
{
File save = new File(getCurrentSaveRootDirectory() + "/DimensionalDoors/pocketDimID" + dimData.dimID);
DeleteFolder.deleteFolder(save);
}
return true;
}
/** /**
* method called when the client disconects/server stops to unregister dims. * method called when the client disconnects/server stops to unregister dims.
* @Return * @Return
*/ */
public void unregsisterDims() public void unregsisterDims()

View File

@@ -29,7 +29,7 @@ import StevenDimDoors.mod_pocketDim.commands.CommandDeleteRifts;
import StevenDimDoors.mod_pocketDim.commands.CommandEndDungeonCreation; import StevenDimDoors.mod_pocketDim.commands.CommandEndDungeonCreation;
import StevenDimDoors.mod_pocketDim.commands.CommandPrintDimensionData; import StevenDimDoors.mod_pocketDim.commands.CommandPrintDimensionData;
import StevenDimDoors.mod_pocketDim.commands.CommandPruneDimensions; import StevenDimDoors.mod_pocketDim.commands.CommandPruneDimensions;
import StevenDimDoors.mod_pocketDim.commands.CommandRegenPocket; import StevenDimDoors.mod_pocketDim.commands.CommandResetDungeons;
import StevenDimDoors.mod_pocketDim.commands.CommandStartDungeonCreation; import StevenDimDoors.mod_pocketDim.commands.CommandStartDungeonCreation;
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
import StevenDimDoors.mod_pocketDim.helpers.dimHelper; import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
@@ -391,7 +391,7 @@ public class mod_pocketDim
@ServerStarting @ServerStarting
public void serverStarting(FMLServerStartingEvent event) public void serverStarting(FMLServerStartingEvent event)
{ {
CommandRegenPocket.instance().register(event); CommandResetDungeons.instance().register(event);
CommandCreateDungeonRift.instance().register(event); CommandCreateDungeonRift.instance().register(event);
CommandDeleteAllLinks.instance().register(event); CommandDeleteAllLinks.instance().register(event);
CommandDeleteDimensionData.instance().register(event); CommandDeleteDimensionData.instance().register(event);