Pocket creation upon entering doors

-Added an "OverWorld location reference" to each door (that offsets more
if you go deeper into dungeon pockets)
-Made sure that the entrance door of a Pocket is a Warp Door if the
Pocket has one
-Made sure that the depth of Dungeon Pockets is always at least 1
-Added some separate teleportation behaviours for different types of
Rifts
-Minor bug fixes
This commit is contained in:
Mathijs Riezebos 2017-02-21 15:16:04 +01:00
parent 86eb14c408
commit de93828a6d
17 changed files with 403 additions and 100 deletions

View file

@ -6,6 +6,8 @@
package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.tileentities.DDTileEntityBase;
import com.zixiken.dimdoors.shared.tileentities.TileEntityDimDoorWarp;
import com.zixiken.dimdoors.shared.util.Location;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@ -14,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.tileentity.TileEntity;
/**
*
@ -28,16 +31,18 @@ public class Pocket {
private final int x; //pocket-relative 0 coordinate, should be at x * PocketRegistry.Instance.gridSize * 16
private final int z; //pocket-relative 0 coordinate, should be at z * PocketRegistry.Instance.gridSize * 16
private final List<String> playerUUIDs;
private final List<Integer> riftIDs; //@todo first one of these should be the entrance door id? Does that even matter?
private final List<Integer> riftIDs;
private final Location depthZeroLocation;
//when adding any new variables, don't forget to add them to the write and load functions
public Pocket(int size, int depth, EnumPocketType typeID, int x, int z, List<Integer> riftIDs) {
public Pocket(int size, int depth, EnumPocketType typeID, int x, int z, List<Integer> riftIDs, Location depthZeroLocation) {
this.size = size;
this.depth = depth;
this.typeID = typeID;
this.x = x;
this.z = z;
this.riftIDs = riftIDs;
this.depthZeroLocation = depthZeroLocation;
playerUUIDs = new ArrayList();
PocketRegistry.Instance.registerNewPocket(this, typeID);
@ -65,8 +70,11 @@ public class Pocket {
} else if (riftIDs.size() == 1) {
return riftIDs.get(0);
} else {
Random random = new Random();
int index = random.nextInt(riftIDs.size());
int index = findWarpDoorIndex(riftIDs);
if (index == -1) {
Random random = new Random();
index = random.nextInt(riftIDs.size());
}
return riftIDs.get(index);
}
}
@ -87,7 +95,8 @@ public class Pocket {
int doorID = doorsTagList.getIntAt(i);
riftIDs.add(doorID);
}
Pocket pocket = new Pocket(size, depth, typeID, x, z, riftIDs); //registers the new pocket as well
Location depthZeroLocation = Location.readFromNBT(pocketNBT.getCompoundTag("depthZeroLocation"));
Pocket pocket = new Pocket(size, depth, typeID, x, z, riftIDs, depthZeroLocation); //registers the new pocket as well
NBTTagList playersTagList = (NBTTagList) pocketNBT.getTag("playerUUIDs"); //@todo, maybe it is bad practice to put this behind the creation statement of the Pocket?
for (int i = 0; i < playersTagList.tagCount(); i++) {
@ -110,14 +119,36 @@ public class Pocket {
doorsTagList.appendTag(doorTag);
}
pocketNBT.setTag("doorIDs", doorsTagList);
NBTTagCompound depthZeroLocCompound = Location.writeToNBT(pocket.depthZeroLocation);
pocketNBT.setTag("depthZeroLocation", depthZeroLocCompound);
NBTTagList playersTagList = new NBTTagList();
for (int i = 0; i < pocket.playerUUIDs.size(); i++) {
NBTTagString playerTag = new NBTTagString(pocket.playerUUIDs.get(i));
playersTagList.appendTag(playerTag);
}
pocketNBT.setTag("playerUUIDs", playersTagList);
pocketNBT.setTag("playerUUIDs", playersTagList);
return pocketNBT;
}
private static int findWarpDoorIndex(List<Integer> riftIDs) { //used to find the entrance door to this pocket
int index = -1;
for (int i = 0; i < riftIDs.size(); i++) {
TileEntity tileEntity = RiftRegistry.Instance.getRiftLocation(i).getTileEntity();
if (tileEntity != null && tileEntity instanceof TileEntityDimDoorWarp) {
index = i;
break;
}
}
return index;
}
/**
* @return the depthZeroLocation
*/
public Location getDepthZeroLocation() {
return depthZeroLocation;
}
}

View file

