Mapping coordinates to Pocket IDs and back

-Changed the Pocket placement algorithm. Instead of following a
rectangular spiral path expanding outwards from (0;0), Pockets now get
placed in a fan-shaped area expanding from (0;0) to (infinity;infinity).
-Changed maximum configurable grid size and defaulted to that
-Added a way to retrieve the Pocket ID from a Location
-Schematic loading streams are only closed if they were opened to begin
with
-Added some easier ways of testing if a Dimension is a Pocket dimension
This commit is contained in:
Mathijs Riezebos 2017-05-05 17:35:02 +02:00
parent 7574e61ede
commit 53568707f0
6 changed files with 134 additions and 41 deletions

View file

@ -23,8 +23,8 @@ public class DDConfig {
public static final boolean HAVE_CONFIG_DEFAULTS_BEEN_CHECKED_FOR_CORRECTNESS = false; //@todo check this at each non-alpha release. This field does not have a use in the mod itself, but should ensure that the developers of this mod, don't forget to reset the config defaults to the right values before releasing a non-alpha release public static final boolean HAVE_CONFIG_DEFAULTS_BEEN_CHECKED_FOR_CORRECTNESS = false; //@todo check this at each non-alpha release. This field does not have a use in the mod itself, but should ensure that the developers of this mod, don't forget to reset the config defaults to the right values before releasing a non-alpha release
public static File configurationFolder; public static File configurationFolder;
private static int pocketGridSize = 8; private static int pocketGridSize = 32;
private static int maxPocketSize = 4; private static int maxPocketSize = 15;
private static int privatePocketSize = 3; private static int privatePocketSize = 3;
private static int publicPocketSize = 2; private static int publicPocketSize = 2;
private static int baseDimID = 684; private static int baseDimID = 684;
@ -68,17 +68,17 @@ public class DDConfig {
//@todo a comment in the config files about how these values only influence new worlds //@todo a comment in the config files about how these values only influence new worlds
Property prop; Property prop;
pocketGridSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "pocketGridSize", pocketGridSize, pocketGridSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "pocketGridSize", pocketGridSize,
"Sets how many chunks apart all pockets in pocket dimensions should be placed. [min: 4, max: 16, default: 8]", 4, 16); "Sets how many chunks apart all pockets in pocket dimensions should be placed. [min: 4, max: 32, default: 32]", 4, 32);
DimDoors.log(DDConfig.class, "pocketGridSize was set to " + pocketGridSize); DimDoors.log(DDConfig.class, "pocketGridSize was set to " + pocketGridSize);
maxPocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "maxPocketSize", maxPocketSize, maxPocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "maxPocketSize", maxPocketSize,
"Sets how deep and wide any pocket can be. [min: 1, max: pocketGridSize/2, default: 4]", 1, (int) (((double) pocketGridSize / 2) - 0.5)); "Sets how deep and wide any pocket can be. [min: 0, max: pocketGridSize/2, default: 4]", 0, (int) (((double) pocketGridSize / 2) - 0.5));
privatePocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "privatePocketSize", privatePocketSize, privatePocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "privatePocketSize", privatePocketSize,
"Sets how deep and wide any personal pocket can be. [min: 1, max: maxPocketsSize, default: 3]", 1, maxPocketSize); "Sets how deep and wide any personal pocket can be. [min: 0, max: maxPocketsSize, default: 3]", 0, maxPocketSize);
publicPocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "publicPocketSize", publicPocketSize, publicPocketSize = setConfigIntWithMaxAndMin(config, Configuration.CATEGORY_GENERAL, "publicPocketSize", publicPocketSize,
"Sets how deep and wide any public pocket can be. [min: 1, max: maxPocketsSize, default: 2]", 1, maxPocketSize); "Sets how deep and wide any public pocket can be. [min: 0, max: maxPocketsSize, default: 2]", 0, maxPocketSize);
prop = config.get(Configuration.CATEGORY_GENERAL, "dungeonSchematicNames", dungeonSchematicNames, prop = config.get(Configuration.CATEGORY_GENERAL, "dungeonSchematicNames", dungeonSchematicNames,
"List of names of Pockets' jSon- and Schematic file names excluding extension. Custom json and schematic files can be dropped in the corresponding folders."); "List of names of Pockets' jSon- and Schematic file names excluding extension. Custom json and schematic files can be dropped in the corresponding folders.");
@ -109,9 +109,11 @@ public class DDConfig {
prop = config.get(Configuration.CATEGORY_GENERAL, "dangerousLimboMonolithsDisabled", DangerousLimboMonolithsDisabled, prop = config.get(Configuration.CATEGORY_GENERAL, "dangerousLimboMonolithsDisabled", DangerousLimboMonolithsDisabled,
"Is Monoliths Dangerous in Limbo disabled?"); "Is Monoliths Dangerous in Limbo disabled?");
DangerousLimboMonolithsDisabled = prop.getBoolean();
prop = config.get(Configuration.CATEGORY_GENERAL, "dangerousLimboMonolithsDisabled", MonolithTeleportationEnabled, prop = config.get(Configuration.CATEGORY_GENERAL, "dangerousLimboMonolithsDisabled", MonolithTeleportationEnabled,
"Is Monolith Teleportation disabled?"); "Is Monolith Teleportation disabled?");
MonolithTeleportationEnabled = prop.getBoolean();
checkAndCorrectDoorRelativeDepths(config); checkAndCorrectDoorRelativeDepths(config);

View file

@ -28,7 +28,7 @@ import net.minecraft.world.WorldServer;
public class Pocket { public class Pocket {
private int ID; //this gets reset every server-load private int ID; //this gets reset every server-load
private final int size; //in chunks private final int size; //in chunks 0 -> 1*1 chunk, 1 -> 2*2 chunks
private final int depth; private final int depth;
private final EnumPocketType typeID; // dungeon, pocket, or personal pocket private final EnumPocketType typeID; // dungeon, pocket, or personal pocket
private final int x; //pocket-relative 0 coordinate, should be at x * PocketRegistry.INSTANCE.gridSize * 16 private final int x; //pocket-relative 0 coordinate, should be at x * PocketRegistry.INSTANCE.gridSize * 16
@ -167,15 +167,34 @@ public class Pocket {
public void validatePlayerEntry(EntityPlayer player) { public void validatePlayerEntry(EntityPlayer player) {
String playerUUID = player.getCachedUniqueIdString(); String playerUUID = player.getCachedUniqueIdString();
for (String allowedPlayerUUID : playerUUIDs) { if (!playerUUIDs.contains(playerUUID)) { //the 'contains' method uses the 'equals' method to check, so for Strings, this should work.
if (allowedPlayerUUID.equals(playerUUID)) {
return;
}
}
playerUUIDs.add(playerUUID); playerUUIDs.add(playerUUID);
} }
}
public boolean isPlayerAllowedInPocket(EntityPlayer player) {
String playerUUID = player.getCachedUniqueIdString();
return playerUUIDs.contains(playerUUID);
}
public void setDepthZeroLocation(Location teleportTargetLocation) { public void setDepthZeroLocation(Location teleportTargetLocation) {
depthZeroLocation.loadfrom(teleportTargetLocation); depthZeroLocation.loadfrom(teleportTargetLocation);
} }
boolean isLocationWithinPocketBounds(final Location location, final int gridSize) {
int locX = location.getPos().getX();
int locZ = location.getPos().getY();
//minimum bounds of the pocket
int pocX = x * gridSize;
int pocZ = z * gridSize;
if (pocX <= locX && pocZ <= locZ) {
//convert to maximum bounds of the pocket
pocX = pocX + (size + 1) * 16;
pocZ = pocZ + (size + 1) * 16;
if (locX < pocX && locZ < pocZ) {
return true;
}
}
return false;
}
} }

View file

@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagList;
@ -228,12 +229,25 @@ public class PocketRegistry {
return privatePockets.get(playerUUID); return privatePockets.get(playerUUID);
} }
private Location getGenerationlocation(int nextUnusedID, EnumPocketType typeID) { private Location getGenerationlocation(final int nextUnusedID, EnumPocketType typeID) {
int x = getSimpleX(nextUnusedID); int x;
int y = 0; int y = 0;
int z = getSimpleZ(nextUnusedID); int z;
int dimID = DimDoorDimensions.getPocketDimensionType(typeID).getId(); int dimID = DimDoorDimensions.getPocketDimensionType(typeID).getId();
if (nextUnusedID == 0) {
x = 0;
z = 0;
} else {
int radius = (int) Math.sqrt(nextUnusedID); //casting to int rounds down the double resulting from taking the square root
int radiusNumber = nextUnusedID - (radius * radius);
double splitter = ((double) radiusNumber) / ((double) radius); //always between 0 and 2
DimDoors.log(this.getClass(), "id is " + nextUnusedID);
DimDoors.log(this.getClass(), "Radius is " + radius);
DimDoors.log(this.getClass(), "Radius number is " + radiusNumber);
DimDoors.log(this.getClass(), "Splitter is " + splitter);
x = splitter <= 1.0 ? radius : radius - (radiusNumber - radius);
z = splitter >= 1.0 ? radius : radiusNumber;
}
Location location = new Location(dimID, x, y, z); Location location = new Location(dimID, x, y, z);
return location; return location;
} }
@ -250,6 +264,7 @@ public class PocketRegistry {
} }
} }
/*
private int getSimpleX(int ID) { private int getSimpleX(int ID) {
//@todo check for smaller than 0 //@todo check for smaller than 0
if (ID == 0) { if (ID == 0) {
@ -300,4 +315,38 @@ public class PocketRegistry {
} }
return group; return group;
} }
*/
private int getPocketIDFromCoords(Location location) {
final int dimID = location.getDimensionID();
if (DimDoorDimensions.isPocketDimensionID(dimID)) {
int x = location.getPos().getX();
int z = location.getPos().getZ();
int shortX = x / (gridSize * 16);
int shortZ = z / (gridSize * 16);
if (shortX >= shortZ) {
return shortX * shortX + shortZ;
} else {
return (shortZ + 2) * shortZ - shortX;
}
}
return -1; //not in a pocket dimension
}
public boolean isPlayerAllowedToBeHere(final EntityPlayerMP player, final Location location) {
if (player.isCreative()) {
return true;
} else {
int pocketID = getPocketIDFromCoords(location);
if (pocketID < 0) { //not in a pocket dimension
return true;
} else {
EnumPocketType type = DimDoorDimensions.getPocketType(location.getDimensionID());
Pocket pocket = pocketLists.get(type).get(pocketID);
if (pocket.isPlayerAllowedInPocket(player) && pocket.isLocationWithinPocketBounds(location, gridSize)) {
return true;
}
return false;
}
}
}
} }