@ -7,13 +7,15 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.world.DimDoorDimensions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
/**
*
@ -157,23 +159,38 @@ public class PocketRegistry {
return pocketLists.get(pocketType).get(ID);
}
public int getEntranceDoorIDOfNewPocket(EnumPocketType typeID, int depth) {//should return the riftID of the entrance door of the newly generated pocket
Location shortenedLocation = getGenerationlocation(nextUnusedIDs.get(typeID), typeID); //@todo, we should have different values of "nextUnusedID" for different pocket-types
public int getEntranceDoorIDOfNewPocket(EnumPocketType typeID, int depth, Location origRiftLocation) {//should return the riftID of the entrance door of the newly generated pocket
Location shortenedLocation = getGenerationlocation(nextUnusedIDs.get(typeID), typeID);
int x = shortenedLocation.getPos().getX();
int z = shortenedLocation.getPos().getZ();
Pocket pocket = generateRandomPocketAt(typeID, depth, shortenedLocation); //registers the pocket as well
Pocket pocket = generateRandomPocketAt(typeID, depth, shortenedLocation, origRiftLocation); //registers the pocket as well
int entranceDoorID = pocket.getEntranceDoorID();
return entranceDoorID;
}
private Pocket generateRandomPocketAt(EnumPocketType typeID, int depth, Location shortenedLocation) {
private Pocket generateRandomPocketAt(EnumPocketType typeID, int depth, Location shortenedLocation, Location origRiftLocation) {
int shortenedX = shortenedLocation.getPos().getX();
int shortenedZ = shortenedLocation.getPos().getZ();
int dimID = shortenedLocation.getDimensionID();
PocketTemplate pocketTemplate = getRandomPocketTemplate(typeID, depth, maxPocketSize);
//correction just in case
if (typeID == EnumPocketType.DUNGEON) {
if (depth <= 0) {
depth = 1;
}
} else {
depth = 0;
}
Pocket pocket = pocketTemplate.place(shortenedX, 0, shortenedZ, gridSize, dimID, nextUnusedIDs.get(typeID), depth, typeID);
PocketTemplate pocketTemplate = getRandomPocketTemplate(typeID, depth, maxPocketSize);
Location depthZeroLocation;
if (typeID != EnumPocketType.PRIVATE) {
depthZeroLocation = transformLocationRandomly(depth, origRiftLocation);
} else {
depthZeroLocation = origRiftLocation;
}
Pocket pocket = pocketTemplate.place(shortenedX, 0, shortenedZ, gridSize, dimID, nextUnusedIDs.get(typeID), depth, typeID, depthZeroLocation);
return pocket;
}
@ -185,7 +202,7 @@ public class PocketRegistry {
int x = getSimpleX(nextUnusedID, typeID);
int y = 0;
int z = getSimpleZ(nextUnusedID, typeID);;
int dimID = 0; //@todo should be fetched using typeID
int dimID = DimDoorDimensions.getPocketDimensionType(typeID).getId();
Location location = new Location(x, y, z, dimID);
return location;
@ -252,4 +269,11 @@ public class PocketRegistry {
}
return group;
}
private Location transformLocationRandomly(int depth, Location origLocation) {
Random random = new Random();
int xOffset = ((64 * depth) ^ (9 / 7)) * (random.nextBoolean() ? 1 : -1);
int zOffset = ((64 * depth) ^ (9 / 7)) * (random.nextBoolean() ? 1 : -1);
return new Location(origLocation.getWorld(), origLocation.getPos().offset(EnumFacing.EAST, xOffset).offset(EnumFacing.SOUTH, zOffset));
}
}

View file

@ -8,8 +8,10 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.util.Schematic;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.tileentities.DDTileEntityBase;
import com.zixiken.dimdoors.shared.util.Location;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@ -80,7 +82,7 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
}
//@todo make sure that the "pocketID" parameter gets used, or remove it.
public Pocket place(int shortenedX, int yBase, int shortenedZ, int gridSize, int dimID, int pocketID, int depth, EnumPocketType pocketTypeID) { //returns the riftID of the entrance DimDoor
public Pocket place(int shortenedX, int yBase, int shortenedZ, int gridSize, int dimID, int pocketID, int depth, EnumPocketType pocketTypeID, Location depthZeroLocation) { //returns the riftID of the entrance DimDoor
int xBase = shortenedX * gridSize * 16;
int zBase = shortenedZ * gridSize * 16;
@ -92,10 +94,13 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
WorldServer world = DimDoors.proxy.getWorldServer(dimID);
//Place the Dungeon content structure
for (int x = 0; x < schematic.getWidth(); x++) {
for (int y = 0; y < schematic.getHeight(); y++) {
for (int z = 0; z < schematic.getWidth(); z++) {
world.setBlockState(new BlockPos(xBase + x, yBase + y, zBase + z), schematic.getPallette().get(schematic.getBlockData()[x][y][z]), 2); //the "2" is to make non-default door-halves not break upon placement
List<IBlockState> palette = schematic.getPallette();
int[][][] blockData = schematic.getBlockData();
for (int x = 0; x < blockData.length; x++) {
for (int y = 0; y < blockData[x].length; y++) {
for (int z = 0; z < blockData[x][y].length; z++) {
world.setBlockState(new BlockPos(xBase + x, yBase + y, zBase + z), palette.get(blockData[x][y][z]), 2); //the "2" is to make non-default door-halves not break upon placement
}
}
}
@ -124,6 +129,6 @@ public class PocketTemplate { //there is exactly one pocket placer for each diff
riftIDs.add(rift.getRiftID());
}
return new Pocket(size, depth, pocketTypeID, shortenedX, shortenedZ, riftIDs);
return new Pocket(size, depth, pocketTypeID, shortenedX, shortenedZ, riftIDs, depthZeroLocation);
}
}

View file

@ -8,6 +8,8 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.tileentities.DDTileEntityBase;
import com.zixiken.dimdoors.shared.tileentities.TileEntityDimDoorChaos;
import com.zixiken.dimdoors.shared.tileentities.TileEntityDimDoorPersonal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -30,29 +32,31 @@ public class RiftRegistry {
// Privates
private int nextRiftID;
private int maximumDungeonDepth = 2; //@todo make this configurable
private final Map<Integer, Location> riftList; //maps all rifts in the world to their ID //@todo, make this a List of (comparable) locations?
//@todo somehow remove rifts from this list even if they are removed in creative
private final List<Integer> unpairedRiftList; //maps of all rifts in the world that are not paired to their ID
private final List<List<Integer>> unpairedDepthRiftList; //List of all "unpairedRiftList s" per Dungeon Depth. Depth 0 is almost anything outside the dungeon dimension
//@todo, once we have a dungeon dimension this List should be implemented (for determining what doors an unpaired door can link to)
//when adding any new variables, don't forget to add them to the write and load functions
private final Map<Integer, Location> rifts; //maps all rifts in the world to their ID //@todo, make this a List of (comparable) locations?
private final List<Integer> personalDoors; //list of all personal door rifts in the world, by riftID
private final List<Integer> unpairedRifts; //list of all pairable rifts in the world that are not paired, by riftID
private final List<List<Integer>> unpairedRiftsPerDepth; //List of all "unpairedRiftList s" per Dungeon Depth. Depth 0 is anything outside the dungeon dimension
//@todo somehow remove rifts from these lists even if they are removed in creative
//when adding any new variables, don't forget to add them to the write and load functions
// Methods
private RiftRegistry() {
nextRiftID = 0;
riftList = new HashMap();
unpairedRiftList = new ArrayList();
unpairedDepthRiftList = new ArrayList();
for (int i = 0; i < maximumDungeonDepth; i++) {
unpairedDepthRiftList.add(new ArrayList());
rifts = new HashMap();
personalDoors = new ArrayList(); //@todo read from and write to NBT
unpairedRifts = new ArrayList();
unpairedRiftsPerDepth = new ArrayList();
for (int i = 0; i <= maximumDungeonDepth; i++) {
unpairedRiftsPerDepth.add(new ArrayList());
}
}
public void reset() {
nextRiftID = 0;
riftList.clear();
unpairedRiftList.clear();
for (List<Integer> dimensionSpecificUnpairedRiftList : unpairedDepthRiftList) {
rifts.clear();
personalDoors.clear();
unpairedRifts.clear();
for (List<Integer> dimensionSpecificUnpairedRiftList : unpairedRiftsPerDepth) {
dimensionSpecificUnpairedRiftList.clear();
}
lastBrokenRift = null;
@ -68,7 +72,7 @@ public class RiftRegistry {
int riftID = riftTag.getInteger("riftID");
NBTTagCompound locationTag = riftTag.getCompoundTag("location");
Location riftLocation = Location.readFromNBT(locationTag);
riftList.put(riftID, riftLocation);
rifts.put(riftID, riftLocation);
}
}
@ -77,22 +81,22 @@ public class RiftRegistry {
for (int i = 0; i < riftsNBT.tagCount(); i++) {
NBTTagCompound riftTag = riftsNBT.getCompoundTagAt(i);
int riftID = riftTag.getInteger("riftID");
unpairedRiftList.add(riftID);
unpairedRifts.add(riftID);
}
}
if (nbt.hasKey("unpairedDepthRiftList")) {
unpairedDepthRiftList.clear(); //because its "maximum depth" (or in other words, "size()") could be re-determined by this action
unpairedRiftsPerDepth.clear(); //because its "maximum depth" (or in other words, "size()") could be re-determined by this action
NBTTagList riftListsNBT = (NBTTagList) nbt.getTag("unpairedDepthRiftList");
maximumDungeonDepth = riftListsNBT.tagCount(); //makes sure both are synched
for (int i = 0; i < riftListsNBT.tagCount(); i++) {
unpairedDepthRiftList.add(new ArrayList());
unpairedRiftsPerDepth.add(new ArrayList());
NBTTagList riftsNBT = (NBTTagList) riftListsNBT.get(i);
for (int j = 0; j < riftsNBT.tagCount(); j++) {
NBTTagCompound riftTag = riftsNBT.getCompoundTagAt(j);
int riftID = riftTag.getInteger("riftID");
unpairedDepthRiftList.get(i).add(riftID);
unpairedRiftsPerDepth.get(i).add(riftID);
}
}
}
@ -103,7 +107,7 @@ public class RiftRegistry {
nbt.setInteger("nextUnusedID", nextRiftID);
NBTTagList riftsNBT = new NBTTagList();
for (Map.Entry<Integer, Location> entry : riftList.entrySet()) {
for (Map.Entry<Integer, Location> entry : rifts.entrySet()) {
NBTTagCompound riftTag = new NBTTagCompound();
riftTag.setInteger("riftID", entry.getKey());
riftTag.setTag("location", Location.writeToNBT(entry.getValue()));
@ -112,7 +116,7 @@ public class RiftRegistry {
nbt.setTag("riftList", riftsNBT);
NBTTagList unpairedRiftsNBT = new NBTTagList();
for (int riftID : unpairedRiftList) {
for (int riftID : unpairedRifts) {
NBTTagCompound riftTag = new NBTTagCompound();
riftTag.setInteger("riftID", riftID);
unpairedRiftsNBT.appendTag(riftTag);
@ -120,7 +124,7 @@ public class RiftRegistry {
nbt.setTag("unpairedRiftList", unpairedRiftsNBT);
NBTTagList unpairedRiftListsNBT = new NBTTagList();
for (List<Integer> unpairedRiftListAtDepth : unpairedDepthRiftList) {
for (List<Integer> unpairedRiftListAtDepth : unpairedRiftsPerDepth) {
NBTTagList unpairedRiftsNBT2 = new NBTTagList();
for (int riftID : unpairedRiftListAtDepth) {
NBTTagCompound riftTag = new NBTTagCompound();
@ -134,53 +138,62 @@ public class RiftRegistry {
public int registerNewRift(DDTileEntityBase rift, int depth) {
Location riftLocation = Location.getLocation(rift);
riftList.put(nextRiftID, riftLocation);
unpairedRiftList.add(nextRiftID);
registerRiftAtDepth(nextRiftID, depth);
rifts.put(nextRiftID, riftLocation);
if (rift instanceof TileEntityDimDoorPersonal || rift instanceof TileEntityDimDoorChaos) {
if (rift instanceof TileEntityDimDoorPersonal) {
personalDoors.add(nextRiftID);
}
} else {
unpairedRifts.add(nextRiftID);
registerUnpairedRiftAtDepth(nextRiftID, depth);
}
DimDoors.log(this.getClass(), "Rift registered as ID: " + nextRiftID);
nextRiftID++;
RiftSavedData.get(DimDoors.getDefWorld()).markDirty(); //Notify that this needs to be saved on world save
return nextRiftID - 1;
}
public void unregisterRift(int riftID) {
if (riftList.containsKey(riftID)) {
if (rifts.containsKey(riftID)) {
unpair(riftID);
riftList.remove(riftID);
unpairedRiftList.remove((Integer) riftID);
unRegisterRiftAtDepth(riftID);
unRegisterUnpairedRiftAtDepth(riftID); //@todo, will this crash if it doesn't find that value?
unpairedRifts.remove((Integer) riftID);
personalDoors.remove((Integer) riftID);
rifts.remove((Integer) riftID);
RiftSavedData.get(DimDoors.getDefWorld()).markDirty(); //Notify that this needs to be saved on world save
}
}
void registerRiftAtDepth(int riftID, int depth) {
void registerUnpairedRiftAtDepth(int riftID, int depth) {
if (depth < maximumDungeonDepth) {
List<Integer> unpairedRiftListAtDepth = unpairedDepthRiftList.get(depth);
List<Integer> unpairedRiftListAtDepth = unpairedRiftsPerDepth.get(depth);
unpairedRiftListAtDepth.add(riftID);
}
}
void unRegisterRiftAtDepth(int riftID) {
TileEntity tileEntity = riftList.get(riftID).getTileEntity();
void unRegisterUnpairedRiftAtDepth(int riftID) {
TileEntity tileEntity = rifts.get(riftID).getTileEntity();
if (tileEntity instanceof DDTileEntityBase) {
DDTileEntityBase rift = (DDTileEntityBase) tileEntity;
int depth = rift.getDepth();
if (depth < maximumDungeonDepth) {
List<Integer> unpairedRiftListAtDepth = unpairedDepthRiftList.get(depth);
List<Integer> unpairedRiftListAtDepth = unpairedRiftsPerDepth.get(depth);
unpairedRiftListAtDepth.remove((Integer) riftID);
}
}
}
public Location getRiftLocation(int ID) {
return riftList.get(ID);
return rifts.get(ID);
}
public void pair(int riftID, int riftID2) {
if (riftID < 0 || riftID2 < 0) {
return;
}
Location location = riftList.get(riftID);
Location location = rifts.get(riftID);
TileEntity tileEntity = location.getTileEntity(); //@todo this method might need to be in another class?
if (tileEntity != null && tileEntity instanceof DDTileEntityBase) {
DDTileEntityBase rift = (DDTileEntityBase) tileEntity;
@ -188,8 +201,8 @@ public class RiftRegistry {
boolean alreadyPaired = rift.pair(riftID2);
if (!alreadyPaired) {
DimDoors.log(this.getClass(), "RiftRegistry unregistering rift " + riftID + " from unPairedRiftRegistry.");
unpairedRiftList.remove((Integer) riftID);
//@todo remove the riftID from the depth list as well
unpairedRifts.remove((Integer) riftID);
unRegisterUnpairedRiftAtDepth(riftID);
}
}
}
@ -198,17 +211,17 @@ public class RiftRegistry {
if (riftID < 0) {
return;
}
Location location = riftList.get(riftID);
Location location = rifts.get(riftID);
if (location == null) {
DimDoors.log(this.getClass(), "RiftID with null location: rift " + riftID);
DimDoors.warn(this.getClass(), "RiftID with null location: rift " + riftID);
}
TileEntity tileEntity = location.getTileEntity();
if (tileEntity != null && tileEntity instanceof DDTileEntityBase) {
DDTileEntityBase rift = (DDTileEntityBase) tileEntity;
boolean alreadyUnPaired = rift.unpair();
if (!alreadyUnPaired) {
unpairedRiftList.add(riftID);
//@todo add the riftID from the depth list as well, maybe move this to the tileEntityRift class itself though?
unpairedRifts.add(riftID);
registerUnpairedRiftAtDepth(riftID, rift.getDepth());
}
}
}
@ -224,7 +237,7 @@ public class RiftRegistry {
public boolean teleportEntityToRift(Entity entity, int pairedRiftID) {
DimDoors.log(this.getClass(), "RiftID of rift that the entity trying to teleport to is " + pairedRiftID + ".");
if (pairedRiftID < 0) {
DimDoors.warn(this.getClass(), "RiftID of rift that entity trying to teleport to seems to be lower than 0 and it shouldn't.");
DimDoors.warn(this.getClass(), "RiftID of rift that entity " + entity + " is trying to teleport to seems to be lower than 0 and it shouldn't.");
return false;
}
Location destinationRiftLocation = getRiftLocation(pairedRiftID);
@ -235,19 +248,105 @@ public class RiftRegistry {
return TeleportHelper.teleport(entity, destinationRift.getTeleportTargetLocation());
}
//@todo are we ever going to use this method?
public int getRandomUnpairedRiftID(int origRiftID) {
if (!unpairedRiftList.isEmpty()) {
int numberOfUnpairedRifts = unpairedRiftList.size();
if (numberOfUnpairedRifts != 1) {//should only be the "original Rift" then
if (!unpairedRifts.isEmpty()) {
int numberOfUnpairedRifts = unpairedRifts.size();
if (numberOfUnpairedRifts != 1) {//should not only be the "original Rift" then
Random random = new Random();
int indexOforigRiftID = unpairedRiftList.indexOf(origRiftID);
int indexOforigRiftID = unpairedRifts.indexOf(origRiftID);
int randomRiftIDIndex = random.nextInt(numberOfUnpairedRifts - 1); //-1 because we do not want to include the key of the original rift, so it will not randomly pair to itself
if (randomRiftIDIndex >= indexOforigRiftID) {
randomRiftIDIndex++;
}
return unpairedRiftList.get(randomRiftIDIndex);
return unpairedRifts.get(randomRiftIDIndex);
}
}
return -1;
}
public int getRandomUnpairedRiftIDAtDepth(int origRiftID, int depth) {
int returnID = -1;
if (unpairedRiftsPerDepth.size() > depth) {
List<Integer> rifts = unpairedRiftsPerDepth.get(depth);
int numberOfUnpairedRifts = rifts.size();
if (numberOfUnpairedRifts > 0) {
Random random = new Random();
int indexOforigRiftID = -1;
int randomRiftIDIndex;
boolean origRiftIsOnSameDepth = rifts.contains(origRiftID);
if (origRiftIsOnSameDepth) {
indexOforigRiftID = rifts.indexOf(origRiftID);
randomRiftIDIndex = random.nextInt(numberOfUnpairedRifts - 1); //-1 because we do not want to include the key of the original rift, so it will not randomly pair to itself
if (randomRiftIDIndex >= indexOforigRiftID) {
randomRiftIDIndex++;
}
} else {
randomRiftIDIndex = random.nextInt(numberOfUnpairedRifts);
}
returnID = rifts.get(randomRiftIDIndex);
}
}
return returnID;
}
public int getRandomUnpairedRiftIDAroundDepth(int origRiftID, int depth) {
int returnID = -1;
if (unpairedRiftsPerDepth.size() > depth) {
int[] weights = getWeightSizeProducts(unpairedRiftsPerDepth, depth - 2, new int[]{15, 25, 30, 20, 10});
if (getArraySum(weights) == 0) {
//@todo there is no unpaired rift around that depth
} else {
int chosenDepth = pickRandom(weights) + depth - 2;
returnID = getRandomUnpairedRiftIDAtDepth(origRiftID, chosenDepth);
}
}
return returnID;
}
public int[] getWeightSizeProducts(List<List<Integer>> nestedList, int minListIndex, int[] weights) { //@todo put this in a utility class
int[] returnArray = new int[weights.length];
for (int i = 0; i < weights.length; i++) {
int listIndex = minListIndex + i;
if (listIndex > 0 && listIndex < nestedList.size()) {
returnArray[i] = nestedList.get(listIndex).size() * weights[i];
} else {
returnArray[i] = 0;
}
}
return returnArray;
}
private int getArraySum(int[] integers) { //@todo put this in a utility class
int returnValue = 0;
for (int i : integers) {
returnValue += i;
}
return returnValue;
}
private int pickRandom(int[] integers) { //@todo put this in a utility class
Random random = new Random();
int pointer = random.nextInt(getArraySum(integers));
for (int i = 0; i < integers.length; i++) {
if (pointer < integers[i]) {
return i;
}
pointer -= integers[i];
}
return -1; //should not be reachable if implementation is correct and getArraySum(integers) does not return 0
}
public int getRandomNonPersonalRiftID() {
List<Integer> nonPersonalRiftIDs = new ArrayList(rifts.keySet());
for (int persRiftID : personalDoors) {
nonPersonalRiftIDs.remove((Integer) persRiftID);
}
if (nonPersonalRiftIDs.size() > 0) {
Random random = new Random();
int index = random.nextInt(nonPersonalRiftIDs.size());
return nonPersonalRiftIDs.get(index);
}
return -1;
}
}

View file

@ -14,7 +14,7 @@ public class TeleportHelper extends Teleporter {
private final Location location;
public TeleportHelper(Location location) {//@todo make TeleportHelper static
super((WorldServer) location.getWorld());
super(location.getWorld());
this.location = location;
}

View file

@ -38,7 +38,7 @@ public abstract class BlockDimDoorBase extends BlockDoor implements IDimDoor, IT
if (!world.isRemote && down.getBlock() == this) { //@todo should only teleport when colliding with top part of the door?
if (down.getValue(BlockDoor.OPEN)
&& entity instanceof EntityPlayer //@todo remove this so any entity can go through?
&& (entity.timeUntilPortal < 1) //to prevent the player from teleporting all over the place we have a 150-tick cooldown
&& (entity.timeUntilPortal < 1) //to prevent the player from teleporting all over the place we have a 50-tick cooldown
&& isEntityFacingDoor(down, (EntityLivingBase) entity)) {
this.toggleDoor(world, pos, false);
enterDimDoor(world, pos, entity);
@ -123,7 +123,7 @@ public abstract class BlockDimDoorBase extends BlockDoor implements IDimDoor, IT
if (riftTile.tryTeleport(entity)) {
//player is succesfully teleported
} else {
//probably should only happen on personal dimdoors
//probably should only happen on personal dimdoors?
if (entity instanceof EntityPlayer) {
EntityPlayer entityPlayer = (EntityPlayer) entity;
DimDoors.chat(entityPlayer, "Teleporting failed, but since mod is still in alpha, stuff like that might simply happen.");

View file

@ -1,8 +1,11 @@
package com.zixiken.dimdoors.shared.blocks;
import com.zixiken.dimdoors.shared.items.ModItems;
import com.zixiken.dimdoors.shared.tileentities.TileEntityDimDoorWarp;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public class BlockDimDoorWarp extends BlockDimDoorBase {
@ -19,4 +22,9 @@ public class BlockDimDoorWarp extends BlockDimDoorBase {
public Item getItemDoor() {
return ModItems.itemDimDoorWarp;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityDimDoorWarp();
}
}

View file

@ -1,5 +1,6 @@
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.shared.EnumPocketType;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.shared.RiftRegistry;
import java.util.Random;
@ -12,13 +13,14 @@ import net.minecraft.world.World;
public abstract class DDTileEntityBase extends TileEntity {
public boolean canRiftBePaired = true;
private boolean isPaired = false;
private int riftID = -1; //should not start at 0
private int pairedRiftID = -1;
private boolean isInPocket = false;
private int pocketID = -1;
private int depth = 0; //depth of the pocket it is in (not in a pocket -> 0)
protected boolean canRiftBePaired = true;
protected boolean isPaired = false;
protected int riftID = -1; //should not start at 0
protected int pairedRiftID = -1;
protected boolean isInPocket = false;
protected int pocketID = -1;
protected EnumPocketType pocketType;
protected int depth = 0; //depth of the pocket it is in (not in a pocket -> 0)
/**
*
@ -73,6 +75,9 @@ public abstract class DDTileEntityBase extends TileEntity {
pairedRiftID = nbt.getInteger("pairedRiftID");
isInPocket = nbt.getBoolean("isInPocket");
pocketID = nbt.getInteger("pocketID");
if (nbt.hasKey("pocketType")) {
pocketType = EnumPocketType.valueOf(nbt.getString("pocketType"));
}
depth = nbt.getInteger("depth");
} catch (Exception e) {
//reading these values should only fail on loading old saves, or loading old schematics, in which case the default values will do
@ -87,6 +92,9 @@ public abstract class DDTileEntityBase extends TileEntity {
nbt.setInteger("pairedRiftID", this.pairedRiftID);
nbt.setBoolean("isInPocket", this.isInPocket);
nbt.setInteger("pocketID", this.pocketID);
if (pocketType != null) {
nbt.setString("pocketType", this.pocketType.name());
}
nbt.setInteger("depth", this.depth);
return nbt;
}
@ -129,4 +137,8 @@ public abstract class DDTileEntityBase extends TileEntity {
public void setIsInPocket() {
isInPocket = true;
}
protected EnumPocketType getPocketType() {
return pocketType;
}
}

View file

@ -1,9 +1,12 @@
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.EnumPocketType;
import com.zixiken.dimdoors.shared.PocketRegistry;
import com.zixiken.dimdoors.shared.blocks.BlockDimDoor;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.shared.RiftRegistry;
import com.zixiken.dimdoors.shared.world.DimDoorDimensions;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
@ -16,7 +19,7 @@ public class TileEntityDimDoor extends DDTileEntityBase {
public boolean doorIsOpen = false;
public EnumFacing orientation = EnumFacing.SOUTH;
public byte lockStatus = 0;
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
@ -63,20 +66,15 @@ public class TileEntityDimDoor extends DDTileEntityBase {
@Override
public boolean tryTeleport(Entity entity) {
//DimDoors.log(this.getClass(), "Trying to teleport from rift " + getRiftID() + ".");
int otherRiftID = -1;
if (!isPaired()) {
//DimDoors.log(this.getClass(), "Trying to find suitable destination rift.");
int randomPairedRiftID = RiftRegistry.Instance.getRandomUnpairedRiftID(getRiftID());
if (randomPairedRiftID < 0) {
DimDoors.warn(this.getClass(), "No suitable destination rift was found.");
return false;
}
RiftRegistry.Instance.pair(getRiftID(), randomPairedRiftID);
//@todo try to automatically pair this door somehow
otherRiftID = getNewTeleportDestination();
} else {
otherRiftID = getPairedRiftID();
//DimDoors.log(this.getClass(), "This rift was already paired correctly.");
}
//DimDoors.log(this.getClass(), "Starting teleportation.");
return RiftRegistry.Instance.teleportEntityToRift(entity, getPairedRiftID()); //this seems to return false...
return RiftRegistry.Instance.teleportEntityToRift(entity, otherRiftID); //@todo this seems to return false?
}
public void uponDoorPlacement(@Nullable TileEntity possibleOldRift) {
@ -91,4 +89,46 @@ public class TileEntityDimDoor extends DDTileEntityBase {
//storing the orientation inside the tile-entity, because that thing can actually save the orientation in the worldsave, unlike the block itself, which fail at that stuff somehow
this.orientation = this.getWorld().getBlockState(this.getPos()).getValue(BlockDimDoor.FACING).getOpposite();
}
protected int getNewTeleportDestination() {
int otherRiftID = -1;
Location locationOfThisRift = RiftRegistry.Instance.getRiftLocation(this.riftID);
if (locationOfThisRift.getDimensionID() == DimDoorDimensions.getPocketDimensionType(EnumPocketType.DUNGEON).getId()) { //if this dimdoor is in a pocket Dungeon
//@todo choose between generating a new pocket or connecting to another door on a similar or close depth
if (randomBooleanChoice(20, 80)) {
otherRiftID = RiftRegistry.Instance.getRandomUnpairedRiftIDAroundDepth(getRiftID(), depth);
if (otherRiftID < 0) {
//@todo, this should rarely happen. Put in an easter egg?
otherRiftID = PocketRegistry.Instance.getEntranceDoorIDOfNewPocket(EnumPocketType.DUNGEON, getRandomisedDepth(), locationOfThisRift);
}
} else {
otherRiftID = PocketRegistry.Instance.getEntranceDoorIDOfNewPocket(EnumPocketType.DUNGEON, getRandomisedDepth(), locationOfThisRift);
}
} else {
otherRiftID = PocketRegistry.Instance.getEntranceDoorIDOfNewPocket(EnumPocketType.PUBLIC, 0, locationOfThisRift); //@todo should this depth be 1 instead?
}
if (otherRiftID < 0) {
DimDoors.warn(this.getClass(), "No suitable destination rift was found. This probably means that a pocket was created without any Doors.");
} else {
//@todo (should the other rift get loaded?)
RiftRegistry.Instance.pair(getRiftID(), otherRiftID);
}
return otherRiftID;
}
private boolean randomBooleanChoice(int trueWeight, int falseWeight) { //@todo make this a utility function
if (trueWeight <= 0 || falseWeight <= 0) {
throw new IllegalArgumentException("Either of both weights was 0 or lower. Both should be at least 1.");
}
Random random = new Random();
return (random.nextInt(trueWeight + falseWeight) < trueWeight);
}
protected int getRandomisedDepth() {
Random random = new Random();
int choice = random.nextInt(100);
return (choice < 20 ? depth - 1 : choice < 50 ? depth : depth + 1); //@todo get rid of hardcoded stuff
}
}

View file

@ -5,14 +5,25 @@
*/
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.shared.RiftRegistry;
import com.zixiken.dimdoors.shared.TeleportHelper;
import com.zixiken.dimdoors.shared.util.Location;
import net.minecraft.entity.Entity;
/**
*
* @author Robijnvogel
*/
public class TileEntityDimDoorChaos extends TileEntityDimDoor {
public TileEntityDimDoorChaos() {
canRiftBePaired = true;
public TileEntityDimDoorChaos() {
canRiftBePaired = false;
}
@Override
public boolean tryTeleport(Entity entity) { //this door is never paired
Location tpLocation = RiftRegistry.Instance.getRiftLocation(RiftRegistry.Instance.getRandomNonPersonalRiftID());
//@todo, this teleports to the location of the rift, not in front of the rift, like it should
return TeleportHelper.teleport(entity, tpLocation);
}
}

View file

@ -1,6 +1,12 @@
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.shared.EnumPocketType;
import com.zixiken.dimdoors.shared.IChunkLoader;
import com.zixiken.dimdoors.shared.PocketRegistry;
import com.zixiken.dimdoors.shared.RiftRegistry;
import com.zixiken.dimdoors.shared.util.Location;
import net.minecraft.entity.Entity;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
@ -57,4 +63,23 @@ public class TileEntityDimDoorGold extends TileEntityDimDoor implements IChunkLo
ForgeChunkManager.releaseTicket(chunkTicket);
super.invalidate();
}
@Override
protected int getNewTeleportDestination() {
//DimDoors.log(this.getClass(), "Trying to find suitable destination rift.");
int otherRiftID = RiftRegistry.Instance.getRandomUnpairedRiftIDAtDepth(getRiftID(), depth);
if (otherRiftID < 0) {
Location locationOfThisRift = RiftRegistry.Instance.getRiftLocation(this.riftID);
otherRiftID = PocketRegistry.Instance.getEntranceDoorIDOfNewPocket(EnumPocketType.DUNGEON, getRandomisedDepth(), locationOfThisRift);
}
if (otherRiftID < 0) {
DimDoors.warn(this.getClass(), "No suitable destination rift was found. This probably means that a pocket was created without any Doors.");
} else {
//@todo (should the other rift get loaded?)
RiftRegistry.Instance.pair(getRiftID(), otherRiftID);
}
return otherRiftID;
}
}