View file

@ -44,7 +44,7 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
this.weights = weights; //chance that this Pocket will get generated this.weights = weights; //chance that this Pocket will get generated
this.minDepth = minDepth; //pocket will only be generated from this Pocket-depth this.minDepth = minDepth; //pocket will only be generated from this Pocket-depth
this.maxDepth = maxDepth; //to this pocket depth this.maxDepth = maxDepth; //to this pocket depth
this.size = size; //size of content of pocket in chunks (walls are 5 thick, so size 0 will be 6*6 blocks, size 1 will be 22*22 blocks, etc. this.size = size; //size of pocket in chunks (0 -> 1*1 chunk, 1 -> 2*2 chunks etc.)
this.schematic = schematic; this.schematic = schematic;
this.typeID = typeID; this.typeID = typeID;
} }

View file

@ -49,7 +49,7 @@ public class SchematicHandler {
final private Map<String, Map<String, Integer>> dungeonNameMap = new HashMap(); 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 //@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) { 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(); List<PocketTemplate> validTemplates = new ArrayList();
int totalWeight = 0; int totalWeight = 0;
for (PocketTemplate template : dungeonTemplates) { for (PocketTemplate template : dungeonTemplates) {
@ -180,19 +180,24 @@ public class SchematicHandler {
//determine which location to load the schematic file from (and what format) //determine which location to load the schematic file from (and what format)
DataInputStream schematicDataStream = null; DataInputStream schematicDataStream = null;
boolean streamOpened = false;
if (schematicStream != null) { if (schematicStream != null) {
schematicDataStream = new DataInputStream(schematicStream); schematicDataStream = new DataInputStream(schematicStream);
streamOpened = true;
} else if (oldVersionSchematicStream != null) { } else if (oldVersionSchematicStream != null) {
schematicDataStream = new DataInputStream(oldVersionSchematicStream); schematicDataStream = new DataInputStream(oldVersionSchematicStream);
streamOpened = true;
} else if (schematicFile.exists()) { } else if (schematicFile.exists()) {
try { try {
schematicDataStream = new DataInputStream(new FileInputStream(schematicFile)); schematicDataStream = new DataInputStream(new FileInputStream(schematicFile));
streamOpened = true;
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file " + template.getName() + ".schem did not load correctly from config folder.", ex); Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file " + template.getName() + ".schem did not load correctly from config folder.", ex);
} }
} else if (oldVersionSchematicFile.exists()) { } else if (oldVersionSchematicFile.exists()) {
try { try {
schematicDataStream = new DataInputStream(new FileInputStream(oldVersionSchematicFile)); schematicDataStream = new DataInputStream(new FileInputStream(oldVersionSchematicFile));
streamOpened = true;
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file " + template.getName() + ".schematic did not load correctly from config folder.", ex); Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file " + template.getName() + ".schematic did not load correctly from config folder.", ex);
} }
@ -202,6 +207,7 @@ public class SchematicHandler {
NBTTagCompound schematicNBT; NBTTagCompound schematicNBT;
Schematic schematic = null; Schematic schematic = null;
if (streamOpened) {
try { try {
schematicNBT = CompressedStreamTools.readCompressed(schematicDataStream); schematicNBT = CompressedStreamTools.readCompressed(schematicDataStream);
schematic = Schematic.loadFromNBT(schematicNBT, template.getName()); schematic = Schematic.loadFromNBT(schematicNBT, template.getName());
@ -215,6 +221,7 @@ public class SchematicHandler {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Error occured while closing schematicDataStream", ex); Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Error occured while closing schematicDataStream", ex);
} }
} }
}
if (schematic != null if (schematic != null
&& (schematic.getWidth() > (template.getSize() + 1) * 16 || schematic.getLength() > (template.getSize() + 1) * 16)) { && (schematic.getWidth() > (template.getSize() + 1) * 16 || schematic.getLength() > (template.getSize() + 1) * 16)) {

View file

@ -17,17 +17,25 @@ import net.minecraftforge.common.DimensionManager;
public class DimDoorDimensions { public class DimDoorDimensions {
public static DimensionType LIMBO; public static DimensionType LIMBO;
private static Map<EnumPocketType, DimensionType> pocketDimensionTypes = new HashMap<>(); private static int minPocketDimID;
public static List<DimensionType> CUSTOM; private static int maxPocketDimID;
private static final List<EnumPocketType> pocketTypes = new ArrayList<>();
private static final Map<EnumPocketType, DimensionType> pocketDimensionTypes = new HashMap<>();
private static final List<DimensionType> CUSTOM = new ArrayList<>();
public static void init() { public static void init() {
int dimID = DDConfig.getBaseDimID(); int dimID = DDConfig.getBaseDimID();
LIMBO = DimensionType.register("Limbo", "_limbo", dimID, WorldProviderLimbo.class, false); LIMBO = DimensionType.register("Limbo", "_limbo", dimID, WorldProviderLimbo.class, false);
dimID++; dimID++; //@todo make this a loop over a function
minPocketDimID = dimID;
pocketTypes.add(EnumPocketType.PRIVATE);
pocketDimensionTypes.put(EnumPocketType.PRIVATE, DimensionType.register("Private", "_private", dimID, WorldProviderPersonalPocket.class, false)); pocketDimensionTypes.put(EnumPocketType.PRIVATE, DimensionType.register("Private", "_private", dimID, WorldProviderPersonalPocket.class, false));
dimID++; dimID++;
pocketTypes.add(EnumPocketType.PUBLIC);
pocketDimensionTypes.put(EnumPocketType.PUBLIC, DimensionType.register("Public", "_public", dimID, WorldProviderPublicPocket.class, false)); pocketDimensionTypes.put(EnumPocketType.PUBLIC, DimensionType.register("Public", "_public", dimID, WorldProviderPublicPocket.class, false));
dimID++; dimID++;
maxPocketDimID = dimID;
pocketTypes.add(EnumPocketType.DUNGEON);
pocketDimensionTypes.put(EnumPocketType.DUNGEON, DimensionType.register("Dungeon", "_dungeon", dimID, WorldProviderDungeonPocket.class, false)); pocketDimensionTypes.put(EnumPocketType.DUNGEON, DimensionType.register("Dungeon", "_dungeon", dimID, WorldProviderDungeonPocket.class, false));
registerDimension(LIMBO); registerDimension(LIMBO);
@ -35,7 +43,6 @@ public class DimDoorDimensions {
registerDimension(pocketDimensionTypes.get(pocketType)); registerDimension(pocketDimensionTypes.get(pocketType));
} }
CUSTOM = new ArrayList<>();
for (int i = 0; i < 0; i++) { //@todo: For future use? Like, server owners can add their own set of DimDoors DimensionTypes via the configs? Or is this nonsense? for (int i = 0; i < 0; i++) { //@todo: For future use? Like, server owners can add their own set of DimDoors DimensionTypes via the configs? Or is this nonsense?
dimID++; dimID++;
DimensionType tempType = DimensionType.register("Name", "_name", dimID, WorldProvider.class, false); DimensionType tempType = DimensionType.register("Name", "_name", dimID, WorldProvider.class, false);
@ -51,4 +58,13 @@ public class DimDoorDimensions {
public static DimensionType getPocketDimensionType(EnumPocketType pocketType) { public static DimensionType getPocketDimensionType(EnumPocketType pocketType) {
return pocketDimensionTypes.get(pocketType); return pocketDimensionTypes.get(pocketType);
} }
public static boolean isPocketDimensionID(int id) {
return id >= minPocketDimID && id <= maxPocketDimID;
}
public static EnumPocketType getPocketType(int dimID) {
int index = dimID - minPocketDimID;
return pocketTypes.get(index);
}
} }