View file

@ -5,14 +5,40 @@
*/
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.shared.EnumPocketType;
import com.zixiken.dimdoors.shared.PocketRegistry;
import com.zixiken.dimdoors.shared.RiftRegistry;
import com.zixiken.dimdoors.shared.TeleportHelper;
import com.zixiken.dimdoors.shared.util.Location;
import com.zixiken.dimdoors.shared.world.DimDoorDimensions;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
/**
*
* @author Robijnvogel
*/
public class TileEntityDimDoorPersonal extends TileEntityDimDoor {
public TileEntityDimDoorPersonal() {
canRiftBePaired = true;
public TileEntityDimDoorPersonal() {
canRiftBePaired = false;
}
@Override
public boolean tryTeleport(Entity entity) { //this door is never paired
Location locationOfThisRift = RiftRegistry.Instance.getRiftLocation(this.riftID);
if (entity instanceof EntityPlayer) {
EntityPlayer entityPlayer = (EntityPlayer) entity;
if (locationOfThisRift.getDimensionID() == DimDoorDimensions.getPocketDimensionType(EnumPocketType.PRIVATE).getId()) {
return TeleportHelper.teleport(entity, PocketRegistry.Instance.getPocket(this.pocketID, EnumPocketType.PRIVATE).getDepthZeroLocation());
} else {
Location tpLocation = RiftRegistry.Instance.getRiftLocation(PocketRegistry.Instance.getPrivateDimDoorID(entityPlayer.getCachedUniqueIdString()));
//@todo, this teleports to the location of the rift, not in front of the rift, like it should
return TeleportHelper.teleport(entity, tpLocation);
}
} else {
return false;
}
}
}

View file

@ -0,0 +1,23 @@
package com.zixiken.dimdoors.shared.tileentities;
import com.zixiken.dimdoors.shared.Pocket;
import com.zixiken.dimdoors.shared.PocketRegistry;
import com.zixiken.dimdoors.shared.RiftRegistry;
import com.zixiken.dimdoors.shared.TeleportHelper;
import net.minecraft.entity.Entity;
public class TileEntityDimDoorWarp extends TileEntityDimDoor {
@Override
public boolean tryTeleport(Entity entity) {
if (isPaired()) {
return RiftRegistry.Instance.teleportEntityToRift(entity, getPairedRiftID());
}
if (!(this.isInPocket)) {
return false;
} else {
Pocket pocket = PocketRegistry.Instance.getPocket(this.pocketID, this.getPocketType());
return TeleportHelper.teleport(entity, pocket.getDepthZeroLocation());
}
}
}

View file

@ -1,7 +1,6 @@
package com.zixiken.dimdoors.shared.util;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@ -62,7 +61,7 @@ public class Location {
return new Location(dimID, blockPos);
}
public static NBTBase writeToNBT(Location location) {
public static NBTTagCompound writeToNBT(Location location) {
NBTTagCompound locationNBT = new NBTTagCompound();
locationNBT.setInteger("worldID", location.dimensionID);
locationNBT.setInteger("x", location.pos.getX());

View file

@ -5,7 +5,7 @@ import com.zixiken.dimdoors.shared.EnumPocketType;
public class WorldProviderDungeonPocket extends WorldProviderPublicPocket {
@Override
EnumPocketType getPocketType() {
public EnumPocketType getPocketType() {
return EnumPocketType.DUNGEON;
}

View file

@ -43,7 +43,7 @@ public class WorldProviderPersonalPocket extends WorldProviderPublicPocket {
}
@Override
EnumPocketType getPocketType() {
public EnumPocketType getPocketType() {
return EnumPocketType.PRIVATE;
}

View file

@ -90,7 +90,7 @@ public class WorldProviderPublicPocket extends WorldProvider {//@todo, we might
return 256;
}
EnumPocketType getPocketType() {
public EnumPocketType getPocketType() {
return EnumPocketType.PUBLIC;
}