Created build.gradle
Restructured folder structure for ForgeGradle Signed-off-by: deathrat <deathrat43@gmail.com>
This commit is contained in:
10
src/main/java/StevenDimDoors/README.md
Normal file
10
src/main/java/StevenDimDoors/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
DimDoors
|
||||
========
|
||||
|
||||
Dimensional Doors for Minecraft
|
||||
Adds several items that allow the player to move between and create dimensions
|
||||
|
||||
see the MC forum topic for details
|
||||
|
||||
http://www.minecraftforum.net/topic/1650007-147-dimensional-doors-v110-physics-what-physics-updated-with-fancy-opengl/
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.world.Teleporter;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
public class BlankTeleporter extends Teleporter
|
||||
{
|
||||
|
||||
|
||||
public BlankTeleporter(WorldServer par1WorldServer)
|
||||
{
|
||||
super(par1WorldServer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new portal near an entity.
|
||||
*/
|
||||
@Override
|
||||
public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setEntityPosition(Entity entity, double x, double y, double z)
|
||||
{
|
||||
entity.lastTickPosX = entity.prevPosX = entity.posX = x;
|
||||
entity.lastTickPosY = entity.prevPosY = entity.posY = y + entity.yOffset;
|
||||
entity.lastTickPosZ = entity.prevPosZ = entity.posZ = z;
|
||||
entity.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStalePortalLocations(long par1)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraftforge.client.IRenderHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class CloudRenderBlank extends IRenderHandler
|
||||
{
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void render(float partialTicks, WorldClient world, Minecraft mc)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
135
src/main/java/StevenDimDoors/mod_pocketDim/CommonProxy.java
Normal file
135
src/main/java/StevenDimDoors/mod_pocketDim/CommonProxy.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.network.IGuiHandler;
|
||||
public class CommonProxy implements IGuiHandler
|
||||
{
|
||||
public static String BLOCK_PNG = "/PocketBlockTextures.png";
|
||||
public static String ITEM_PNG = "/PocketItemTextures.png";
|
||||
public static String RIFT_PNG = "/RIFT.png";
|
||||
public static String RIFT2_PNG = "/RIFT2.png";
|
||||
public static String WARP_PNG = "/WARP.png";
|
||||
|
||||
public void registerRenderers()
|
||||
|
||||
{
|
||||
}
|
||||
public void registerEntity(Class <? extends Entity > entity, String entityname, int id, Object mod, int trackingrange, int updateFreq, boolean updatevelo)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void loadTextures()
|
||||
{
|
||||
}
|
||||
|
||||
public void writeNBTToFile(World world)
|
||||
{
|
||||
boolean flag = true;
|
||||
|
||||
try
|
||||
{
|
||||
File dataStore = world.getSaveHandler().getMapFileFromName("idcounts");
|
||||
String dirFolder = dataStore.getCanonicalPath();
|
||||
dirFolder = dirFolder.replace("idcounts.dat", "");
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
dirFolder.replace("saves/", FMLCommonHandler.instance().getMinecraftServerInstance().getFolderName());
|
||||
}
|
||||
|
||||
File file = new File(dirFolder, "GGMData.dat");
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
file.createNewFile();
|
||||
}
|
||||
|
||||
FileOutputStream fileoutputstream = new FileOutputStream(file);
|
||||
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
||||
|
||||
|
||||
|
||||
CompressedStreamTools.writeCompressed(nbttagcompound, fileoutputstream);
|
||||
fileoutputstream.close();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// exception.printStackTrace();
|
||||
|
||||
if (!(exception instanceof NullPointerException))
|
||||
{
|
||||
}
|
||||
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void readNBTFromFile(World world)
|
||||
{
|
||||
boolean flag = true;
|
||||
|
||||
try
|
||||
{
|
||||
File dataStore = world.getSaveHandler().getMapFileFromName("idcounts");
|
||||
String dirFolder = dataStore.getCanonicalPath();
|
||||
dirFolder = dirFolder.replace("idcounts.dat", "");
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
dirFolder.replace("saves/", FMLCommonHandler.instance().getMinecraftServerInstance().getFolderName());
|
||||
}
|
||||
|
||||
File file = new File(dirFolder, "GGMData.dat");
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
file.createNewFile();
|
||||
FileOutputStream fileoutputstream = new FileOutputStream(file);
|
||||
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
||||
|
||||
CompressedStreamTools.writeCompressed(nbttagcompound, fileoutputstream);
|
||||
fileoutputstream.close();
|
||||
}
|
||||
|
||||
/*FileInputStream fileinputstream = new FileInputStream(file);
|
||||
NBTTagCompound nbttagcompound = CompressedStreamTools.readCompressed(fileinputstream);
|
||||
fileinputstream.close();*/
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// exception.printStackTrace();
|
||||
|
||||
if (!(exception instanceof NullPointerException))
|
||||
{
|
||||
}
|
||||
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void printStringClient(String string)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.network.INetworkManager;
|
||||
import net.minecraft.network.NetLoginHandler;
|
||||
import net.minecraft.network.packet.NetHandler;
|
||||
import net.minecraft.network.packet.Packet1Login;
|
||||
import net.minecraft.network.packet.Packet250CustomPayload;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import cpw.mods.fml.common.network.IConnectionHandler;
|
||||
import cpw.mods.fml.common.network.Player;
|
||||
|
||||
public class ConnectionHandler implements IConnectionHandler
|
||||
{
|
||||
@Override
|
||||
public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager)
|
||||
{
|
||||
try
|
||||
{
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(PacketConstants.CLIENT_JOIN_PACKET_ID);
|
||||
PocketManager.writePacket(writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
packet.length = packet.data.length;
|
||||
manager.addToSendQueue(packet);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
//This shouldn't happen...
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) { }
|
||||
|
||||
@Override
|
||||
public void connectionOpened(NetHandler netClientHandler,MinecraftServer server, INetworkManager manager) { }
|
||||
|
||||
@Override
|
||||
public void connectionClosed(INetworkManager manager)
|
||||
{
|
||||
if(PocketManager.isConnected)
|
||||
{
|
||||
PocketManager.unload();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) { }
|
||||
|
||||
@Override
|
||||
public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager)
|
||||
{
|
||||
//Send information about all the registered dimensions and links to the client
|
||||
|
||||
}
|
||||
}
|
||||
135
src/main/java/StevenDimDoors/mod_pocketDim/CraftingManager.java
Normal file
135
src/main/java/StevenDimDoors/mod_pocketDim/CraftingManager.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import static StevenDimDoors.mod_pocketDim.mod_pocketDim.*;
|
||||
|
||||
public class CraftingManager
|
||||
{
|
||||
|
||||
public static void registerRecipies()
|
||||
{
|
||||
Item coreCraftingItem = Item.enderPearl;
|
||||
|
||||
if(properties.enableServerMode)
|
||||
{
|
||||
coreCraftingItem = itemWorldThread;
|
||||
}
|
||||
if (properties.CraftingDimensionalDoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemDimDoor, 1), new Object[]
|
||||
{
|
||||
" ", "yxy", " ", 'x', coreCraftingItem, 'y', Item.doorIron
|
||||
});
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(itemDimDoor, 1), new Object[]
|
||||
{
|
||||
" ", "yxy", " ", 'x', mod_pocketDim.itemStableFabric, 'y', Item.doorIron
|
||||
});
|
||||
}
|
||||
if(properties.CraftingUnstableDoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemChaosDoor, 1), new Object[]
|
||||
{
|
||||
" ", "yxy", " ", 'x', Item.eyeOfEnder, 'y', mod_pocketDim.itemDimDoor
|
||||
});
|
||||
}
|
||||
if(properties.CraftingWarpDoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemExitDoor, 1), new Object[]
|
||||
{
|
||||
" ", "yxy", " ", 'x', coreCraftingItem, 'y', Item.doorWood
|
||||
});
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(itemExitDoor, 1), new Object[]
|
||||
{
|
||||
" ", "yxy", " ", 'x', mod_pocketDim.itemStableFabric, 'y', Item.doorWood
|
||||
});
|
||||
}
|
||||
if(properties.CraftingTransTrapdoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(transTrapdoor, 1), new Object[]
|
||||
{
|
||||
" y ", " x ", " y ", 'x', coreCraftingItem, 'y', Block.trapdoor
|
||||
});
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(transTrapdoor, 1), new Object[]
|
||||
{
|
||||
" y ", " x ", " y ", 'x', mod_pocketDim.itemStableFabric, 'y', Block.trapdoor
|
||||
});
|
||||
}
|
||||
if(properties.CraftingRiftSignatureAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemLinkSignature, 1), new Object[]
|
||||
{
|
||||
" y ", "yxy", " y ", 'x', coreCraftingItem, 'y', Item.ingotIron
|
||||
});
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(itemLinkSignature, 1), new Object[]
|
||||
{
|
||||
" y ", "yxy", " y ", 'x', mod_pocketDim.itemStableFabric, 'y', Item.ingotIron
|
||||
});
|
||||
}
|
||||
|
||||
if(properties.CraftingRiftRemoverAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemRiftRemover, 1), new Object[]
|
||||
{
|
||||
" y ", "yxy", " y ", 'x', coreCraftingItem, 'y', Item.ingotGold
|
||||
});
|
||||
GameRegistry.addRecipe(new ItemStack(itemRiftRemover, 1), new Object[]
|
||||
{
|
||||
"yyy", "yxy", "yyy", 'x', mod_pocketDim.itemStableFabric, 'y', Item.ingotGold
|
||||
});
|
||||
}
|
||||
|
||||
if (properties.CraftingRiftBladeAllowed)
|
||||
{
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(itemRiftBlade, 1), new Object[]
|
||||
{
|
||||
" x ", " x ", " y ", 'x', coreCraftingItem, 'y',mod_pocketDim.itemRiftRemover
|
||||
});
|
||||
}
|
||||
|
||||
if (properties.CraftingStableFabricAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(itemStableFabric, 1), new Object[]
|
||||
{
|
||||
"yyy", "yxy", "yyy", 'x', coreCraftingItem, 'y', mod_pocketDim.itemWorldThread
|
||||
});
|
||||
}
|
||||
|
||||
if (properties.CraftingStabilizedRiftSignatureAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(mod_pocketDim.itemStabilizedLinkSignature,1), new Object[]
|
||||
{
|
||||
" y ", "yxy", " y ", 'x', mod_pocketDim.itemLinkSignature, 'y', mod_pocketDim.itemStableFabric
|
||||
});
|
||||
}
|
||||
if (properties.CraftingGoldDimDoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(mod_pocketDim.itemGoldDimDoor,1), new Object[]
|
||||
{
|
||||
" x ", " y ", " x ", 'x', mod_pocketDim.itemGoldDoor, 'y', Item.eyeOfEnder
|
||||
});
|
||||
}
|
||||
if (properties.CraftingGoldDoorAllowed)
|
||||
{
|
||||
GameRegistry.addRecipe(new ItemStack(mod_pocketDim.itemGoldDoor,1), new Object[]
|
||||
{
|
||||
"yy ", "yy ", "yy ", 'y', Item.ingotGold
|
||||
});
|
||||
|
||||
GameRegistry.addRecipe(new ItemStack(mod_pocketDim.itemGoldDoor,1), new Object[]
|
||||
{
|
||||
" yy", " yy", " yy", 'y', Item.ingotGold
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
212
src/main/java/StevenDimDoors/mod_pocketDim/DDLoot.java
Normal file
212
src/main/java/StevenDimDoors/mod_pocketDim/DDLoot.java
Normal file
@@ -0,0 +1,212 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.WeightedRandom;
|
||||
import net.minecraft.util.WeightedRandomChestContent;
|
||||
import net.minecraftforge.common.ChestGenHooks;
|
||||
|
||||
/*
|
||||
* Registers a category of loot chests for Dimensional Doors in Forge.
|
||||
*/
|
||||
public class DDLoot {
|
||||
|
||||
//These are the categories of loot to be merged into our chests
|
||||
static final String[] chestSources = new String[] {
|
||||
ChestGenHooks.MINESHAFT_CORRIDOR,
|
||||
ChestGenHooks.PYRAMID_DESERT_CHEST,
|
||||
ChestGenHooks.PYRAMID_JUNGLE_CHEST,
|
||||
ChestGenHooks.STRONGHOLD_CORRIDOR,
|
||||
ChestGenHooks.STRONGHOLD_CROSSING,
|
||||
ChestGenHooks.VILLAGE_BLACKSMITH,
|
||||
ChestGenHooks.DUNGEON_CHEST
|
||||
};
|
||||
|
||||
public static final String DIMENSIONAL_DUNGEON_CHEST = "dimensionalDungeonChest";
|
||||
public static ChestGenHooks DungeonChestInfo = null;
|
||||
private static final int CHEST_SIZE = 5;
|
||||
|
||||
private static final int COMMON_LOOT_WEIGHT = 9; //1 less than weight of iron ingots
|
||||
private static final int UNCOMMON_LOOT_WEIGHT = 4; //1 less than weight of iron armor
|
||||
private static final int RARE_LOOT_WEIGHT = 1; //Same weight as music discs, golden apple
|
||||
private static final int DUNGEON_CHEST_WEIGHT_INFLATION = 10; // (weight of iron ingots in dungeon) / (weight of iron ingots in other chests)
|
||||
|
||||
private DDLoot() { }
|
||||
|
||||
public static void registerInfo()
|
||||
{
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
//Register the dimensional dungeon chest with ChestGenHooks. This isn't necessary, but allows
|
||||
//other mods to add their own loot to our chests if they know our loot category, without having
|
||||
//to interface with our code.
|
||||
DungeonChestInfo = ChestGenHooks.getInfo(DIMENSIONAL_DUNGEON_CHEST);
|
||||
DungeonChestInfo.setMin(CHEST_SIZE);
|
||||
DungeonChestInfo.setMax(CHEST_SIZE);
|
||||
|
||||
//Merge the item lists from source chests
|
||||
//This means chests will include future loot as Minecraft updates! ^_^
|
||||
ArrayList<WeightedRandomChestContent> items = mergeCategories(chestSources);
|
||||
|
||||
//Add any enabled DD loot to the list of items
|
||||
addContent(properties.FabricOfRealityLootEnabled, items, mod_pocketDim.blockDimWall.blockID, 8, 32, COMMON_LOOT_WEIGHT);
|
||||
|
||||
addContent(properties.DimensionalDoorLootEnabled, items, mod_pocketDim.itemDimDoor.itemID, UNCOMMON_LOOT_WEIGHT);
|
||||
addContent(properties.WarpDoorLootEnabled, items, mod_pocketDim.itemExitDoor.itemID, UNCOMMON_LOOT_WEIGHT);
|
||||
addContent(properties.TransTrapdoorLootEnabled, items, mod_pocketDim.transTrapdoor.blockID, UNCOMMON_LOOT_WEIGHT);
|
||||
addContent(properties.RiftSignatureLootEnabled, items, mod_pocketDim.itemLinkSignature.itemID, UNCOMMON_LOOT_WEIGHT);
|
||||
addContent(properties.StableFabricLootEnabled, items, mod_pocketDim.itemStableFabric.itemID, UNCOMMON_LOOT_WEIGHT);
|
||||
addContent(properties.RiftRemoverLootEnabled, items, mod_pocketDim.itemRiftRemover.itemID, UNCOMMON_LOOT_WEIGHT);
|
||||
|
||||
addContent(properties.UnstableDoorLootEnabled, items, mod_pocketDim.itemChaosDoor.itemID, RARE_LOOT_WEIGHT);
|
||||
addContent(properties.StabilizedRiftSignatureLootEnabled, items, mod_pocketDim.itemStabilizedLinkSignature.itemID, RARE_LOOT_WEIGHT);
|
||||
addContent(properties.RiftBladeLootEnabled, items, mod_pocketDim.itemRiftBlade.itemID, RARE_LOOT_WEIGHT);
|
||||
|
||||
//Add all the items to our dungeon chest
|
||||
addItemsToContainer(DungeonChestInfo, items);
|
||||
}
|
||||
|
||||
private static ArrayList<WeightedRandomChestContent> mergeCategories(String[] categories)
|
||||
{
|
||||
//Retrieve the items of each container category and merge the lists together. If two matching items
|
||||
//are found, choose the item with the minimum weight. Special checks are included for DUNGEON_CHEST
|
||||
//because the items in that category have strange weights that are incompatible with all other
|
||||
//chest categories.
|
||||
|
||||
Random random = new Random();
|
||||
HashMap<Integer, WeightedRandomChestContent> container = new HashMap<Integer, WeightedRandomChestContent>();
|
||||
|
||||
for (String category : categories)
|
||||
{
|
||||
WeightedRandomChestContent[] items = ChestGenHooks.getItems(category, random);
|
||||
for (WeightedRandomChestContent item : items)
|
||||
{
|
||||
ItemStack stack = item.theItemId;
|
||||
int id = stack.itemID;
|
||||
int subtype = stack.getItem().getHasSubtypes() ? stack.getItemDamage() : 0;
|
||||
|
||||
//Correct the weights of Vanilla dungeon chests (DUNGEON_CHEST)
|
||||
//Comparing by String references is valid here since they should match!
|
||||
if (category == ChestGenHooks.DUNGEON_CHEST)
|
||||
{
|
||||
//It's okay to modify the weights directly. These are copies of instances,
|
||||
//not direct references. It won't affect Vanilla chests.
|
||||
item.itemWeight /= DUNGEON_CHEST_WEIGHT_INFLATION;
|
||||
if (item.itemWeight == 0)
|
||||
item.itemWeight = 1;
|
||||
}
|
||||
|
||||
//Generate an identifier for this item using its item ID and damage value,
|
||||
//if it has subtypes. This solves the issue of matching items that have
|
||||
//the same item ID but different subtypes (e.g. wood planks, dyes).
|
||||
int key = ((subtype & 0xFFFF) << 16) + ((id & 0xFFFF) << 16);
|
||||
WeightedRandomChestContent other = container.get(key);
|
||||
if (other == null)
|
||||
{
|
||||
//This item has not been seen before. Simply add it to the container.
|
||||
container.put(key, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
//This item conflicts with an existing entry. Replace that entry
|
||||
//if our current item has a lower weight.
|
||||
if (item.itemWeight < other.itemWeight)
|
||||
{
|
||||
container.put(key, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//I've added a minor hack here to make enchanted books more common
|
||||
//If this is necessary for more items, create an override table and use that
|
||||
//rather than hardcoding the changes below
|
||||
final int enchantedBookID = Item.enchantedBook.itemID;
|
||||
for (WeightedRandomChestContent item : container.values())
|
||||
{
|
||||
if (item.theItemId.itemID == enchantedBookID)
|
||||
{
|
||||
item.itemWeight = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Return merged list
|
||||
return new ArrayList<WeightedRandomChestContent>( container.values() );
|
||||
}
|
||||
|
||||
private static void addContent(boolean include, ArrayList<WeightedRandomChestContent> items,
|
||||
int itemID, int weight)
|
||||
{
|
||||
if (include)
|
||||
items.add(new WeightedRandomChestContent(itemID, 0, 1, 1, weight));
|
||||
}
|
||||
|
||||
private static void addContent(boolean include, ArrayList<WeightedRandomChestContent> items,
|
||||
int itemID, int minAmount, int maxAmount, int weight)
|
||||
{
|
||||
if (include)
|
||||
items.add(new WeightedRandomChestContent(itemID, 0, minAmount, maxAmount, weight));
|
||||
}
|
||||
|
||||
private static void addItemsToContainer(ChestGenHooks container, ArrayList<WeightedRandomChestContent> items)
|
||||
{
|
||||
//System.out.println("Preparing Chest Stuff");
|
||||
|
||||
for (WeightedRandomChestContent item : items)
|
||||
{
|
||||
container.addItem(item);
|
||||
//Uncomment this code to print out loot and weight pairs
|
||||
//System.out.println(item.theItemId.getDisplayName() + "\t" + item.itemWeight);
|
||||
}
|
||||
}
|
||||
|
||||
public static void generateChestContents(ChestGenHooks chestInfo, IInventory inventory, Random random)
|
||||
{
|
||||
//This is a custom version of net.minecraft.util.WeightedRandomChestContent.generateChestContents()
|
||||
//It's designed to avoid the following bugs in MC 1.5:
|
||||
//1. The randomized filling algorithm will sometimes overwrite item stacks with other stacks
|
||||
//2. If multiple enchanted books appear, then they will have the same enchantment
|
||||
|
||||
//The prime number below is used for choosing chest slots in a seemingly-random pattern. Its value
|
||||
//was selected specifically to achieve a spread-out distribution for chests with up to 104 slots.
|
||||
//Choosing a prime number ensures that our increments are relatively-prime to the chest size, which
|
||||
//means we'll cover all the slots before repeating any. This is mathematically guaranteed.
|
||||
final int primeOffset = 239333;
|
||||
|
||||
int count = chestInfo.getCount(random);
|
||||
int size = inventory.getSizeInventory();
|
||||
WeightedRandomChestContent[] content = chestInfo.getItems(random);
|
||||
|
||||
for (int k = 0; k < count; k++)
|
||||
{
|
||||
WeightedRandomChestContent selection = (WeightedRandomChestContent)WeightedRandom.getRandomItem(random, content);
|
||||
|
||||
//Call getChestGenBase() to make sure we generate a different enchantment for books.
|
||||
//Don't just use a condition to check if the item is an instance of ItemEnchantedBook because
|
||||
//we don't know if other mods might add items that also need to be regenerated.
|
||||
selection = selection.theItemId.getItem().getChestGenBase(chestInfo, random, selection);
|
||||
|
||||
ItemStack[] stacks = ChestGenHooks.generateStacks(random, selection.theItemId, selection.theMinimumChanceToGenerateItem, selection.theMaximumChanceToGenerateItem);
|
||||
|
||||
for (ItemStack item : stacks)
|
||||
{
|
||||
int limit = size;
|
||||
int index = random.nextInt(size);
|
||||
|
||||
while (limit > 0 && inventory.getStackInSlot(index) != null)
|
||||
{
|
||||
limit--;
|
||||
index = (index + primeOffset) % size;
|
||||
}
|
||||
|
||||
inventory.setInventorySlotContents(index, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
275
src/main/java/StevenDimDoors/mod_pocketDim/DDProperties.java
Normal file
275
src/main/java/StevenDimDoors/mod_pocketDim/DDProperties.java
Normal file
@@ -0,0 +1,275 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraftforge.common.Configuration;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner;
|
||||
import StevenDimDoors.mod_pocketDim.world.GatewayGenerator;
|
||||
|
||||
public class DDProperties
|
||||
{
|
||||
/**
|
||||
* Block IDs
|
||||
*/
|
||||
|
||||
public final int UnstableDoorID;
|
||||
public final int DimensionalDoorID;
|
||||
public final int GoldDoorID;
|
||||
public final int GoldDimDoorID;
|
||||
public final int WarpDoorID;
|
||||
public final int TransTrapdoorID;
|
||||
public final int TransientDoorID;
|
||||
public final int FabricBlockID;
|
||||
public final int RiftBlockID;
|
||||
|
||||
/**
|
||||
* World Generation Block IDs
|
||||
*/
|
||||
|
||||
public final int LimboBlockID;
|
||||
public final int PermaFabricBlockID;
|
||||
|
||||
/**
|
||||
* Item IDs
|
||||
*/
|
||||
|
||||
public final int RiftBladeItemID;
|
||||
public final int RiftSignatureItemID;
|
||||
public final int GoldDimDoorItemID;
|
||||
public final int GoldDoorItemID;
|
||||
public final int RiftRemoverItemID;
|
||||
public final int StableFabricItemID;
|
||||
public final int StabilizedRiftSignatureItemID;
|
||||
public final int DimensionalDoorItemID;
|
||||
public final int UnstableDoorItemID;
|
||||
public final int WarpDoorItemID;
|
||||
public final int ItemWorldThreadID;
|
||||
|
||||
|
||||
/**
|
||||
* Other IDs
|
||||
*/
|
||||
|
||||
public final int LimboBiomeID;
|
||||
public final int PocketBiomeID;
|
||||
public final int LimboDimensionID;
|
||||
public final int LimboProviderID;
|
||||
public final int PocketProviderID;
|
||||
public final int DoorRenderEntityID;
|
||||
public final int MonolithEntityID;
|
||||
|
||||
/**
|
||||
* Crafting Flags
|
||||
*/
|
||||
|
||||
public final boolean CraftingDimensionalDoorAllowed;
|
||||
public final boolean CraftingWarpDoorAllowed;
|
||||
public final boolean CraftingRiftSignatureAllowed;
|
||||
public final boolean CraftingRiftRemoverAllowed;
|
||||
public final boolean CraftingUnstableDoorAllowed;
|
||||
public final boolean CraftingRiftBladeAllowed;
|
||||
public final boolean CraftingTransTrapdoorAllowed;
|
||||
public final boolean CraftingStabilizedRiftSignatureAllowed;
|
||||
public final boolean CraftingStableFabricAllowed;
|
||||
public final boolean CraftingGoldDimDoorAllowed;
|
||||
public final boolean CraftingGoldDoorAllowed;
|
||||
|
||||
/**
|
||||
* Loot Flags
|
||||
*/
|
||||
|
||||
public final boolean DimensionalDoorLootEnabled;
|
||||
public final boolean WarpDoorLootEnabled;
|
||||
public final boolean UnstableDoorLootEnabled;
|
||||
public final boolean TransTrapdoorLootEnabled;
|
||||
public final boolean RiftSignatureLootEnabled;
|
||||
public final boolean RiftRemoverLootEnabled;
|
||||
public final boolean StabilizedRiftSignatureLootEnabled;
|
||||
public final boolean RiftBladeLootEnabled;
|
||||
public final boolean StableFabricLootEnabled;
|
||||
public final boolean FabricOfRealityLootEnabled;
|
||||
|
||||
/**
|
||||
* Other Flags
|
||||
*/
|
||||
|
||||
public final boolean enableServerMode;
|
||||
public final boolean WorldRiftGenerationEnabled;
|
||||
public final boolean RiftSpreadEnabled;
|
||||
public final boolean RiftGriefingEnabled;
|
||||
public final boolean RiftsSpawnEndermenEnabled;
|
||||
public final boolean LimboEnabled;
|
||||
public final boolean HardcoreLimboEnabled;
|
||||
public final boolean LimboReturnsInventoryEnabled;
|
||||
public final boolean DoorRenderingEnabled;
|
||||
public final boolean TNFREAKINGT_Enabled;
|
||||
|
||||
|
||||
/**
|
||||
* Other
|
||||
*/
|
||||
|
||||
public final int NonTntWeight;
|
||||
public final int ClusterGenerationChance;
|
||||
public final int GatewayGenerationChance;
|
||||
public final int MonolithSpawningChance;
|
||||
public final int LimboReturnRange;
|
||||
public final String CustomSchematicDirectory;
|
||||
|
||||
|
||||
//Singleton instance
|
||||
private static DDProperties instance = null;
|
||||
//Path for custom dungeons within configuration directory
|
||||
private final String CUSTOM_SCHEMATIC_SUBDIRECTORY = "/DimDoors_Custom_schematics";
|
||||
//Names of categories
|
||||
private final String CATEGORY_SERVERMODE = "server mode";
|
||||
private final String CATEGORY_CRAFTING = "crafting";
|
||||
private final String CATEGORY_ENTITY = "entity";
|
||||
private final String CATEGORY_DIMENSION = "dimension";
|
||||
private final String CATEGORY_PROVIDER = "provider";
|
||||
private final String CATEGORY_BIOME = "biome";
|
||||
private final String CATEGORY_LOOT = "loot";
|
||||
|
||||
private DDProperties(File configFile)
|
||||
{
|
||||
//Load the configuration. This must be done in the constructor, even though I'd rather have a separate
|
||||
//function, because "blank final" variables must be initialized within the constructor.
|
||||
|
||||
CustomSchematicDirectory = configFile.getParent() + CUSTOM_SCHEMATIC_SUBDIRECTORY;
|
||||
Configuration config = new Configuration(configFile);
|
||||
config.load();
|
||||
|
||||
CraftingDimensionalDoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Dimensional Door", true).getBoolean(true);
|
||||
CraftingWarpDoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Warp Door", true).getBoolean(true);
|
||||
CraftingUnstableDoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Unstable Door", true).getBoolean(true);
|
||||
CraftingTransTrapdoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Transdimensional Trapdoor", true).getBoolean(true);
|
||||
CraftingRiftSignatureAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Rift Signature", true).getBoolean(true);
|
||||
CraftingRiftRemoverAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Rift Remover", true).getBoolean(true);
|
||||
CraftingStabilizedRiftSignatureAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Stabilized Rift Signature", true).getBoolean(true);
|
||||
CraftingRiftBladeAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Rift Blade", true).getBoolean(true);
|
||||
CraftingStableFabricAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Stable Fabric", true).getBoolean(true);
|
||||
CraftingGoldDimDoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Crafting Golden Dimensional Door", true).getBoolean(true);
|
||||
CraftingGoldDoorAllowed = config.get(CATEGORY_CRAFTING, "Allow Golden Door", true).getBoolean(true);
|
||||
|
||||
DimensionalDoorLootEnabled = config.get(CATEGORY_LOOT, "Enable Dimensional Door Loot", true).getBoolean(true);
|
||||
WarpDoorLootEnabled = config.get(CATEGORY_LOOT, "Enable Warp Door Loot", false).getBoolean(false);
|
||||
UnstableDoorLootEnabled = config.get(CATEGORY_LOOT, "Enable Unstable Door Loot", false).getBoolean(false);
|
||||
TransTrapdoorLootEnabled = config.get(CATEGORY_LOOT, "Enable Transdimensional Trapdoor Loot", false).getBoolean(false);
|
||||
RiftSignatureLootEnabled = config.get(CATEGORY_LOOT, "Enable Rift Signature Loot", true).getBoolean(true);
|
||||
RiftRemoverLootEnabled = config.get(CATEGORY_LOOT, "Enable Rift Remover Loot", true).getBoolean(true);
|
||||
StabilizedRiftSignatureLootEnabled = config.get(CATEGORY_LOOT, "Enable Stabilized Rift Signature Loot", false).getBoolean(false);
|
||||
RiftBladeLootEnabled = config.get(CATEGORY_LOOT, "Enable Rift Blade Loot", true).getBoolean(true);
|
||||
StableFabricLootEnabled = config.get(CATEGORY_LOOT, "Enable Stable Fabric Loot", false).getBoolean(false);
|
||||
FabricOfRealityLootEnabled = config.get(CATEGORY_LOOT, "Enable Fabric of Reality Loot", true).getBoolean(true);
|
||||
|
||||
RiftGriefingEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift Griefing", true,
|
||||
"Sets whether rifts destroy blocks around them or not").getBoolean(true);
|
||||
RiftSpreadEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift Spread", true,
|
||||
"Sets whether rifts create more rifts when they are near other rifts").getBoolean(true);
|
||||
RiftsSpawnEndermenEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Endermen Spawning from Rifts", true,
|
||||
"Sets whether groups of connected rifts will spawn Endermen").getBoolean(true);
|
||||
|
||||
LimboEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Limbo", true,
|
||||
"Sets whether the Limbo dimension is activated").getBoolean(true);
|
||||
LimboReturnsInventoryEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Limbo Returns Inventory", true,
|
||||
"Sets whether players keep their inventories upon dying and respawning in Limbo").getBoolean(true);
|
||||
HardcoreLimboEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Hardcore Limbo", false,
|
||||
"Sets whether players that die in Limbo will respawn there").getBoolean(false);
|
||||
LimboReturnRange = config.get(Configuration.CATEGORY_GENERAL, "Limbo Return Range", 500,
|
||||
"Sets the farthest distance that Limbo can send you upon returning to the Overworld").getInt();
|
||||
DoorRenderingEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Door Rendering", true).getBoolean(true);
|
||||
|
||||
TNFREAKINGT_Enabled = config.get(Configuration.CATEGORY_GENERAL, "EXPLOSIONS!!???!!!?!?!!", false).getBoolean(false);
|
||||
NonTntWeight = config.get(Configuration.CATEGORY_GENERAL, "HOWMUCHTNT", 25,
|
||||
"Weighs the chance that a block will not be TNT. Must be greater than or equal to 0. " +
|
||||
"EXPLOSIONS must be set to true for this to have any effect.").getInt();
|
||||
|
||||
enableServerMode = config.get(CATEGORY_SERVERMODE, "Server Mode", false,
|
||||
"Enables servermode, changing all crafting recipies to require stabilized fabric. " +
|
||||
"Stabilized fabric, in turn, requires the item World Thread, which is not craftable or obtainable at all. "+
|
||||
"It is up to the server manager on how to distribute it.").getBoolean(false);
|
||||
|
||||
DoorRenderEntityID=config.get(CATEGORY_ENTITY, "Door Render Entity ID", 89).getInt();
|
||||
MonolithEntityID = config.get(CATEGORY_ENTITY, "Monolith Entity ID", 125).getInt();
|
||||
|
||||
DimensionalDoorID = config.getBlock("Dimensional Door Block ID", 1970).getInt();
|
||||
TransTrapdoorID = config.getBlock("Transdimensional Trapdoor Block ID", 1971).getInt();
|
||||
FabricBlockID =config.getBlock("Fabric Of Reality Block ID", 1973).getInt();
|
||||
WarpDoorID = config.getBlock("Warp Door Block ID", 1975).getInt();
|
||||
RiftBlockID = config.getBlock("Rift Block ID", 1977).getInt();
|
||||
UnstableDoorID = config.getBlock("Unstable Door Block ID", 1978).getInt();
|
||||
TransientDoorID = config.getBlock("Transient Door Block ID", 1979).getInt();
|
||||
GoldDoorID = config.getBlock("Gold Door Block ID", 1980).getInt();
|
||||
GoldDimDoorID = config.getBlock("Gold Dim Door Block ID", 1981).getInt();
|
||||
|
||||
WarpDoorItemID = config.getItem("Warp Door Item ID", 5670).getInt();
|
||||
RiftRemoverItemID = config.getItem("Rift Remover Item ID", 5671).getInt();
|
||||
StableFabricItemID = config.getItem("Stable Fabric Item ID", 5672).getInt();
|
||||
UnstableDoorItemID = config.getItem("Unstable Door Item ID", 5673).getInt();
|
||||
DimensionalDoorItemID = config.getItem("Dimensional Door Item ID", 5674).getInt();
|
||||
RiftSignatureItemID = config.getItem("Rift Signature Item ID", 5675).getInt();
|
||||
RiftBladeItemID = config.getItem("Rift Blade Item ID", 5676).getInt();
|
||||
StabilizedRiftSignatureItemID = config.getItem("Stabilized Rift Signature Item ID", 5677).getInt();
|
||||
GoldDoorItemID = config.getItem("Gold Door Item ID", 5678).getInt();
|
||||
GoldDimDoorItemID = config.getItem("Gold Dim Door Item ID", 5679).getInt();
|
||||
ItemWorldThreadID = config.getItem("World Thread Item ID", 5680).getInt();
|
||||
|
||||
LimboBlockID = config.getTerrainBlock("World Generation Block IDs - must be less than 256", "Limbo Block ID", 217,
|
||||
"Blocks used for the terrain in Limbo").getInt();
|
||||
PermaFabricBlockID = config.getTerrainBlock("World Generation Block IDs - must be less than 256",
|
||||
"Perma Fabric Block ID", 220, "Blocks used for enclosing pocket dimensions").getInt();
|
||||
|
||||
LimboDimensionID = config.get(CATEGORY_DIMENSION, "Limbo Dimension ID", -23).getInt();
|
||||
PocketProviderID = config.get(CATEGORY_PROVIDER, "Pocket Provider ID", 24).getInt();
|
||||
LimboProviderID = config.get(CATEGORY_PROVIDER, "Limbo Provider ID", 13).getInt();
|
||||
|
||||
WorldRiftGenerationEnabled = config.get(Configuration.CATEGORY_GENERAL, "Enable Rift World Generation", true,
|
||||
"Sets whether dungeon rifts generate in dimensions other than Limbo").getBoolean(true);
|
||||
|
||||
MonolithSpawningChance = config.get(Configuration.CATEGORY_GENERAL, "Monolith Spawning Chance", 28,
|
||||
"Sets the chance (out of " + MonolithSpawner.MAX_MONOLITH_SPAWNING_CHANCE + ") that Monoliths will " +
|
||||
"spawn in a given Limbo chunk. The default chance is 28.").getInt();
|
||||
|
||||
ClusterGenerationChance = config.get(Configuration.CATEGORY_GENERAL, "Cluster Generation Chance", 2,
|
||||
"Sets the chance (out of " + GatewayGenerator.MAX_CLUSTER_GENERATION_CHANCE + ") that a cluster of rifts will " +
|
||||
"generate in a given chunk. The default chance is 2.").getInt();
|
||||
|
||||
GatewayGenerationChance = config.get(Configuration.CATEGORY_GENERAL, "Gateway Generation Chance", 15,
|
||||
"Sets the chance (out of " + GatewayGenerator.MAX_GATEWAY_GENERATION_CHANCE + ") that a Rift Gateway will " +
|
||||
"generate in a given chunk. The default chance is 15.").getInt();
|
||||
|
||||
LimboBiomeID = config.get(CATEGORY_BIOME, "Limbo Biome ID", 251).getInt();
|
||||
PocketBiomeID = config.get(CATEGORY_BIOME, "Pocket Biome ID", 250).getInt();
|
||||
|
||||
config.save();
|
||||
|
||||
//Unfortunately, there are users out there who have been misconfiguring the worldgen blocks to have IDs above 255.
|
||||
//This leads to disastrous and cryptic errors in other areas of Minecraft. To prevent headaches, we'll throw
|
||||
//an exception here if the blocks have invalid IDs.
|
||||
if (LimboBlockID > 255 || PermaFabricBlockID > 255)
|
||||
{
|
||||
throw new IllegalStateException("World generation blocks MUST have block IDs less than 256. Fix your configuration!");
|
||||
}
|
||||
}
|
||||
|
||||
public static DDProperties initialize(File configFile)
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new DDProperties(configFile);
|
||||
else
|
||||
throw new IllegalStateException("Cannot initialize DDProperties twice");
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static DDProperties instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
//This is to prevent some frustrating bugs that could arise when classes
|
||||
//are loaded in the wrong order. Trust me, I had to squash a few...
|
||||
throw new IllegalStateException("Instance of DDProperties requested before initialization");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
257
src/main/java/StevenDimDoors/mod_pocketDim/DimData.java
Normal file
257
src/main/java/StevenDimDoors/mod_pocketDim/DimData.java
Normal file
@@ -0,0 +1,257 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
/**Class that contains all the information about a specific dim that is pertienent to Dim Doors. Holds all the rifts present in the dim sorted by x,y,z and
|
||||
* wether or not the dim is a pocket or not, along with its depth.
|
||||
* @Return
|
||||
*/
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
@Deprecated
|
||||
public class DimData implements Serializable
|
||||
{
|
||||
public int dimID;
|
||||
public int depth;
|
||||
public int dimOrientation;
|
||||
|
||||
public World world;
|
||||
|
||||
public LinkData exitDimLink;
|
||||
|
||||
public boolean isPocket;
|
||||
public boolean hasBeenFilled=false;
|
||||
public boolean hasDoor=false;
|
||||
public boolean isDimRandomRift=false;
|
||||
public Object dungeonGenerator = null;
|
||||
//public boolean isPrivatePocket = false;
|
||||
public HashMap<Integer, HashMap<Integer, HashMap<Integer, LinkData>>> linksInThisDim = new HashMap();
|
||||
HashMap<Integer, LinkData> dimX;
|
||||
HashMap<Integer, HashMap<Integer, LinkData>> dimY ;
|
||||
|
||||
static final long serialVersionUID = 454342L;
|
||||
|
||||
public DimData(int dimID, boolean isPocket, int depth, LinkData exitLinkData)
|
||||
{
|
||||
this.dimID=dimID;
|
||||
this.depth=depth;
|
||||
this.isPocket=isPocket;
|
||||
|
||||
this.exitDimLink= exitLinkData;
|
||||
}
|
||||
|
||||
public DimData(int dimID, boolean isPocket, int depth, int exitLinkDimID, int exitX, int exitY, int exitZ)
|
||||
{
|
||||
this(dimID, isPocket, depth, new LinkData(exitLinkDimID, exitX, exitY, exitZ));
|
||||
}
|
||||
|
||||
public LinkData findNearestRift(World world, int range, int x, int y, int z)
|
||||
{
|
||||
LinkData nearest=null;
|
||||
float distance=range+1;
|
||||
int i=-range;
|
||||
int j=-range;
|
||||
int k=-range;
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
while (i<range)
|
||||
{
|
||||
while (j<range)
|
||||
{
|
||||
while (k<range)
|
||||
{
|
||||
if (world.getBlockId(x+i, y+j, z+k) == properties.RiftBlockID && MathHelper.abs(i)+MathHelper.abs(j)+MathHelper.abs(k)<distance)
|
||||
{
|
||||
if(MathHelper.abs(i)+MathHelper.abs(j)+MathHelper.abs(k)!=0)
|
||||
{
|
||||
nearest=this.findLinkAtCoords(x+i, y+j, z+k);
|
||||
distance=MathHelper.abs(i)+MathHelper.abs(j)+MathHelper.abs(k);
|
||||
}
|
||||
|
||||
}
|
||||
k++;
|
||||
}
|
||||
k=-range;
|
||||
j++;
|
||||
|
||||
}
|
||||
j=-range;
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return nearest;
|
||||
|
||||
}
|
||||
|
||||
public ArrayList findRiftsInRange(World world, int range, int x, int y, int z)
|
||||
{
|
||||
LinkData nearest=null;
|
||||
ArrayList rifts = new ArrayList();
|
||||
int i=-range;
|
||||
int j=-range;
|
||||
int k=-range;
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
while (i<range)
|
||||
{
|
||||
while (j<range)
|
||||
{
|
||||
while (k<range)
|
||||
{
|
||||
if(world.getBlockId(x+i, y+j, z+k)==properties.RiftBlockID)
|
||||
{
|
||||
if(MathHelper.abs(i)+MathHelper.abs(j)+MathHelper.abs(k)!=0)
|
||||
{
|
||||
nearest=this.findLinkAtCoords(x+i, y+j, z+k);
|
||||
if(nearest!=null)
|
||||
{
|
||||
rifts.add(nearest);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
k++;
|
||||
}
|
||||
k=-range;
|
||||
j++;
|
||||
|
||||
}
|
||||
j=-range;
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return rifts;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public LinkData addLinkToDim(LinkData link)
|
||||
{
|
||||
if(this.linksInThisDim.containsKey(link.locZCoord))
|
||||
{
|
||||
this.dimY=this.linksInThisDim.get(link.locZCoord);
|
||||
|
||||
if(this.dimY.containsKey(link.locYCoord))
|
||||
{
|
||||
this.dimX=this.dimY.get(link.locYCoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dimX=new HashMap<Integer, LinkData>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dimX=new HashMap<Integer, LinkData>();
|
||||
this.dimY=new HashMap<Integer, HashMap<Integer, LinkData>>();
|
||||
}
|
||||
|
||||
this.dimX.put(link.locXCoord, link);
|
||||
this.dimY.put(link.locYCoord, dimX);
|
||||
this.linksInThisDim.put(link.locZCoord, dimY);
|
||||
|
||||
//System.out.println("added link to dim "+this.dimID);
|
||||
return link;
|
||||
|
||||
}
|
||||
|
||||
public LinkData addLinkToDim( int destinationDimID, int locationXCoord, int locationYCoord, int locationZCoord, int destinationXCoord, int destinationYCoord, int destinationZCoord, int linkOrientation)
|
||||
{
|
||||
LinkData linkData= new LinkData(this.dimID, destinationDimID, locationXCoord, locationYCoord, locationZCoord, destinationXCoord, destinationYCoord,destinationZCoord,this.isPocket,linkOrientation);
|
||||
|
||||
return this.addLinkToDim(linkData);
|
||||
}
|
||||
|
||||
public boolean isLimbo()
|
||||
{
|
||||
return (this.dimID == DDProperties.instance().LimboDimensionID);
|
||||
}
|
||||
|
||||
public void removeLinkAtCoords(LinkData link)
|
||||
{
|
||||
this.removeLinkAtCoords(link.locDimID, link.locXCoord, link.locYCoord, link.locZCoord);
|
||||
}
|
||||
|
||||
public void removeLinkAtCoords(int locationID, int locationXCoord, int locationYCoord, int locationZCoord)
|
||||
{
|
||||
if (this.linksInThisDim.containsKey(locationZCoord))
|
||||
{
|
||||
this.dimY=this.linksInThisDim.get(locationZCoord);
|
||||
|
||||
if(this.dimY.containsKey(locationYCoord))
|
||||
{
|
||||
this.dimX=this.dimY.get(locationYCoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dimX=new HashMap<Integer, LinkData>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dimX=new HashMap<Integer, LinkData>();
|
||||
this.dimY=new HashMap<Integer, HashMap<Integer, LinkData>>();
|
||||
}
|
||||
|
||||
this.dimX.remove(locationXCoord);
|
||||
this.dimY.put(locationYCoord, dimX);
|
||||
this.linksInThisDim.put(locationZCoord, dimY);
|
||||
}
|
||||
|
||||
public LinkData findLinkAtCoords(int locationXCoord, int locationYCoord, int locationZCoord)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this.linksInThisDim.containsKey(locationZCoord))
|
||||
{
|
||||
this.dimY=this.linksInThisDim.get(locationZCoord);
|
||||
|
||||
if(this.dimY.containsKey(locationYCoord))
|
||||
{
|
||||
this.dimX=this.dimY.get(locationYCoord);
|
||||
|
||||
if(this.dimX.containsKey(locationXCoord))
|
||||
{
|
||||
return this.dimX.get(locationXCoord);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception E)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<LinkData> getLinksInDim()
|
||||
{
|
||||
//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)
|
||||
{
|
||||
return links;
|
||||
}
|
||||
for (HashMap<Integer, HashMap<Integer, LinkData>> first : this.linksInThisDim.values())
|
||||
{
|
||||
for (HashMap<Integer, LinkData> second : first.values())
|
||||
{
|
||||
for (LinkData linkData : second.values())
|
||||
{
|
||||
links.add(linkData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return links;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
|
||||
@Deprecated
|
||||
public class DungeonGenerator implements Serializable
|
||||
{
|
||||
//This static field is hax so that I don't have to add an instance field to DungeonGenerator to support DungeonType.
|
||||
//Otherwise it would have to be serializable and all sorts of problems would arise.
|
||||
private static final HashMap<DungeonGenerator, DungeonType> dungeonTypes = new HashMap<DungeonGenerator, DungeonType>();
|
||||
|
||||
public int weight;
|
||||
public String schematicPath;
|
||||
public ArrayList<HashMap> sideRifts = new ArrayList<HashMap>();
|
||||
public LinkData exitLink;
|
||||
public boolean isOpen;
|
||||
|
||||
public int sideDoorsSoFar=0;
|
||||
public int exitDoorsSoFar=0;
|
||||
public int deadEndsSoFar=0;
|
||||
|
||||
public DungeonGenerator(int weight, String schematicPath, boolean isOpen, DungeonType dungeonType)
|
||||
{
|
||||
this.weight = weight;
|
||||
this.schematicPath = schematicPath;
|
||||
this.isOpen = isOpen;
|
||||
|
||||
dungeonTypes.put(this, dungeonType); //Hax...
|
||||
}
|
||||
|
||||
public DungeonType getDungeonType()
|
||||
{
|
||||
DungeonType type = dungeonTypes.get(this);
|
||||
if (type == null)
|
||||
{
|
||||
//Infer the dungeon's type from its file name
|
||||
//There is minimal risk of us applying this to untagged dungeons and this'll be phased out
|
||||
//when we get the new save format.
|
||||
try
|
||||
{
|
||||
File file = new File(schematicPath);
|
||||
String typeName = file.getName().split("_")[0];
|
||||
String packName = file.getParentFile().getName();
|
||||
DungeonPack pack = DungeonHelper.instance().getDungeonPack(packName);
|
||||
if (pack == null)
|
||||
{
|
||||
pack = DungeonHelper.instance().getDungeonPack("ruins");
|
||||
}
|
||||
type = pack.getType(typeName);
|
||||
}
|
||||
catch (Exception e) { }
|
||||
if (type == null)
|
||||
{
|
||||
type = DungeonType.UNKNOWN_TYPE;
|
||||
}
|
||||
dungeonTypes.put(this, type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return (schematicPath != null) ? schematicPath.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return equals((DungeonGenerator) other);
|
||||
}
|
||||
|
||||
public boolean equals(DungeonGenerator other)
|
||||
{
|
||||
return ((this.schematicPath != null && this.schematicPath.equals(other.schematicPath)) ||
|
||||
(this.schematicPath == other.schematicPath));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import paulscode.sound.SoundSystem;
|
||||
import net.minecraft.client.audio.SoundManager;
|
||||
import net.minecraft.client.audio.SoundPool;
|
||||
import net.minecraft.client.audio.SoundPoolEntry;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.sound.PlayBackgroundMusicEvent;
|
||||
import net.minecraftforge.client.event.sound.SoundLoadEvent;
|
||||
import net.minecraftforge.event.EventPriority;
|
||||
import net.minecraftforge.event.ForgeSubscribe;
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingFallEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
|
||||
import StevenDimDoors.mod_pocketDim.world.PocketProvider;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class EventHookContainer
|
||||
{
|
||||
private final DDProperties properties;
|
||||
|
||||
public EventHookContainer(DDProperties properties)
|
||||
{
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@ForgeSubscribe
|
||||
public void onSoundLoad(SoundLoadEvent event)
|
||||
{
|
||||
event.manager.addSound(mod_pocketDim.modid+":monk.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":crack.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":tearing.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":rift.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":riftStart.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":riftEnd.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":riftClose.ogg");
|
||||
event.manager.addSound(mod_pocketDim.modid+":riftDoor.ogg");
|
||||
event.manager.addMusic(mod_pocketDim.modid+":creepy.ogg");
|
||||
|
||||
}
|
||||
@SideOnly(Side.CLIENT)
|
||||
@ForgeSubscribe
|
||||
public void onSoundEffectResult(PlayBackgroundMusicEvent event)
|
||||
{
|
||||
if (FMLClientHandler.instance().getClient().thePlayer.worldObj.provider.dimensionId==mod_pocketDim.properties.LimboDimensionID);
|
||||
{
|
||||
this.playMusicForDim(FMLClientHandler.instance().getClient().thePlayer.worldObj);
|
||||
}
|
||||
}
|
||||
@ForgeSubscribe
|
||||
public void onWorldLoad(WorldEvent.Load event)
|
||||
{
|
||||
// We need to initialize PocketManager here because onServerAboutToStart fires before we can
|
||||
// use DimensionManager and onServerStarting fires after the game tries to generate terrain.
|
||||
// If a gateway tries to generate before PocketManager has initialized, we get a crash.
|
||||
if (!PocketManager.isLoaded())
|
||||
{
|
||||
PocketManager.load();
|
||||
}
|
||||
|
||||
if (PocketManager.isLoaded())
|
||||
{
|
||||
RiftRegenerator.regenerateRiftsInAllWorlds();
|
||||
}
|
||||
|
||||
this.playMusicForDim(event.world);
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
public void onPlayerFall(LivingFallEvent event)
|
||||
{
|
||||
event.setCanceled(event.entity.worldObj.provider.dimensionId == properties.LimboDimensionID);
|
||||
}
|
||||
@ForgeSubscribe(priority=EventPriority.HIGHEST)
|
||||
public boolean LivingDeathEvent(LivingDeathEvent event)
|
||||
{
|
||||
Entity entity = event.entity;
|
||||
|
||||
if (entity instanceof EntityPlayer && properties.LimboEnabled &&
|
||||
entity.worldObj.provider instanceof PocketProvider)
|
||||
{
|
||||
EntityPlayer player = (EntityPlayer) entity;
|
||||
if (!properties.LimboReturnsInventoryEnabled)
|
||||
{
|
||||
player.inventory.clearInventory(-1, -1);
|
||||
}
|
||||
|
||||
ChunkCoordinates coords = LimboProvider.getLimboSkySpawn(player.worldObj.rand);
|
||||
Point4D destination = new Point4D((int) (coords.posX+entity.posX), coords.posY, (int) (coords.posZ+entity.posZ ), mod_pocketDim.properties.LimboDimensionID);
|
||||
DDTeleporter.teleportEntity(player, destination, false);
|
||||
player.setHealth(player.getMaxHealth());
|
||||
event.setCanceled(true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
public void onWorldSave(WorldEvent.Save event)
|
||||
{
|
||||
if (event.world.provider.dimensionId == 0)
|
||||
{
|
||||
PocketManager.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void playMusicForDim(World world)
|
||||
{
|
||||
if(world.isRemote)
|
||||
{
|
||||
SoundManager sndManager = FMLClientHandler.instance().getClient().sndManager;
|
||||
|
||||
if(world.provider instanceof LimboProvider)
|
||||
{
|
||||
sndManager.sndSystem.stop("BgMusic");
|
||||
SoundPoolEntry soundPoolEntry = sndManager.soundPoolMusic.getRandomSoundFromSoundPool(mod_pocketDim.modid+":creepy");
|
||||
if(soundPoolEntry!=null)
|
||||
{
|
||||
sndManager.sndSystem.backgroundMusic("LimboMusic", soundPoolEntry.getSoundUrl(), soundPoolEntry.getSoundName(), false);
|
||||
sndManager.sndSystem.play("LimboMusic");
|
||||
}
|
||||
}
|
||||
else if(!(world.provider instanceof LimboProvider))
|
||||
{
|
||||
sndManager.sndSystem.stop("LimboMusic");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
||||
|
||||
public interface IChunkLoader
|
||||
{
|
||||
public void forceChunkLoading(Ticket ticket,int x, int z);
|
||||
}
|
||||
68
src/main/java/StevenDimDoors/mod_pocketDim/LinkData.java
Normal file
68
src/main/java/StevenDimDoors/mod_pocketDim/LinkData.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.Serializable;
|
||||
@Deprecated
|
||||
public class LinkData implements Serializable
|
||||
{
|
||||
|
||||
public int locXCoord;
|
||||
public int locYCoord;
|
||||
public int locZCoord;
|
||||
|
||||
public int destXCoord;
|
||||
public int destYCoord;
|
||||
public int destZCoord;
|
||||
public int numberofChildren;
|
||||
public boolean isLocPocket;
|
||||
public int linkOrientation;
|
||||
|
||||
public int destDimID;
|
||||
public int locDimID;
|
||||
|
||||
public boolean exists=false;
|
||||
public boolean hasGennedDoor=false;
|
||||
|
||||
static final long serialVersionUID = 45544342L;
|
||||
|
||||
|
||||
public LinkData()
|
||||
{
|
||||
this.exists=false;
|
||||
}
|
||||
|
||||
public LinkData(int exitLinkDimID, int exitX, int exitY, int exitZ)
|
||||
{
|
||||
this.destDimID=exitLinkDimID;
|
||||
this.destXCoord=exitX;
|
||||
this.destYCoord=exitY;
|
||||
this.destZCoord=exitZ;
|
||||
}
|
||||
|
||||
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.locXCoord=locationXCoord;
|
||||
this.locYCoord=locationYCoord;
|
||||
this.locZCoord=locationZCoord;
|
||||
|
||||
this.destXCoord=destinationXCoord;
|
||||
this.destYCoord=destinationYCoord;
|
||||
this.destZCoord=destinationZCoord;
|
||||
|
||||
this.destDimID=destinationDimID;
|
||||
this.locDimID=locationDimID;
|
||||
this.isLocPocket=isPocket;
|
||||
this.linkOrientation=orientation;
|
||||
}
|
||||
|
||||
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;
|
||||
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 ");
|
||||
return linkInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ObjectSaveInputStream extends ObjectInputStream {
|
||||
|
||||
// private static Logger logger = LoggerFactory.getLogger(ObjectSaveInputStream.class);
|
||||
|
||||
public ObjectSaveInputStream(InputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
|
||||
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
|
||||
Class<?> localClass; // the class in the local JVM that this descriptor represents.
|
||||
try {
|
||||
localClass = Class.forName(resultClassDescriptor.getName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
// logger.error("No local class for " + resultClassDescriptor.getName(), e);
|
||||
return resultClassDescriptor;
|
||||
}
|
||||
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
|
||||
if (localClassDescriptor != null) { // only if class implements serializable
|
||||
final long localSUID = localClassDescriptor.getSerialVersionUID();
|
||||
final long streamSUID = resultClassDescriptor.getSerialVersionUID();
|
||||
if (streamSUID != localSUID) { // check for serialVersionUID mismatch.
|
||||
final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");
|
||||
s.append("local serialVersionUID = ").append(localSUID);
|
||||
s.append(" stream serialVersionUID = ").append(streamSUID);
|
||||
Exception e = new InvalidClassException(s.toString());
|
||||
// logger.error("Potentially Fatal Deserialization Operation.", e);
|
||||
resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization
|
||||
}
|
||||
}
|
||||
return resultClassDescriptor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
public class PacketConstants
|
||||
{
|
||||
private PacketConstants() { }
|
||||
|
||||
public static final String CHANNEL_NAME = "DimDoorsPackets";
|
||||
|
||||
public static final byte CLIENT_JOIN_PACKET_ID = 1;
|
||||
public static final byte CREATE_DIM_PACKET_ID = 2;
|
||||
public static final byte DELETE_DIM_PACKET_ID = 3;
|
||||
public static final byte CREATE_LINK_PACKET_ID = 4;
|
||||
public static final byte DELETE_LINK_PACKET_ID = 5;
|
||||
public static final byte CLIENT_LOGIN_DIM_REGISTER = 6;
|
||||
|
||||
}
|
||||
126
src/main/java/StevenDimDoors/mod_pocketDim/Point3D.java
Normal file
126
src/main/java/StevenDimDoors/mod_pocketDim/Point3D.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class Point3D implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -9044026830605287190L;
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
|
||||
public Point3D(int x, int y,int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Point3D(Point4D point)
|
||||
{
|
||||
this.x = point.getX();
|
||||
this.y = point.getY();
|
||||
this.z = point.getZ();
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public int setX(int x)
|
||||
{
|
||||
return this.x = x;
|
||||
}
|
||||
|
||||
public int setY(int y)
|
||||
{
|
||||
return this.y = y;
|
||||
}
|
||||
|
||||
public int setZ(int z)
|
||||
{
|
||||
return this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point3D clone()
|
||||
{
|
||||
return new Point3D(x, y, z);
|
||||
}
|
||||
public int[] toIntArray()
|
||||
{
|
||||
return new int[]{x,y,z};
|
||||
}
|
||||
public boolean equals(Point3D other)
|
||||
{
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
return (this.x == other.x && this.y == other.y && this.z == other.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return equals((Point3D) other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
//Time for some witchcraft.
|
||||
//The code here is inspired by a discussion on Stack Overflow regarding hash codes for 3D.
|
||||
//Source: http://stackoverflow.com/questions/9858376/hashcode-for-3d-integer-coordinates-with-high-spatial-coherence
|
||||
|
||||
//I believe that most of the time, any points we might be hashing will be in close proximity to each other.
|
||||
//For instance, points that are within the same chunk or within a few neighboring chunks. Only the low-order
|
||||
//bits of each component would differ. I'll use 8 bits from Y and the 12 bits from X and Z. ~SenseiKiwi
|
||||
|
||||
int bit;
|
||||
int hash;
|
||||
int index;
|
||||
|
||||
hash = 0;
|
||||
index = 0;
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
hash |= ((y >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((x >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((z >> bit) & 1) << index;
|
||||
index++;
|
||||
}
|
||||
for (; bit < 12; bit++)
|
||||
{
|
||||
hash |= ((x >> bit) & 1) << index;
|
||||
index++;
|
||||
hash |= ((z >> bit) & 1) << index;
|
||||
index++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + x + ", " + y + ", " + z + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||
import net.minecraft.network.INetworkManager;
|
||||
import net.minecraft.network.packet.Packet250CustomPayload;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||
import cpw.mods.fml.common.network.IPacketHandler;
|
||||
import cpw.mods.fml.common.network.PacketDispatcher;
|
||||
import cpw.mods.fml.common.network.Player;
|
||||
|
||||
public class ServerPacketHandler implements IPacketHandler
|
||||
{
|
||||
public ServerPacketHandler()
|
||||
{
|
||||
PocketManager.registerDimWatcher(new DimWatcher());
|
||||
PocketManager.registerLinkWatcher(new LinkWatcher());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { }
|
||||
|
||||
private static class DimWatcher implements IUpdateWatcher<ClientDimData>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(ClientDimData message)
|
||||
{
|
||||
sendDimPacket(PacketConstants.CREATE_DIM_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(ClientDimData message)
|
||||
{
|
||||
sendDimPacket(PacketConstants.DELETE_DIM_PACKET_ID, message);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LinkWatcher implements IUpdateWatcher<ClientLinkData>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(ClientLinkData message)
|
||||
{
|
||||
sendLinkPacket(PacketConstants.CREATE_LINK_PACKET_ID, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(ClientLinkData message)
|
||||
{
|
||||
sendLinkPacket(PacketConstants.DELETE_LINK_PACKET_ID, message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendDimPacket(byte id, ClientDimData data)
|
||||
{
|
||||
try
|
||||
{
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(id);
|
||||
data.write(writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
packet.length = packet.data.length;
|
||||
PacketDispatcher.sendPacketToAllPlayers(packet);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
//This shouldn't happen...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendLinkPacket(byte id, ClientLinkData message)
|
||||
{
|
||||
try
|
||||
{
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(buffer);
|
||||
writer.writeByte(id);
|
||||
message.write(writer);
|
||||
writer.close();
|
||||
packet.channel = PacketConstants.CHANNEL_NAME;
|
||||
packet.data = buffer.toByteArray();
|
||||
packet.length = packet.data.length;
|
||||
PacketDispatcher.sendPacketToAllPlayers(packet);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
//This shouldn't happen...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
137
src/main/java/StevenDimDoors/mod_pocketDim/Spells.java
Normal file
137
src/main/java/StevenDimDoors/mod_pocketDim/Spells.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
|
||||
public class Spells
|
||||
{
|
||||
public EntityPlayer player;
|
||||
public int spellID;
|
||||
public int castingTime=0;
|
||||
|
||||
public int fireCastTime=40;
|
||||
public int smokeCastTime=5;
|
||||
public int plagueCastTime=5;
|
||||
|
||||
public Random rand= new Random();
|
||||
|
||||
public int fireSpell=1;
|
||||
public int smokeVanish=2;
|
||||
public int enderPush=3;
|
||||
public int flood=4;
|
||||
public int nightVision=5;
|
||||
public int heal = 6;
|
||||
public int plague = 7;
|
||||
public int butcher = 8;
|
||||
|
||||
|
||||
public Spells(EntityPlayer player, int spellID)
|
||||
{
|
||||
this.spellID=spellID;
|
||||
this.player=player;
|
||||
}
|
||||
|
||||
public boolean cast()
|
||||
{
|
||||
this.castingTime++;
|
||||
|
||||
if(this.spellID==this.fireSpell)
|
||||
{
|
||||
return this.castFire();
|
||||
|
||||
}
|
||||
|
||||
if(this.spellID==this.smokeVanish)
|
||||
{
|
||||
return this.castSmoke();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean castSmoke()
|
||||
{
|
||||
|
||||
if(!this.player.isPotionActive(Potion.invisibility))
|
||||
{
|
||||
this.player.addPotionEffect(new PotionEffect(Potion.invisibility.id, 2 * 200, 200));
|
||||
}
|
||||
|
||||
if(this.castingTime<this.smokeCastTime)
|
||||
{
|
||||
for(int i = 0; i<16;i++)
|
||||
{
|
||||
this.player.worldObj.spawnParticle("largesmoke", this.player.posX+this.rand.nextDouble()-.5, this.player.posY+(this.rand.nextDouble()-.5)*2, this.player.posZ+this.rand.nextDouble()-.5,
|
||||
this.rand.nextGaussian()/50,this.rand.nextGaussian()/50,this.rand.nextGaussian()/50);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
|
||||
}
|
||||
|
||||
public boolean castFire()
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(this.castingTime<this.fireCastTime)
|
||||
{
|
||||
for(int i = 0; i<50;i++)
|
||||
{
|
||||
this.player.worldObj.spawnParticle("flame", this.player.posX+this.rand.nextDouble()-.5, this.player.posY+this.rand.nextDouble()-.5, this.player.posZ+this.rand.nextDouble()-.5,
|
||||
(this.rand.nextDouble()-.5)/3, (this.rand.nextDouble()-.5)/3, (this.rand.nextDouble()-.5/3));
|
||||
|
||||
this.player.worldObj.spawnParticle("flame", this.player.posX+this.rand.nextDouble()-.5, this.player.posY+this.rand.nextDouble()-.5, this.player.posZ+this.rand.nextDouble()-.5,
|
||||
(this.rand.nextDouble()-.5), (this.rand.nextDouble()-.45)/2, (this.rand.nextDouble()-.5));
|
||||
this.player.worldObj.spawnParticle("flame", this.player.posX+this.rand.nextDouble()-.5, this.player.posY+this.rand.nextDouble()-.5, this.player.posZ+this.rand.nextDouble()-.5,
|
||||
(this.rand.nextDouble()-.5)/10, (this.rand.nextDouble()-.45)/20, (this.rand.nextDouble()-.5)/10);
|
||||
this.player.worldObj.spawnParticle("flame", this.player.posX+this.rand.nextDouble()-.5, this.player.posY+this.rand.nextDouble()-.5, this.player.posZ+this.rand.nextDouble()-.5,
|
||||
(this.rand.nextDouble()-.5)*2, (this.rand.nextDouble()-.45), (this.rand.nextDouble()-.5)*2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
List<Entity> list = player.worldObj.getEntitiesWithinAABBExcludingEntity(player,AxisAlignedBB.getBoundingBox( player.posX-7, player.posY-3, player.posZ-7, player.posX+7, player.posY+7, player.posZ+7));
|
||||
for(Entity entity : list)
|
||||
{
|
||||
entity.setFire(3);
|
||||
entity.attackEntityFrom(DamageSource.lava, 2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
public boolean castEnderPush()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean castFlood()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean castNightVision()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean castPlague()
|
||||
{
|
||||
|
||||
}
|
||||
**/
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.ITileEntityProvider;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Icon;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.BlockRotator;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class BaseDimDoor extends BlockDoor implements IDimDoor, ITileEntityProvider
|
||||
{
|
||||
protected final DDProperties properties;
|
||||
private Icon blockIconBottom;
|
||||
|
||||
public BaseDimDoor(int blockID, Material material, DDProperties properties)
|
||||
{
|
||||
super(blockID, material);
|
||||
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName()+"_top");
|
||||
this.blockIconBottom = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName()+"_bottom");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
|
||||
/**
|
||||
* From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
|
||||
*/
|
||||
public Icon getIcon(int par1, int par2)
|
||||
{
|
||||
return this.blockIcon;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
this.enterDimDoor(world, x, y, z, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
|
||||
boolean shouldOpen=true;
|
||||
|
||||
//System.out.println(String.valueOf(par1World.getBlockMetadata(par2, par3, par4)));
|
||||
if(player.inventory.getCurrentItem()!=null)
|
||||
{
|
||||
if(player.inventory.getCurrentItem().getItem() == mod_pocketDim.itemRiftBlade)
|
||||
{
|
||||
shouldOpen = false;
|
||||
if (!world.isRemote && world.getBlockId(x, y-1, z) == this.blockID)
|
||||
{
|
||||
int var12 = MathHelper.floor_double((player.rotationYaw+90) * 4.0F / 360.0F + 0.5D) & 3;
|
||||
|
||||
if (world.getBlockMetadata(x, y-1, z) == var12)
|
||||
{
|
||||
var12 = BlockRotator.transformMetadata(var12, 1, this.blockID);
|
||||
}
|
||||
world.setBlockMetadataWithNotify(x, y-1, z, var12, 2);
|
||||
}
|
||||
if (!world.isRemote && world.getBlockId(x, y+1, z) == this.blockID)
|
||||
{
|
||||
int var12 = MathHelper.floor_double((player.rotationYaw+90) * 4.0F / 360.0F + 0.5D) & 3;
|
||||
if(world.getBlockMetadata(x, y, z)==var12)
|
||||
{
|
||||
var12 = BlockRotator.transformMetadata(var12, 1, this.blockID);
|
||||
}
|
||||
world.setBlockMetadataWithNotify(x, y, z, var12, 2);
|
||||
}
|
||||
world.playAuxSFXAtEntity(player, 1001, x, y, z, 0);
|
||||
|
||||
if (!shouldOpen && !world.isRemote)
|
||||
{
|
||||
player.inventory.getCurrentItem().damageItem(5, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(shouldOpen)
|
||||
{
|
||||
int var10 = this.getFullMetadata(world, x, y, z);
|
||||
int var11 = var10 & 7;
|
||||
var11 ^= 4;
|
||||
|
||||
if ((var10 & 8) == 0)
|
||||
{
|
||||
world.setBlockMetadataWithNotify(x, y, z, var11,2);
|
||||
world.markBlockRangeForRenderUpdate(x, y, z, x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
world.setBlockMetadataWithNotify(x, y - 1, z, var11,2);
|
||||
world.markBlockRangeForRenderUpdate(x, y - 1, z, x, y, z);
|
||||
}
|
||||
|
||||
world.playAuxSFXAtEntity(player, 1003, x, y, z, 0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(World world, int x, int y, int z)
|
||||
{
|
||||
//FIXME: We need to set door generation flags on the tile entities. Ignoring that for now. ~SenseiKiwi
|
||||
|
||||
this.placeLink(world, x, y, z);
|
||||
world.setBlockTileEntity(x, y, z, this.createNewTileEntity(world));
|
||||
this.updateAttachedTile(world, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public Icon getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
|
||||
{
|
||||
if(par1IBlockAccess.getBlockId(par2, par3-1, par4) == this.blockID)
|
||||
{
|
||||
return this.blockIcon;
|
||||
}
|
||||
else
|
||||
{
|
||||
return blockIconBottom;
|
||||
}
|
||||
}
|
||||
|
||||
//Called to update the render information on the tile entity. Could probably implement a data watcher,
|
||||
//but this works fine and is more versatile I think.
|
||||
public BaseDimDoor updateAttachedTile(World world, int x, int y, int z)
|
||||
{
|
||||
TileEntity tile = world.getBlockTileEntity(x, y, z);
|
||||
if (tile instanceof TileEntityDimDoor)
|
||||
{
|
||||
TileEntityDimDoor dimTile = (TileEntityDimDoor) tile;
|
||||
dimTile.openOrClosed = PocketManager.getLink(x, y, z, world.provider.dimensionId) != null;
|
||||
dimTile.orientation = this.getFullMetadata(world, x, y, z) & 7;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two
|
||||
* adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
|
||||
*/
|
||||
@Override
|
||||
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
|
||||
{
|
||||
TileEntityDimDoor tile = (TileEntityDimDoor) par1World.getBlockTileEntity(par2, par3, par4);
|
||||
tile.openOrClosed = this.isDoorOpen( par1World, par2, par3, par4);
|
||||
tile.orientation = this.getFullMetadata(par1World, par2, par3, par4) & 7;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
|
||||
{
|
||||
this.setDoorRotation(this.getFullMetadata(par1IBlockAccess, par2, par3, par4));
|
||||
}
|
||||
|
||||
|
||||
public void setDoorRotation(int par1)
|
||||
{
|
||||
float var2 = 0.1875F;
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F);
|
||||
int var3 = par1 & 3;
|
||||
boolean var4 = (par1 & 4) != 0;
|
||||
boolean var5 = (par1 & 16) != 0;
|
||||
|
||||
if (var3 == 0)
|
||||
{
|
||||
if (var4)
|
||||
{
|
||||
if (!var5)
|
||||
{
|
||||
this.setBlockBounds(0.001F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.001F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
else if (var3 == 1)
|
||||
{
|
||||
if (var4)
|
||||
{
|
||||
if (!var5)
|
||||
{
|
||||
this.setBlockBounds(1.0F - var2, 0.0F, 0.001F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.001F, var2, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
|
||||
}
|
||||
}
|
||||
else if (var3 == 2)
|
||||
{
|
||||
if (var4)
|
||||
{
|
||||
if (!var5)
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, .99F, 1.0F, 1.0F);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.0F, .99F, 1.0F, var2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
else if (var3 == 3)
|
||||
{
|
||||
if (var4)
|
||||
{
|
||||
if (!var5)
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 0.99F);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 0.99F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
|
||||
* their own) Args: x, y, z, neighbor blockID
|
||||
*/
|
||||
@Override
|
||||
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
|
||||
{
|
||||
int var6 = par1World.getBlockMetadata(par2, par3, par4);
|
||||
|
||||
if ((var6 & 8) == 0)
|
||||
{
|
||||
boolean var7 = false;
|
||||
|
||||
if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID)
|
||||
{
|
||||
par1World.setBlock(par2, par3, par4, 0);
|
||||
var7 = true;
|
||||
}
|
||||
|
||||
/**
|
||||
if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4))
|
||||
{
|
||||
par1World.setBlockWithNotify(par2, par3, par4, 0);
|
||||
var7 = true;
|
||||
|
||||
if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID)
|
||||
{
|
||||
par1World.setBlockWithNotify(par2, par3 + 1, par4, 0);
|
||||
}
|
||||
}
|
||||
**/
|
||||
|
||||
if (var7)
|
||||
{
|
||||
if (!par1World.isRemote)
|
||||
{
|
||||
this.dropBlockAsItem(par1World, par2, par3, par4, properties.DimensionalDoorID, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
|
||||
|
||||
if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower()) && par5 != this.blockID)
|
||||
{
|
||||
this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID)
|
||||
{
|
||||
par1World.setBlock(par2, par3, par4, 0);
|
||||
}
|
||||
|
||||
if (par5 > 0 && par5 != this.blockID)
|
||||
{
|
||||
this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int idPicked(World par1World, int par2, int par3, int par4)
|
||||
{
|
||||
return this.getDrops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int idDropped(int par1, Random par2Random, int par3)
|
||||
{
|
||||
return (par1 & 8) != 0 ? 0 : (getDrops());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the block is attempted to be harvested
|
||||
*/
|
||||
@Override
|
||||
public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
|
||||
{
|
||||
if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0 && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID)
|
||||
{
|
||||
par1World.setBlock(par2, par3 - 1, par4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World world)
|
||||
{
|
||||
return new TileEntityDimDoor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDimDoor(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
// FX entities dont exist on the server
|
||||
if (world.isRemote)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that this is the top block of the door
|
||||
if (world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
int metadata = world.getBlockMetadata(x, y - 1, z);
|
||||
boolean canUse = isDoorOpen(metadata);
|
||||
if (canUse && entity instanceof EntityPlayer)
|
||||
{
|
||||
// Dont check for non-player entites
|
||||
canUse = isEntityFacingDoor(metadata, (EntityLivingBase) entity);
|
||||
}
|
||||
if (canUse)
|
||||
{
|
||||
// Teleport the entity through the link, if it exists
|
||||
DimLink link = PocketManager.getLink(x, y, z, world.provider.dimensionId);
|
||||
if (link != null)
|
||||
{
|
||||
DDTeleporter.traverseDimDoor(world, link, entity, this);
|
||||
}
|
||||
// Close the door only after the entity goes through
|
||||
// so players don't have it slam in their faces.
|
||||
this.onPoweredBlockChange(world, x, y, z, false);
|
||||
}
|
||||
}
|
||||
else if (world.getBlockId(x, y + 1, z) == this.blockID)
|
||||
{
|
||||
enterDimDoor(world, x, y + 1, z, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return this.blockID;
|
||||
}
|
||||
|
||||
protected static boolean isDoorOpen(int metadata)
|
||||
{
|
||||
return (metadata & 4) != 0;
|
||||
}
|
||||
|
||||
protected static boolean isEntityFacingDoor(int metadata, EntityLivingBase entity)
|
||||
{
|
||||
// Although any entity has the proper fields for this check,
|
||||
// we should only apply it to living entities since things
|
||||
// like Minecarts might come in backwards.
|
||||
int direction = MathHelper.floor_double((entity.rotationYaw + 90) * 4.0F / 360.0F + 0.5D) & 3;
|
||||
return ((metadata & 3) == direction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockContainer;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Icon;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockDimWall extends Block
|
||||
{
|
||||
private static final float SUPER_HIGH_HARDNESS = 10000000000000F;
|
||||
private static final float SUPER_EXPLOSION_RESISTANCE = 18000000F;
|
||||
private Icon[] blockIcon = new Icon[2];
|
||||
|
||||
public BlockDimWall(int blockID, int j, Material par2Material)
|
||||
{
|
||||
super(blockID, Material.ground);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBlockHardness(World world, int x, int y, int z)
|
||||
{
|
||||
if (world.getBlockMetadata(x, y, z) == 0)
|
||||
{
|
||||
return this.blockHardness;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SUPER_HIGH_HARDNESS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExplosionResistance(Entity entity, World world, int x, int y, int z, double explosionX, double explosionY, double explosionZ)
|
||||
{
|
||||
if (world.getBlockMetadata(x, y, z) == 0)
|
||||
{
|
||||
return super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SUPER_EXPLOSION_RESISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon[0] = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
this.blockIcon[1] = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName() + "Perm");
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public Icon getIcon(int par1, int par2)
|
||||
{
|
||||
return (par2 != 1) ? blockIcon[0] : blockIcon[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damageDropped(int metadata)
|
||||
{
|
||||
//Return 0 to avoid dropping Ancient Fabric even if the player somehow manages to break it
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getSubBlocks(int unknown, CreativeTabs tab, List subItems)
|
||||
{
|
||||
for (int ix = 0; ix < 2; ix++)
|
||||
{
|
||||
subItems.add(new ItemStack(this, 1, ix));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {}
|
||||
|
||||
@Override
|
||||
protected boolean canSilkHarvest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int quantityDropped(Random par1Random)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* replaces the block clicked with the held block, instead of placing the block on top of it. Shift click to disable.
|
||||
*/
|
||||
@Override
|
||||
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int par6, float par7, float par8, float par9)
|
||||
{
|
||||
//Check if the metadata value is 0 -- we don't want the user to replace Ancient Fabric
|
||||
if (entityPlayer.getCurrentEquippedItem() != null && world.getBlockMetadata(x, y, z) == 0)
|
||||
{
|
||||
Item playerEquip = entityPlayer.getCurrentEquippedItem().getItem();
|
||||
|
||||
if (playerEquip instanceof ItemBlock)
|
||||
{
|
||||
// SenseiKiwi: Using getBlockID() rather than the raw itemID is critical.
|
||||
// Some mods may override that function and use item IDs outside the range
|
||||
// of the block list.
|
||||
|
||||
int blockID = ((ItemBlock) playerEquip).getBlockID();
|
||||
Block block = Block.blocksList[blockID];
|
||||
if (!Block.isNormalCube(blockID) || block instanceof BlockContainer || blockID == this.blockID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!world.isRemote)
|
||||
{
|
||||
if (!entityPlayer.capabilities.isCreativeMode)
|
||||
{
|
||||
entityPlayer.getCurrentEquippedItem().stackSize--;
|
||||
}
|
||||
world.setBlock(x, y, z, entityPlayer.getCurrentEquippedItem().itemID, entityPlayer.getCurrentEquippedItem().getItemDamage(), 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class BlockDimWallPerm extends Block
|
||||
{
|
||||
private static final Random random = new Random();
|
||||
private static DDProperties properties = null;
|
||||
|
||||
public BlockDimWallPerm(int i, int j, Material par2Material)
|
||||
{
|
||||
super(i, Material.ground);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int quantityDropped(Random par1Random)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {}
|
||||
|
||||
/**
|
||||
* Only matters if the player is in limbo, acts to teleport the player from limbo back to dim 0
|
||||
*/
|
||||
@Override
|
||||
public void onEntityWalking(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
if (!world.isRemote && world.provider.dimensionId == properties.LimboDimensionID)
|
||||
{
|
||||
World overworld = DimensionManager.getWorld(0);
|
||||
if (overworld != null && entity instanceof EntityPlayerMP)
|
||||
{
|
||||
EntityPlayer player = (EntityPlayer) entity;
|
||||
player.fallDistance = 0;
|
||||
int rangeLimit = properties.LimboReturnRange / 2;
|
||||
int destinationX = x + MathHelper.getRandomIntegerInRange(random, -rangeLimit, rangeLimit);
|
||||
int destinationZ = z + MathHelper.getRandomIntegerInRange(random, -rangeLimit, rangeLimit);
|
||||
|
||||
//make sure I am in the middle of a chunk, and not on a boundary, so it doesn't load the chunk next to me
|
||||
destinationX = destinationX + (destinationX >> 4);
|
||||
destinationZ = destinationZ + (destinationZ >> 4);
|
||||
|
||||
int destinationY = yCoordHelper.getFirstUncovered(overworld, destinationX, 63, destinationZ, true);
|
||||
|
||||
//FIXME: Shouldn't we make the player's destination safe BEFORE teleporting him?!
|
||||
//player.setPositionAndUpdate( x, y, z );
|
||||
Point4D destination = new Point4D(destinationX, destinationY, destinationZ, 0);
|
||||
DDTeleporter.teleportEntity(player, destination, false);
|
||||
|
||||
//player.setPositionAndUpdate( x, y, z );
|
||||
|
||||
// Make absolutely sure the player doesn't spawn inside blocks, though to be honest this shouldn't ever have to be a problem...
|
||||
overworld.setBlockToAir(destinationX, destinationY, destinationZ);
|
||||
overworld.setBlockToAir(destinationX, destinationY + 1, destinationZ);
|
||||
|
||||
for (int xc = -3; xc < 4; xc++)
|
||||
{
|
||||
for (int zc = -3; zc < 4; zc++)
|
||||
{
|
||||
if (Math.abs(xc) + Math.abs(zc) < random.nextInt(3) + 2 ||
|
||||
Math.abs(xc) + Math.abs(zc) < random.nextInt(3) + 3)
|
||||
{
|
||||
overworld.setBlock(destinationX + xc, destinationY - 1, destinationZ + zc, properties.LimboBlockID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: Why do we do this repeatedly? We also set the fall distance at the start...
|
||||
player.setPositionAndUpdate( destinationX, destinationY, destinationZ );
|
||||
player.fallDistance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.Icon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public class BlockDoorGold extends BlockDoor
|
||||
{
|
||||
|
||||
private Icon blockIconBottom;
|
||||
@SuppressWarnings("unused") // ??
|
||||
private DDProperties properties;
|
||||
|
||||
public BlockDoorGold(int par1, Material par2Material,DDProperties properties)
|
||||
{
|
||||
super(par1, par2Material);
|
||||
this.properties=properties;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName()+"_top");
|
||||
this.blockIconBottom = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName()+"_bottom");
|
||||
}
|
||||
|
||||
public int idDropped(int par1, Random par2Random, int par3)
|
||||
{
|
||||
return mod_pocketDim.itemGoldDoor.itemID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(int par1, int par2)
|
||||
{
|
||||
return this.blockIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public Icon getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
|
||||
{
|
||||
if(par1IBlockAccess.getBlockId(par2, par3-1, par4) == this.blockID)
|
||||
{
|
||||
return this.blockIcon;
|
||||
}
|
||||
else
|
||||
{
|
||||
return blockIconBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoorGold;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class BlockGoldDimDoor extends BaseDimDoor
|
||||
{
|
||||
|
||||
public BlockGoldDimDoor(int blockID, Material material,
|
||||
DDProperties properties) {
|
||||
super(blockID, material, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null)
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkTypes.POCKET,world.getBlockMetadata(x, y - 1, z));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return mod_pocketDim.itemGoldDoor.itemID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World world)
|
||||
{
|
||||
return new TileEntityDimDoorGold();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.util.Icon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.LimboDecay;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockLimbo extends Block
|
||||
{
|
||||
private final int limboDimensionID;
|
||||
private final LimboDecay decay;
|
||||
|
||||
public BlockLimbo(int i, int j, Material par2Material, int limboDimensionID, LimboDecay decay)
|
||||
{
|
||||
super(i, Material.ground);
|
||||
this.limboDimensionID = limboDimensionID;
|
||||
this.decay = decay;
|
||||
this.setTickRandomly(true);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public Icon getBlockTexture(IBlockAccess blockAccess, int x, int y, int z, int side)
|
||||
{
|
||||
return this.getIcon(side, blockAccess.getBlockMetadata(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister iconRegister)
|
||||
{
|
||||
this.blockIcon = iconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(int par1, int par2)
|
||||
{
|
||||
return this.blockIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the block is in Limbo, attempt to decay surrounding blocks upon receiving a random update tick.
|
||||
*/
|
||||
@Override
|
||||
public void updateTick(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
//Make sure this block is in Limbo
|
||||
if (world.provider.dimensionId == limboDimensionID)
|
||||
{
|
||||
decay.applySpreadDecay(world, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
370
src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java
Normal file
370
src/main/java/StevenDimDoors/mod_pocketDim/blocks/BlockRift.java
Normal file
@@ -0,0 +1,370 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockContainer;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||
import StevenDimDoors.mod_pocketDimClient.ClosingRiftFX;
|
||||
import StevenDimDoors.mod_pocketDimClient.GoggleRiftFX;
|
||||
import StevenDimDoors.mod_pocketDimClient.RiftFX;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockRift extends BlockContainer
|
||||
{
|
||||
private static final float MIN_IMMUNE_HARDNESS = 200.0F;
|
||||
private static final int BLOCK_DESTRUCTION_RANGE = 4;
|
||||
private static final int BLOCK_DESTRUCTION_VOLUME = (int) Math.pow(2 * BLOCK_DESTRUCTION_RANGE + 1, 3);
|
||||
private static final int MAX_BLOCK_SEARCH_CHANCE = 100;
|
||||
private static final int BLOCK_SEARCH_CHANCE = 50;
|
||||
private static final int MAX_BLOCK_DESTRUCTION_CHANCE = 100;
|
||||
private static final int BLOCK_DESTRUCTION_CHANCE = 50;
|
||||
|
||||
private final DDProperties properties;
|
||||
private final ArrayList<Integer> blocksImmuneToRift;
|
||||
|
||||
public BlockRift(int i, int j, Material par2Material, DDProperties properties)
|
||||
{
|
||||
super(i, par2Material);
|
||||
this.setTickRandomly(true);
|
||||
this.properties = properties;
|
||||
this.blocksImmuneToRift = new ArrayList<Integer>();
|
||||
this.blocksImmuneToRift.add(properties.FabricBlockID);
|
||||
this.blocksImmuneToRift.add(properties.PermaFabricBlockID);
|
||||
this.blocksImmuneToRift.add(properties.DimensionalDoorID);
|
||||
this.blocksImmuneToRift.add(properties.WarpDoorID);
|
||||
this.blocksImmuneToRift.add(properties.TransTrapdoorID);
|
||||
this.blocksImmuneToRift.add(properties.UnstableDoorID);
|
||||
this.blocksImmuneToRift.add(properties.RiftBlockID);
|
||||
this.blocksImmuneToRift.add(properties.TransientDoorID);
|
||||
this.blocksImmuneToRift.add(properties.GoldDimDoorID);
|
||||
this.blocksImmuneToRift.add(properties.GoldDoorID);
|
||||
|
||||
this.blocksImmuneToRift.add(Block.blockIron.blockID);
|
||||
this.blocksImmuneToRift.add(Block.blockDiamond.blockID);
|
||||
this.blocksImmuneToRift.add(Block.blockEmerald.blockID);
|
||||
this.blocksImmuneToRift.add(Block.blockGold.blockID);
|
||||
this.blocksImmuneToRift.add(Block.blockLapis.blockID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
//sends a packet informing the client that there is a link present so it renders properly. (when placed)
|
||||
@Override
|
||||
public void onBlockAdded(World par1World, int par2, int par3, int par4)
|
||||
{
|
||||
try
|
||||
{
|
||||
// PacketHandler.onLinkCreatedPacket(dimHelper.instance.getLinkDataFromCoords(par2, par3, par4, par1World));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
// this.updateTick(par1World, par2, par3, par4, new Random());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollidable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {}
|
||||
|
||||
@Override
|
||||
public boolean isOpaqueCube()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
|
||||
*/
|
||||
@Override
|
||||
public boolean canCollideCheck(int par1, boolean par2)
|
||||
{
|
||||
|
||||
return par2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Returns true if the given side of this block type should be rendered (if it's solid or not), if the
|
||||
* adjacent block is at the given coordinates. Args: blockAccess, x, y, z, side
|
||||
*/
|
||||
@Override
|
||||
public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//this doesnt do anything yet.
|
||||
@Override
|
||||
public int getRenderType()
|
||||
{
|
||||
if(mod_pocketDim.isPlayerWearingGoogles)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
|
||||
* coordinates. Args: blockAccess, x, y, z, side
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
|
||||
* cleared to be reused)
|
||||
*/
|
||||
@Override
|
||||
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//function that regulates how many blocks it eats/ how fast it eats them.
|
||||
@Override
|
||||
public void updateTick(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
if (properties.RiftGriefingEnabled && !world.isRemote &&
|
||||
PocketManager.getLink(x, y, z, world.provider.dimensionId) != null)
|
||||
{
|
||||
//Randomly decide whether to search for blocks to destroy. This reduces the frequency of search operations,
|
||||
//moderates performance impact, and controls the apparent speed of block destruction.
|
||||
if (random.nextInt(MAX_BLOCK_SEARCH_CHANCE) < BLOCK_SEARCH_CHANCE &&
|
||||
((TileEntityRift) world.getBlockTileEntity(x, y, z)).isNearRift )
|
||||
{
|
||||
destroyNearbyBlocks(world, x, y, z, random);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyNearbyBlocks(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
HashMap<Point3D, Integer> pointDistances = new HashMap<Point3D, Integer>(BLOCK_DESTRUCTION_VOLUME);
|
||||
Queue<Point3D> points = new LinkedList<Point3D>();
|
||||
|
||||
//Perform a breadth-first search outwards from the point at which the rift is located. Record the distances
|
||||
//of the points we visit to stop the search at its maximum range.
|
||||
pointDistances.put(new Point3D(x, y, z), 0);
|
||||
addAdjacentBlocks(x, y, z, 0, pointDistances, points);
|
||||
while (!points.isEmpty())
|
||||
{
|
||||
Point3D current = points.remove();
|
||||
int distance = pointDistances.get(current);
|
||||
|
||||
//If the current block is air, continue searching. Otherwise, try destroying the block.
|
||||
if (world.isAirBlock(current.getX(), current.getY(), current.getZ()))
|
||||
{
|
||||
//Make sure we stay within the search range
|
||||
if (distance < BLOCK_DESTRUCTION_RANGE)
|
||||
{
|
||||
addAdjacentBlocks(current.getX(), current.getY(), current.getZ(), distance, pointDistances, points);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Check if the current block is immune to destruction by rifts. If not, randomly decide whether to destroy it.
|
||||
//The randomness makes it so the destroyed area appears "noisy" if the rift is exposed to a large surface.
|
||||
if (!isBlockImmune(world, current.getX(), current.getY(), current.getZ()) &&
|
||||
random.nextInt(MAX_BLOCK_DESTRUCTION_CHANCE) < BLOCK_DESTRUCTION_CHANCE)
|
||||
{
|
||||
world.setBlockToAir(current.getX(), current.getY(), current.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAdjacentBlocks(int x, int y, int z, int distance, HashMap<Point3D, Integer> pointDistances, Queue<Point3D> points)
|
||||
{
|
||||
Point3D[] neighbors = new Point3D[] {
|
||||
new Point3D(x - 1, y, z),
|
||||
new Point3D(x + 1, y, z),
|
||||
new Point3D(x, y - 1, z),
|
||||
new Point3D(x, y + 1, z),
|
||||
new Point3D(x, y, z - 1),
|
||||
new Point3D(x, y, z + 1)
|
||||
};
|
||||
for (int index = 0; index < neighbors.length; index++)
|
||||
{
|
||||
if (!pointDistances.containsKey(neighbors[index]))
|
||||
{
|
||||
pointDistances.put(neighbors[index], distance + 1);
|
||||
points.add(neighbors[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* regulates the render effect, especially when multiple rifts start to link up. Has 3 main parts- Grows toward and away from nearest rft, bends toward it, and a randomization function
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
|
||||
public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random rand)
|
||||
{
|
||||
|
||||
int count;
|
||||
//growth in the direction towards the nearby rift
|
||||
float xGrowth=0;
|
||||
float yGrowth=0;
|
||||
float zGrowth=0;
|
||||
//growth away from the nearby rift
|
||||
float xGrowthn=0;
|
||||
float yGrowthn=0;
|
||||
float zGrowthn=0;
|
||||
//how far the particles are away from original rift. Used to decrease noise the farther they are away.
|
||||
float xChange = 0;
|
||||
float yChange = 0;
|
||||
float zChange = 0;
|
||||
|
||||
TileEntityRift tile = (TileEntityRift)par1World.getBlockTileEntity(par2, par3, par4);
|
||||
|
||||
float Xoffset=0;
|
||||
float Yoffset=0;
|
||||
float Zoffset=0;
|
||||
for (count = 0; count < 12 && tile!=null; ++count)
|
||||
{
|
||||
//TODO change to a switch statement for clarity
|
||||
if(tile.xOffset>0)
|
||||
{
|
||||
if(rand.nextInt(tile.xOffset)==0)
|
||||
{
|
||||
xGrowth =xGrowth+.15F*tile.xOffset;
|
||||
|
||||
}
|
||||
}
|
||||
else if(tile.xOffset<0)
|
||||
{
|
||||
if(rand.nextInt(-tile.xOffset)==0)
|
||||
{
|
||||
xGrowthn =xGrowthn-.15F*-tile.xOffset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.yOffset>0)
|
||||
{
|
||||
if(rand.nextInt(tile.yOffset)==0)
|
||||
{
|
||||
yGrowth =yGrowth+.15F*tile.yOffset;
|
||||
|
||||
}
|
||||
}
|
||||
else if(tile.yOffset<0)
|
||||
{
|
||||
if(rand.nextInt(-tile.yOffset)==0)
|
||||
{
|
||||
yGrowthn =yGrowthn-.15F*-tile.yOffset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.zOffset>0)
|
||||
{
|
||||
if(rand.nextInt(tile.zOffset)==0)
|
||||
{
|
||||
zGrowth =zGrowth+.15F*tile.zOffset;
|
||||
|
||||
}
|
||||
}
|
||||
else if(tile.zOffset<0)
|
||||
{
|
||||
if(rand.nextInt(-tile.zOffset)==0)
|
||||
{
|
||||
zGrowthn =zGrowthn-.15F*-tile.zOffset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xChange=(float) ((xGrowth+xGrowthn)+rand.nextGaussian()*.05F);
|
||||
yChange=(float) ((yGrowth+yGrowthn)+rand.nextGaussian()*.05F);
|
||||
zChange=(float) ((zGrowth+zGrowthn)+rand.nextGaussian()*.05F);
|
||||
|
||||
Xoffset= ((0.25F/(1+Math.abs(xChange))));
|
||||
|
||||
Yoffset= ((0.25F/(1+Math.abs(yChange))));
|
||||
Zoffset= ((0.25F/(1+Math.abs(zChange))));
|
||||
|
||||
|
||||
|
||||
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new RiftFX(par1World,par2+.5+xChange+Xoffset*rand.nextGaussian(), par3+.5+yChange+Yoffset*rand.nextGaussian() , par4+.5+zChange+Zoffset*rand.nextGaussian(), rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new RiftFX(par1World,par2+.5-xChange-Xoffset*rand.nextGaussian(), par3+.5-yChange-Yoffset*rand.nextGaussian() , par4+.5-zChange-Zoffset*rand.nextGaussian(), rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, rand.nextGaussian() * 0.001D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||
|
||||
|
||||
if(rand.nextBoolean())
|
||||
{
|
||||
//renders an extra little blob on top of the actual rift location so its easier to find. Eventually will only render if the player has the goggles.
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new GoggleRiftFX(par1World,par2+.5, par3+.5, par4+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||
}
|
||||
if(tile.shouldClose)
|
||||
{
|
||||
//renders an opposite color effect if it is being closed by the rift remover
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new ClosingRiftFX(par1World,par2+.5, par3+.5, par4+.5, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, FMLClientHandler.instance().getClient().effectRenderer));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBlockImmune(World world, int x, int y, int z)
|
||||
{
|
||||
Block block = Block.blocksList[world.getBlockId(x, y, z)];
|
||||
if (block != null)
|
||||
{
|
||||
float hardness = block.getBlockHardness(world, x, y, z);
|
||||
return (hardness < 0 || hardness >= MIN_IMMUNE_HARDNESS || blocksImmuneToRift.contains(block.blockID));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int idPicked(World par1World, int par2, int par3, int par4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int idDropped(int par1, Random par2Random, int par3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World var1)
|
||||
{
|
||||
return new TileEntityRift();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DimensionalDoor extends BaseDimDoor
|
||||
{
|
||||
|
||||
public DimensionalDoor(int blockID, Material material, DDProperties properties)
|
||||
{
|
||||
super(blockID, material, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null)
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkTypes.POCKET,world.getBlockMetadata(x, y - 1, z));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return Item.doorIron.itemID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IDimDoor
|
||||
{
|
||||
public void enterDimDoor(World world, int x, int y, int z, Entity entity);
|
||||
|
||||
public void placeLink(World world, int x, int y, int z);
|
||||
|
||||
public int getDrops();
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockTrapDoor;
|
||||
import net.minecraft.block.ITileEntityProvider;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class TransTrapdoor extends BlockTrapDoor implements IDimDoor, ITileEntityProvider
|
||||
{
|
||||
|
||||
public TransTrapdoor(int blockID, Material material)
|
||||
{
|
||||
super(blockID, material);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.blockIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
//Teleports the player to the exit link of that dimension, assuming it is a pocket
|
||||
@Override
|
||||
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
enterDimDoor(world, x, y, z, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDimDoor(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
if (!world.isRemote && isTrapdoorOpen(world.getBlockMetadata(x, y, z)))
|
||||
{
|
||||
this.onPoweredBlockChange(world, x, y, z, false);
|
||||
|
||||
DimLink link = PocketManager.getLink(x, y, z, world);
|
||||
if (link != null)
|
||||
{
|
||||
DDTeleporter.traverseDimDoor(world, link, entity,this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(World world, int x, int y, int z)
|
||||
{
|
||||
this.placeLink(world, x, y, z);
|
||||
world.setBlockTileEntity(x, y, z, this.createNewTileEntity(world));
|
||||
this.updateAttachedTile(world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTick(World world, int x, int y, int z, Random random)
|
||||
{
|
||||
TileEntityTransTrapdoor tile = (TileEntityTransTrapdoor) world.getBlockTileEntity(x, y, z);
|
||||
tile.hasRift = PocketManager.getLink(x, y, z, world) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World world)
|
||||
{
|
||||
return new TileEntityTransTrapdoor();
|
||||
}
|
||||
|
||||
public void updateAttachedTile(World world, int x, int y, int z)
|
||||
{
|
||||
TileEntity tile = world.getBlockTileEntity(x, y, z);
|
||||
if (tile instanceof TileEntityTransTrapdoor)
|
||||
{
|
||||
TileEntityTransTrapdoor trapdoorTile = (TileEntityTransTrapdoor) tile;
|
||||
trapdoorTile.hasRift = (PocketManager.getLink(x, y, z, world) != null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null && dimension.isPocketDimension())
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkTypes.UNSAFE_EXIT,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int idDropped(int metadata, Random random, int fortuneLevel)
|
||||
{
|
||||
return getDrops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return Block.trapdoor.blockID;
|
||||
}
|
||||
|
||||
public static boolean isTrapdoorSetLow(int metadata)
|
||||
{
|
||||
return (metadata & 8) == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.particle.EntityFX;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class TransientDoor extends BaseDimDoor
|
||||
{
|
||||
public TransientDoor(int blockID, Material material, DDProperties properties)
|
||||
{
|
||||
super(blockID, material, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDimDoor(World world, int x, int y, int z, Entity entity)
|
||||
{
|
||||
// We need to ignore particle entities
|
||||
if (world.isRemote)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that this is the top block of the door
|
||||
if (world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
boolean canUse = true;
|
||||
int metadata = world.getBlockMetadata(x, y - 1, z);
|
||||
if (canUse && entity instanceof EntityPlayer)
|
||||
{
|
||||
// Don't check for non-living entities since it might not work right
|
||||
canUse = BaseDimDoor.isEntityFacingDoor(metadata, (EntityLivingBase) entity);
|
||||
}
|
||||
if (canUse)
|
||||
{
|
||||
// Teleport the entity through the link, if it exists
|
||||
DimLink link = PocketManager.getLink(x, y, z, world.provider.dimensionId);
|
||||
if (link != null)
|
||||
{
|
||||
DDTeleporter.traverseDimDoor(world, link, entity, this);
|
||||
// Turn the door into a rift AFTER teleporting the player.
|
||||
// The door's orientation may be necessary for the teleport.
|
||||
world.setBlock(x, y, z, properties.RiftBlockID);
|
||||
world.setBlockToAir(x, y - 1, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (world.getBlockId(x, y + 1, z) == this.blockID)
|
||||
{
|
||||
enterDimDoor(world, x, y + 1, z, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null && dimension.isPocketDimension())
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkTypes.SAFE_EXIT,world.getBlockMetadata(x, y - 1, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollidable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRenderType()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
public class UnstableDoor extends BaseDimDoor
|
||||
{
|
||||
public UnstableDoor(int blockID, Material material, DDProperties properties)
|
||||
{
|
||||
super(blockID, material, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
dimension.createLink(x, y, z, LinkTypes.RANDOM,world.getBlockMetadata(x, y - 1, z));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return Item.doorIron.itemID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package StevenDimDoors.mod_pocketDim.blocks;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class WarpDoor extends BaseDimDoor
|
||||
{
|
||||
public WarpDoor(int blockID, Material material, DDProperties properties)
|
||||
{
|
||||
super(blockID, material, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeLink(World world, int x, int y, int z)
|
||||
{
|
||||
if (!world.isRemote && world.getBlockId(x, y - 1, z) == this.blockID)
|
||||
{
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (link == null && dimension.isPocketDimension())
|
||||
{
|
||||
dimension.createLink(x, y, z, LinkTypes.SAFE_EXIT,world.getBlockMetadata(x, y - 1, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDrops()
|
||||
{
|
||||
return Item.doorWood.itemID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.world.PocketBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.MathHelper;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CommandCreateDungeonRift extends DDCommandBase
|
||||
{
|
||||
private static CommandCreateDungeonRift instance = null;
|
||||
|
||||
private CommandCreateDungeonRift()
|
||||
{
|
||||
super("dd-rift", "<dungeon name | 'list' | 'random'>");
|
||||
}
|
||||
|
||||
public static CommandCreateDungeonRift instance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommandCreateDungeonRift();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-rift <dungeon name>\r\n" +
|
||||
" /dd-rift list\r\n" +
|
||||
" /dd-rift random";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
NewDimData dimension;
|
||||
DungeonHelper dungeonHelper = DungeonHelper.instance();
|
||||
|
||||
if (sender.worldObj.isRemote)
|
||||
{
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
if (command.length == 0)
|
||||
{
|
||||
return DDCommandResult.TOO_FEW_ARGUMENTS;
|
||||
}
|
||||
if (command.length > 1)
|
||||
{
|
||||
return DDCommandResult.TOO_MANY_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (command[0].equals("list"))
|
||||
{
|
||||
Collection<String> dungeonNames = dungeonHelper.getDungeonNames();
|
||||
for (String name : dungeonNames)
|
||||
{
|
||||
sendChat(sender,(name));
|
||||
}
|
||||
sendChat(sender,(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
DimLink link;
|
||||
DungeonData result;
|
||||
int x = MathHelper.floor_double(sender.posX);
|
||||
int y = MathHelper.floor_double(sender.posY);
|
||||
int z = MathHelper.floor_double (sender.posZ);
|
||||
int orientation = MathHelper.floor_double((sender.rotationYaw + 180.0F) * 4.0F / 360.0F - 0.5D) & 3;
|
||||
|
||||
if (command[0].equals("random"))
|
||||
{
|
||||
|
||||
dimension = PocketManager.getDimensionData(sender.worldObj);
|
||||
link = dimension.createLink(x, y + 1, z, LinkTypes.DUNGEON,orientation);
|
||||
sender.worldObj.setBlock(x, y + 1, z,mod_pocketDim.blockRift.blockID,0,3);
|
||||
|
||||
sendChat(sender,("Created a rift to a random dungeon."));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = findDungeonByPartialName(command[0], dungeonHelper.getRegisteredDungeons());
|
||||
if (result == null)
|
||||
{
|
||||
result = findDungeonByPartialName(command[0], dungeonHelper.getUntaggedDungeons());
|
||||
}
|
||||
//Check if we found any matches
|
||||
if (result != null)
|
||||
{
|
||||
//Create a rift to our selected dungeon and notify the player
|
||||
//TODO currently crashes, need to create the dimension first
|
||||
dimension = PocketManager.getDimensionData(sender.worldObj);
|
||||
link = dimension.createLink(x, y + 1, z, LinkTypes.DUNGEON,orientation);
|
||||
PocketBuilder.generateSelectedDungeonPocket(link, mod_pocketDim.properties, result);
|
||||
|
||||
sender.worldObj.setBlock(x, y + 1, z,mod_pocketDim.blockRift.blockID,0,3);
|
||||
sendChat(sender,("Created a rift to \"" + result.schematicName() + "\" dungeon (Dimension ID = " + link.destination().getDimension() + ")."));
|
||||
}
|
||||
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 DungeonData findDungeonByPartialName(String query, Collection<DungeonData> dungeons)
|
||||
{
|
||||
//Search for the shortest dungeon name that contains the lowercase query string.
|
||||
String dungeonName;
|
||||
String normalQuery = query.toLowerCase();
|
||||
DungeonData bestMatch = null;
|
||||
int matchLength = Integer.MAX_VALUE;
|
||||
|
||||
for (DungeonData 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 = dungeon.schematicName().toLowerCase();
|
||||
if (dungeonName.length() < matchLength && dungeonName.contains(normalQuery))
|
||||
{
|
||||
matchLength = dungeonName.length();
|
||||
bestMatch = dungeon;
|
||||
}
|
||||
}
|
||||
return bestMatch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
|
||||
public class CommandCreatePocket extends DDCommandBase
|
||||
{
|
||||
private static CommandCreatePocket instance = null;
|
||||
|
||||
private CommandCreatePocket()
|
||||
{
|
||||
super("dd-create", "");
|
||||
}
|
||||
|
||||
public static CommandCreatePocket instance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommandCreatePocket();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-create";
|
||||
}
|
||||
|
||||
@Override
|
||||
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 (command.length > 0)
|
||||
{
|
||||
return DDCommandResult.TOO_MANY_ARGUMENTS;
|
||||
}
|
||||
|
||||
//Place a door leading to a pocket dimension where the player is standing.
|
||||
//The pocket dimension will serve as a room for the player to build a dungeon.
|
||||
int x = (int) sender.posX;
|
||||
int y = (int) sender.posY;
|
||||
int z = (int) sender.posZ;
|
||||
DungeonHelper.instance().createCustomDungeonDoor(sender.worldObj, x, y, z);
|
||||
|
||||
//Notify the player
|
||||
sendChat(sender,("Created a door to a pocket dimension. Please build your dungeon there."));
|
||||
}
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CommandDeleteAllLinks extends DDCommandBase
|
||||
{
|
||||
private static CommandDeleteAllLinks instance = null;
|
||||
|
||||
private CommandDeleteAllLinks()
|
||||
{
|
||||
super("dd-deletelinks", "???");
|
||||
}
|
||||
|
||||
public static CommandDeleteAllLinks instance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommandDeleteAllLinks();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-deletelinks <targetDimensionID>";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
int linksRemoved=0;
|
||||
int targetDim;
|
||||
boolean shouldGo= true;
|
||||
|
||||
if(command.length==1)
|
||||
{
|
||||
targetDim = parseInt(sender, command[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetDim=0;
|
||||
shouldGo=false;
|
||||
sendChat(sender, ("Error-Invalid argument, delete_all_links <targetDimID>"));
|
||||
}
|
||||
|
||||
if(shouldGo)
|
||||
{
|
||||
|
||||
NewDimData dim = PocketManager.getDimensionData(targetDim);
|
||||
ArrayList<DimLink> linksInDim = dim.getAllLinks();
|
||||
|
||||
for (DimLink link : linksInDim)
|
||||
{
|
||||
World targetWorld = PocketManager.loadDimension(targetDim);
|
||||
targetWorld.setBlock(link.source().getX(), link.source().getY(), link.source().getZ(), 0);
|
||||
dim.deleteLink(link);
|
||||
//TODO Probably should check what the block is, but thats annoying so Ill do it later.
|
||||
|
||||
linksRemoved++;
|
||||
}
|
||||
sendChat(sender,("Removed " + linksRemoved + " links."));
|
||||
|
||||
}
|
||||
return DDCommandResult.SUCCESS; //TEMPORARY HACK
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CommandDeleteRifts extends DDCommandBase
|
||||
{
|
||||
private static CommandDeleteRifts instance = null;
|
||||
|
||||
private CommandDeleteRifts()
|
||||
{
|
||||
super("dd-???", "???");
|
||||
}
|
||||
|
||||
public static CommandDeleteRifts instance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommandDeleteRifts();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-??? <dimension ID>";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
int linksRemoved=0;
|
||||
int targetDim;
|
||||
boolean shouldGo= true;
|
||||
|
||||
if(command.length==1)
|
||||
{
|
||||
targetDim = parseInt(sender, command[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetDim=0;
|
||||
shouldGo=false;
|
||||
sendChat(sender,("Error-Invalid argument, delete_all_links <targetDimID>"));
|
||||
}
|
||||
|
||||
if(shouldGo)
|
||||
{
|
||||
|
||||
NewDimData dim = PocketManager.getDimensionData(targetDim);
|
||||
ArrayList<DimLink> linksInDim = dim.getAllLinks();
|
||||
|
||||
for (DimLink link : linksInDim)
|
||||
{
|
||||
World targetWorld = PocketManager.loadDimension(targetDim);
|
||||
|
||||
if(sender.worldObj.getBlockId(link.source().getX(), link.source().getY(), link.source().getZ())==mod_pocketDim.blockRift.blockID)
|
||||
{
|
||||
targetWorld.setBlock(link.source().getX(), link.source().getY(), link.source().getZ(), 0);
|
||||
linksRemoved++;
|
||||
dim.deleteLink(link);
|
||||
}
|
||||
}
|
||||
sendChat(sender,("Removed " + linksRemoved + " rifts."));
|
||||
|
||||
}
|
||||
return DDCommandResult.SUCCESS; //TEMPORARY HACK
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
|
||||
public class CommandExportDungeon extends DDCommandBase
|
||||
{
|
||||
private static CommandExportDungeon instance = null;
|
||||
|
||||
private CommandExportDungeon()
|
||||
{
|
||||
super("dd-export", new String[] {
|
||||
"<dungeon type> <dungeon name> <'open' | 'closed'> [weight]",
|
||||
"<schematic name> override" } );
|
||||
}
|
||||
|
||||
public static CommandExportDungeon instance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommandExportDungeon();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-export <dungeon type> <dungeon name> open <weight>\r\n" +
|
||||
" /dd-export <dungeon type> <dungeon name> closed <weight>\r\n" +
|
||||
" /dd-export <schematic name> override";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
/*
|
||||
* There are two versions of this command. One version takes 3 to 4 arguments consisting
|
||||
* of the information needed for a proper schematic name.
|
||||
*
|
||||
* 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 (command.length < 2)
|
||||
{
|
||||
return DDCommandResult.TOO_FEW_ARGUMENTS;
|
||||
}
|
||||
if (command.length > 4)
|
||||
{
|
||||
return DDCommandResult.TOO_MANY_ARGUMENTS;
|
||||
}
|
||||
|
||||
//Check if we received the 2-argument version
|
||||
if (command.length == 2)
|
||||
{
|
||||
if (command[1].equalsIgnoreCase("override"))
|
||||
{
|
||||
//Check that the schematic name is a legal name
|
||||
if (DungeonHelper.SCHEMATIC_NAME_PATTERN.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
|
||||
//TODO: Why do we check remoteness here but not before? And why not for the other export case?
|
||||
//Something feels wrong... ~SenseiKiwi
|
||||
if (!sender.worldObj.isRemote)
|
||||
{
|
||||
//TODO: This validation should be in DungeonHelper or in another class. We should move it
|
||||
//during the save file format rewrite. ~SenseiKiwi
|
||||
|
||||
if (!dungeonHelper.validateDungeonType(command[0], dungeonHelper.getDungeonPack("ruins")))
|
||||
{
|
||||
return new DDCommandResult("Error: Invalid dungeon type. Please use one of the existing types.");
|
||||
}
|
||||
if (!DungeonHelper.DUNGEON_NAME_PATTERN.matcher(command[1]).matches())
|
||||
{
|
||||
return new DDCommandResult("Error: Invalid dungeon name. Please use only letters, numbers, and dashes.");
|
||||
}
|
||||
if (!command[2].equalsIgnoreCase("open") && !command[2].equalsIgnoreCase("closed"))
|
||||
{
|
||||
return new DDCommandResult("Error: Please specify whether the dungeon is 'open' or 'closed'.");
|
||||
}
|
||||
|
||||
//If there are no more arguments, export the dungeon.
|
||||
if (command.length == 3)
|
||||
{
|
||||
return exportDungeon(sender, join(command, "_", 0, 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Validate the weight argument
|
||||
try
|
||||
{
|
||||
int weight = Integer.parseInt(command[3]);
|
||||
if (weight >= DungeonHelper.MIN_DUNGEON_WEIGHT && weight <= DungeonHelper.MAX_DUNGEON_WEIGHT)
|
||||
{
|
||||
return exportDungeon(sender, join(command, "_", 0, 4));
|
||||
}
|
||||
}
|
||||
catch (Exception e) { }
|
||||
}
|
||||
|
||||
//If we've reached this point, then we must have an invalid weight.
|
||||
return new DDCommandResult("Invalid dungeon weight. Please specify a weight between "
|
||||
+ DungeonHelper.MIN_DUNGEON_WEIGHT + " 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))
|
||||
{
|
||||
sendChat(player,("Saved dungeon schematic in " + exportPath));
|
||||
dungeonHelper.registerDungeon(exportPath, dungeonHelper.getDungeonPack("ruins"), false, true);
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DDCommandResult("Error: Failed to save dungeon schematic!");
|
||||
}
|
||||
}
|
||||
|
||||
private static String join(String[] source, String delimiter, int start, int end)
|
||||
{
|
||||
//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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
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
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "/dd-resetdungeons";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
if(sender.worldObj.isRemote)
|
||||
{
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
if (command.length > 0)
|
||||
{
|
||||
return DDCommandResult.TOO_FEW_ARGUMENTS;
|
||||
}
|
||||
|
||||
int dungeonCount = 0;
|
||||
int resetCount = 0;
|
||||
ArrayList<Integer> dimsToDelete = new ArrayList<Integer>();
|
||||
ArrayList<Integer> dimsToFix = new ArrayList<Integer>();
|
||||
|
||||
for (NewDimData data : PocketManager.getDimensions())
|
||||
{
|
||||
|
||||
if(DimensionManager.getWorld(data.id())==null&&data.isDungeon())
|
||||
{
|
||||
resetCount++;
|
||||
dungeonCount++;
|
||||
dimsToDelete.add(data.id());
|
||||
}
|
||||
else if(data.isDungeon())
|
||||
{
|
||||
dimsToFix.add(data.id());
|
||||
dungeonCount++;
|
||||
for(DimLink link : data.links())
|
||||
{
|
||||
if(link.linkType()==LinkTypes.REVERSE)
|
||||
{
|
||||
data.createLink(link.source(), LinkTypes.DUNGEON_EXIT, link.orientation());
|
||||
}
|
||||
if(link.linkType()==LinkTypes.DUNGEON)
|
||||
{
|
||||
data.createLink(link.source(), LinkTypes.DUNGEON, link.orientation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Integer dimID:dimsToDelete)
|
||||
{
|
||||
PocketManager.deletePocket(PocketManager.getDimensionData(dimID), true);
|
||||
}
|
||||
/**
|
||||
* temporary workaround
|
||||
*/
|
||||
for(Integer dimID: dimsToFix)
|
||||
{
|
||||
PocketManager.getDimensionData(dimID).setParentToRoot();
|
||||
}
|
||||
//TODO- for some reason the parent field of loaded dimenions get reset to null if I call .setParentToRoot() before I delete the pockets.
|
||||
//TODO implement blackList
|
||||
//Notify the user of the results
|
||||
sendChat(sender,("Reset complete. " + resetCount + " out of " + dungeonCount + " dungeons were reset."));
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class CommandTeleportPlayer extends DDCommandBase
|
||||
{
|
||||
private static CommandTeleportPlayer instance = null;
|
||||
|
||||
private CommandTeleportPlayer()
|
||||
{
|
||||
super("dd-tp", new String[] {"<Player Name> <Dimension ID> <X Coord> <Y Coord> <Z Coord>"} );
|
||||
}
|
||||
|
||||
public static CommandTeleportPlayer instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new CommandTeleportPlayer();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "Usage: /dd-tp <player name> <dimension id> <x> <y> <z>";
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO- Change to accept variety of input, like just coords, just dim ID, or two player names.
|
||||
*/
|
||||
@Override
|
||||
protected DDCommandResult processCommand(EntityPlayer sender, String[] command)
|
||||
{
|
||||
List<Integer> dimensionIDs = Arrays.asList(DimensionManager.getStaticDimensionIDs()); //Gets list of all registered dimensions, regardless if loaded or not
|
||||
EntityPlayer targetPlayer = sender;
|
||||
int dimDestinationID = sender.worldObj.provider.dimensionId;
|
||||
|
||||
if(command.length == 5)
|
||||
{
|
||||
for(int i= 1; i <5;i++)
|
||||
{
|
||||
if(!isInteger(command[i]))
|
||||
{
|
||||
return DDCommandResult.INVALID_ARGUMENTS;
|
||||
}
|
||||
}
|
||||
if(sender.worldObj.getPlayerEntityByName(command[0])!=null) //Gets the targeted player
|
||||
{
|
||||
targetPlayer = sender.worldObj.getPlayerEntityByName(command[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DDCommandResult.INVALID_ARGUMENTS;
|
||||
}
|
||||
dimDestinationID=Integer.parseInt(command[1]);//gets the target dim ID from the command string
|
||||
|
||||
if(!dimensionIDs.contains(dimDestinationID))
|
||||
{
|
||||
return DDCommandResult.INVALID_DIMENSION_ID;
|
||||
}
|
||||
|
||||
PocketManager.loadDimension(dimDestinationID);
|
||||
Point4D destination = new Point4D(Integer.parseInt(command[2]),Integer.parseInt(command[3]),Integer.parseInt(command[4]),dimDestinationID);
|
||||
DDTeleporter.teleportEntity(targetPlayer, destination, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DDCommandResult.INVALID_ARGUMENTS;
|
||||
}
|
||||
return DDCommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
public boolean isInteger( String input )
|
||||
{
|
||||
try
|
||||
{
|
||||
Integer.parseInt( input );
|
||||
return true;
|
||||
}
|
||||
catch(Exception e )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package StevenDimDoors.mod_pocketDim.commands;
|
||||
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChatMessageComponent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
|
||||
/*
|
||||
* An abstract base class for our Dimensional Doors commands. This cleans up the code a little and provides
|
||||
* some convenience improvements.
|
||||
*/
|
||||
public abstract class DDCommandBase extends CommandBase
|
||||
{
|
||||
private String name;
|
||||
private String[] formats;
|
||||
|
||||
public DDCommandBase(String name, String format)
|
||||
{
|
||||
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
|
||||
* and returns a status code and message for the result of the operation.
|
||||
*/
|
||||
protected abstract DDCommandResult processCommand(EntityPlayer sender, String[] command);
|
||||
|
||||
@Override
|
||||
public final String getCommandName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers the command at server startup.
|
||||
*/
|
||||
public void register(FMLServerStartingEvent event)
|
||||
{
|
||||
event.registerServerCommand(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Method invoked by the server to execute a command. The call is forwarded to a derived class
|
||||
* to provide the sending player directly.
|
||||
*/
|
||||
@Override
|
||||
public final void processCommand(ICommandSender sender, String[] command)
|
||||
{
|
||||
//Forward the 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)
|
||||
{
|
||||
sendChat(player,("Usage: " + name + " " + format));
|
||||
}
|
||||
}
|
||||
sendChat(player,(result.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendChat(EntityPlayer player, String message)
|
||||
{
|
||||
ChatMessageComponent cmp = new ChatMessageComponent();
|
||||
cmp.addText(message);
|
||||
player.sendChatToPlayer(cmp);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,700 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.item.EntityMinecart;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.packet.Packet41EntityEffect;
|
||||
import net.minecraft.network.packet.Packet43Experience;
|
||||
import net.minecraft.network.packet.Packet9Respawn;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper;
|
||||
import StevenDimDoors.mod_pocketDim.items.BaseItemDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.BlockRotator;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.world.PocketBuilder;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DDTeleporter
|
||||
{
|
||||
private static final Random random = new Random();
|
||||
private static final int END_DIMENSION_ID = 1;
|
||||
private static final int MAX_ROOT_SHIFT_CHANCE = 100;
|
||||
private static final int START_ROOT_SHIFT_CHANCE = 0;
|
||||
private static final int ROOT_SHIFT_CHANCE_PER_LEVEL = 5;
|
||||
|
||||
public static int cooldown = 0;
|
||||
|
||||
private DDTeleporter() { }
|
||||
|
||||
/**Checks if the destination supplied is valid, ie, filled by any non-replaceable block.
|
||||
*
|
||||
* @param entity
|
||||
* @param world
|
||||
* @param destination
|
||||
* @param properties
|
||||
* @return
|
||||
*/
|
||||
public static boolean CheckDestination(Entity entity, WorldServer world, Point4D destination,DDProperties properties)
|
||||
{
|
||||
int x = destination.getX();
|
||||
int y = destination.getY();
|
||||
int z = destination.getZ();
|
||||
int blockIDTop;
|
||||
int blockIDBottom;
|
||||
|
||||
Point3D point;
|
||||
|
||||
int orientation;
|
||||
|
||||
orientation = getDestinationOrientation(destination, properties);
|
||||
entity.rotationYaw = (orientation * 90) + 90;
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
point= new Point3D(MathHelper.floor_double(x - 0.5), y - 1, MathHelper.floor_double(z + 0.5));
|
||||
break;
|
||||
case 1:
|
||||
point= new Point3D(MathHelper.floor_double(x + 0.5), y - 1, MathHelper.floor_double(z - 0.5));
|
||||
break;
|
||||
case 2:
|
||||
point = new Point3D(MathHelper.floor_double(x + 1.5), y - 1, MathHelper.floor_double(z + 0.5));
|
||||
break;
|
||||
case 3:
|
||||
point = new Point3D(MathHelper.floor_double(x + 0.5), y - 1, MathHelper.floor_double(z + 1.5));
|
||||
break;
|
||||
default:
|
||||
point = new Point3D(x, y - 1, z);
|
||||
break;
|
||||
}
|
||||
blockIDBottom = world.getBlockId(point.getX(), point.getY(), point.getZ());
|
||||
blockIDTop = world.getBlockId(point.getX(), point.getY()+1, point.getZ());
|
||||
|
||||
if(!(Block.blocksList[blockIDBottom]==null))
|
||||
{
|
||||
if(!Block.blocksList[blockIDBottom].isBlockReplaceable(world, point.getX(), point.getY(), point.getZ()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!(Block.blocksList[blockIDTop]==null))
|
||||
{
|
||||
if(!Block.blocksList[blockIDTop].isBlockReplaceable(world, point.getX(), point.getY()+1, point.getZ()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
private static void placeInPortal(Entity entity, WorldServer world, Point4D destination, DDProperties properties, boolean checkOrientation)
|
||||
{
|
||||
int x = destination.getX();
|
||||
int y = destination.getY();
|
||||
int z = destination.getZ();
|
||||
|
||||
int orientation;
|
||||
if (checkOrientation)
|
||||
{
|
||||
orientation = getDestinationOrientation(destination, properties);
|
||||
entity.rotationYaw = (orientation * 90) + 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Teleport the entity to the precise destination point
|
||||
orientation = -1;
|
||||
}
|
||||
|
||||
if(!CheckDestination(entity, world, destination, properties))
|
||||
{
|
||||
if(entity instanceof EntityPlayerMP)
|
||||
{
|
||||
EntityPlayer player = (EntityPlayer) entity;
|
||||
player.rotationYaw=(orientation * 90)+90;
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 0.5);
|
||||
break;
|
||||
case 1:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 0.5);
|
||||
break;
|
||||
case 2:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 0.5);
|
||||
break;
|
||||
case 3:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + .5);
|
||||
break;
|
||||
default:
|
||||
player.setPositionAndUpdate(x, y - 1, z);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (entity instanceof EntityPlayer)
|
||||
{
|
||||
EntityPlayer player = (EntityPlayer) entity;
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
player.setPositionAndUpdate(x - 0.5, y - 1, z + 0.5);
|
||||
break;
|
||||
case 1:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z - 0.5);
|
||||
break;
|
||||
case 2:
|
||||
player.setPositionAndUpdate(x + 1.5, y - 1, z + 0.5);
|
||||
break;
|
||||
case 3:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 1.5);
|
||||
break;
|
||||
default:
|
||||
player.setPositionAndUpdate(x + 0.5, y - 1, z + 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (entity instanceof EntityMinecart)
|
||||
{
|
||||
entity.motionX = 0;
|
||||
entity.motionZ = 0;
|
||||
entity.motionY = 0;
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
DDTeleporter.setEntityPosition(entity, x - 0.5, y, z + 0.5);
|
||||
entity.motionX = -0.39;
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
break;
|
||||
case 1:
|
||||
DDTeleporter.setEntityPosition(entity, x + 0.5, y, z - 0.5);
|
||||
entity.motionZ = -0.39;
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
break;
|
||||
case 2:
|
||||
DDTeleporter.setEntityPosition(entity, x + 1.5, y, z + 0.5);
|
||||
entity.motionX = 0.39;
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
break;
|
||||
case 3:
|
||||
DDTeleporter.setEntityPosition(entity, x + 0.5, y, z + 1.5 );
|
||||
entity.motionZ = 0.39;
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
break;
|
||||
default:
|
||||
DDTeleporter.setEntityPosition(entity, x + 0.5, y, z + 0.5);
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
setEntityPosition(entity, x - 0.5, y, z + 0.5);
|
||||
break;
|
||||
case 1:
|
||||
setEntityPosition(entity, x + 0.5, y, z - 0.5);
|
||||
break;
|
||||
case 2:
|
||||
setEntityPosition(entity, x + 1.5, y, z + 0.5);
|
||||
break;
|
||||
case 3:
|
||||
setEntityPosition(entity, x + 0.5, y, z + 1.5);
|
||||
break;
|
||||
default:
|
||||
setEntityPosition(entity, x + 0.5, y, z + 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setEntityPosition(Entity entity, double x, double y, double z)
|
||||
{
|
||||
entity.lastTickPosX = entity.prevPosX = entity.posX = x;
|
||||
entity.lastTickPosY = entity.prevPosY = entity.posY = y + entity.yOffset;
|
||||
entity.lastTickPosZ = entity.prevPosZ = entity.posZ = z;
|
||||
entity.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
private static int getDestinationOrientation(Point4D door, DDProperties properties)
|
||||
{
|
||||
World world = DimensionManager.getWorld(door.getDimension());
|
||||
if (world == null)
|
||||
{
|
||||
throw new IllegalStateException("The destination world should be loaded!");
|
||||
}
|
||||
|
||||
//Check if the block below that point is actually a door
|
||||
int blockID = world.getBlockId(door.getX(), door.getY() - 1, door.getZ());
|
||||
if (blockID != properties.DimensionalDoorID && blockID != properties.WarpDoorID &&
|
||||
blockID != properties.TransientDoorID && blockID != properties.UnstableDoorID
|
||||
&& blockID != properties.GoldDimDoorID)
|
||||
{
|
||||
//Return the pocket's orientation instead
|
||||
return PocketManager.getDimensionData(door.getDimension()).orientation();
|
||||
}
|
||||
|
||||
//Return the orientation portion of its metadata
|
||||
return world.getBlockMetadata(door.getX(), door.getY() - 1, door.getZ()) & 3;
|
||||
}
|
||||
|
||||
public static Entity teleportEntity(Entity entity, Point4D destination, boolean checkOrientation)
|
||||
{
|
||||
if (entity == null)
|
||||
{
|
||||
throw new IllegalArgumentException("entity cannot be null.");
|
||||
}
|
||||
if (destination == null)
|
||||
{
|
||||
throw new IllegalArgumentException("destination cannot be null.");
|
||||
}
|
||||
|
||||
//This beautiful teleport method is based off of xCompWiz's teleport function.
|
||||
|
||||
WorldServer oldWorld = (WorldServer) entity.worldObj;
|
||||
WorldServer newWorld;
|
||||
EntityPlayerMP player = (entity instanceof EntityPlayerMP) ? (EntityPlayerMP) entity : null;
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
// Is something riding? Handle it first.
|
||||
if (entity.riddenByEntity != null)
|
||||
{
|
||||
return teleportEntity(entity.riddenByEntity, destination, checkOrientation);
|
||||
}
|
||||
|
||||
// Are we riding something? Dismount and tell the mount to go first.
|
||||
Entity cart = entity.ridingEntity;
|
||||
if (cart != null)
|
||||
{
|
||||
entity.mountEntity(null);
|
||||
cart = teleportEntity(cart, destination, checkOrientation);
|
||||
// We keep track of both so we can remount them on the other side.
|
||||
}
|
||||
|
||||
// Determine if our destination is in another realm.
|
||||
boolean difDest = entity.dimension != destination.getDimension();
|
||||
if (difDest)
|
||||
{
|
||||
// Destination isn't loaded? Then we need to load it.
|
||||
newWorld = PocketManager.loadDimension(destination.getDimension());
|
||||
}
|
||||
else
|
||||
{
|
||||
newWorld = oldWorld;
|
||||
}
|
||||
|
||||
|
||||
// GreyMaria: What is this even accomplishing? We're doing the exact same thing at the end of this all.
|
||||
// TODO Check to see if this is actually vital.
|
||||
DDTeleporter.placeInPortal(entity, newWorld, destination, properties, checkOrientation);
|
||||
|
||||
if (difDest) // Are we moving our target to a new dimension?
|
||||
{
|
||||
if(player != null) // Are we working with a player?
|
||||
{
|
||||
// We need to do all this special stuff to move a player between dimensions.
|
||||
|
||||
// Set the new dimension and inform the client that it's moving to a new world.
|
||||
player.dimension = destination.getDimension();
|
||||
player.playerNetServerHandler.sendPacketToPlayer(new Packet9Respawn(player.dimension, (byte)player.worldObj.difficultySetting, newWorld.getWorldInfo().getTerrainType(), newWorld.getHeight(), player.theItemInWorldManager.getGameType()));
|
||||
|
||||
// GreyMaria: Used the safe player entity remover before.
|
||||
// This should fix an apparently unreported bug where
|
||||
// the last non-sleeping player leaves the Overworld
|
||||
// for a pocket dimension, causing all sleeping players
|
||||
// to remain asleep instead of progressing to day.
|
||||
((WorldServer)entity.worldObj).getPlayerManager().removePlayer(player);
|
||||
oldWorld.removePlayerEntityDangerously(player);
|
||||
player.isDead = false;
|
||||
|
||||
// Creates sanity by ensuring that we're only known to exist where we're supposed to be known to exist.
|
||||
oldWorld.getPlayerManager().removePlayer(player);
|
||||
newWorld.getPlayerManager().addPlayer(player);
|
||||
|
||||
player.theItemInWorldManager.setWorld(newWorld);
|
||||
|
||||
// Synchronize with the server so the client knows what time it is and what it's holding.
|
||||
player.mcServer.getConfigurationManager().updateTimeAndWeatherForPlayer(player, newWorld);
|
||||
player.mcServer.getConfigurationManager().syncPlayerInventory(player);
|
||||
for(Object potionEffect : player.getActivePotionEffects())
|
||||
{
|
||||
PotionEffect effect = (PotionEffect)potionEffect;
|
||||
player.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(player.entityId, effect));
|
||||
}
|
||||
|
||||
player.playerNetServerHandler.sendPacketToPlayer(new Packet43Experience(player.experience, player.experienceTotal, player.experienceLevel));
|
||||
}
|
||||
|
||||
// Creates sanity by removing the entity from its old location's chunk entity list, if applicable.
|
||||
int entX = entity.chunkCoordX;
|
||||
int entZ = entity.chunkCoordZ;
|
||||
if ((entity.addedToChunk) && (oldWorld.getChunkProvider().chunkExists(entX, entZ)))
|
||||
{
|
||||
oldWorld.getChunkFromChunkCoords(entX, entZ).removeEntity(entity);
|
||||
oldWorld.getChunkFromChunkCoords(entX, entZ).isModified = true;
|
||||
}
|
||||
// Memory concerns.
|
||||
oldWorld.onEntityRemoved(entity);
|
||||
|
||||
if (player == null) // Are we NOT working with a player?
|
||||
{
|
||||
NBTTagCompound entityNBT = new NBTTagCompound();
|
||||
entity.isDead = false;
|
||||
entity.writeMountToNBT(entityNBT);
|
||||
entity.isDead = true;
|
||||
entity = EntityList.createEntityFromNBT(entityNBT, newWorld);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
// TODO FIXME IMPLEMENT NULL CHECKS THAT ACTUALLY DO SOMETHING.
|
||||
/*
|
||||
* shit ourselves in an organized fashion, preferably
|
||||
* in a neat pile instead of all over our users' games
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Finally, respawn the entity in its new home.
|
||||
newWorld.spawnEntityInWorld(entity);
|
||||
entity.setWorld(newWorld);
|
||||
}
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
||||
|
||||
// Hey, remember me? It's time to remount.
|
||||
if (cart != null)
|
||||
{
|
||||
// Was there a player teleported? If there was, it's important that we update shit.
|
||||
if (player != null)
|
||||
{
|
||||
entity.worldObj.updateEntityWithOptionalForce(entity, true);
|
||||
}
|
||||
entity.mountEntity(cart);
|
||||
}
|
||||
|
||||
// Did we teleport a player? Load the chunk for them.
|
||||
if (player != null)
|
||||
{
|
||||
newWorld.getChunkProvider().loadChunk(MathHelper.floor_double(entity.posX) >> 4, MathHelper.floor_double(entity.posZ) >> 4);
|
||||
// Tell Forge we're moving its players so everyone else knows.
|
||||
// Let's try doing this down here in case this is what's killing NEI.
|
||||
GameRegistry.onPlayerChangedDimension((EntityPlayer)entity);
|
||||
|
||||
}
|
||||
DDTeleporter.placeInPortal(entity, newWorld, destination, properties, checkOrientation);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary function used to teleport the player using doors. Performs numerous null checks, and also generates the destination door/pocket if it has not done so already.
|
||||
* Also ensures correct orientation relative to the door.
|
||||
* @param world - world the player is currently in
|
||||
* @param link - the link the player is using to teleport; sends the player to its destination
|
||||
* @param player - the instance of the player to be teleported
|
||||
*/
|
||||
public static void traverseDimDoor(World world, DimLink link, Entity entity, Block door)
|
||||
{
|
||||
if (world == null)
|
||||
{
|
||||
throw new IllegalArgumentException("world cannot be null.");
|
||||
}
|
||||
if (link == null)
|
||||
{
|
||||
throw new IllegalArgumentException("link cannot be null.");
|
||||
}
|
||||
if (entity == null)
|
||||
{
|
||||
throw new IllegalArgumentException("entity cannot be null.");
|
||||
}
|
||||
if (world.isRemote)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (cooldown == 0 || entity instanceof EntityPlayer)
|
||||
{
|
||||
cooldown = 2 + random.nextInt(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!initializeDestination(link, DDProperties.instance(),door))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (link.linkType() == LinkTypes.RANDOM)
|
||||
{
|
||||
Point4D randomDestination = getRandomDestination();
|
||||
if (randomDestination != null)
|
||||
{
|
||||
entity = teleportEntity(entity, randomDestination, true);
|
||||
entity.worldObj.playSoundEffect(entity.posX, entity.posY, entity.posZ, "mob.endermen.portal", 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buildExitDoor(door, link, DDProperties.instance());
|
||||
entity = teleportEntity(entity, link.destination(), link.linkType() != LinkTypes.UNSAFE_EXIT);
|
||||
entity.worldObj.playSoundEffect(entity.posX, entity.posY, entity.posZ, "mob.endermen.portal", 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean initializeDestination(DimLink link, DDProperties properties, Block door)
|
||||
{
|
||||
if (link.hasDestination())
|
||||
{
|
||||
if(PocketManager.isBlackListed(link.destination().getDimension()))
|
||||
{
|
||||
link=PocketManager.getDimensionData(link.source().getDimension()).createLink(link.link.point,LinkTypes.SAFE_EXIT,link.link.orientation);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the destination type and respond accordingly
|
||||
switch (link.linkType())
|
||||
{
|
||||
case LinkTypes.DUNGEON:
|
||||
return PocketBuilder.generateNewDungeonPocket(link, properties);
|
||||
case LinkTypes.POCKET:
|
||||
return PocketBuilder.generateNewPocket(link, properties,door);
|
||||
case LinkTypes.SAFE_EXIT:
|
||||
return generateSafeExit(link, properties);
|
||||
case LinkTypes.DUNGEON_EXIT:
|
||||
return generateDungeonExit(link, properties);
|
||||
case LinkTypes.UNSAFE_EXIT:
|
||||
return generateUnsafeExit(link);
|
||||
case LinkTypes.NORMAL:
|
||||
case LinkTypes.REVERSE:
|
||||
case LinkTypes.RANDOM:
|
||||
return true;
|
||||
default:
|
||||
throw new IllegalArgumentException("link has an unrecognized link type.");
|
||||
}
|
||||
}
|
||||
|
||||
private static Point4D getRandomDestination()
|
||||
{
|
||||
// Our aim is to return a random link's source point
|
||||
// so that a link of type RANDOM can teleport a player there.
|
||||
|
||||
// Restrictions:
|
||||
// 1. Ignore links with their source inside a pocket dimension.
|
||||
// 2. Ignore links with link type RANDOM.
|
||||
|
||||
// Iterate over the root dimensions. Pocket dimensions cannot be roots.
|
||||
// Don't just pick a random root and a random link within that root
|
||||
// because we want to have unbiased selection among all links.
|
||||
ArrayList<Point4D> matches = new ArrayList<Point4D>();
|
||||
for (NewDimData dimension : PocketManager.getRootDimensions())
|
||||
{
|
||||
for (DimLink link : dimension.getAllLinks())
|
||||
{
|
||||
if (link.linkType() != LinkTypes.RANDOM)
|
||||
{
|
||||
matches.add(link.source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick a random point, if any is available
|
||||
if (!matches.isEmpty())
|
||||
{
|
||||
return matches.get( random.nextInt(matches.size()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean generateUnsafeExit(DimLink link)
|
||||
{
|
||||
// An unsafe exit teleports the user to the first available air space
|
||||
// in the pocket's root dimension. X and Z are kept roughly the same
|
||||
// as the source location, but Y is set by searching down. We don't
|
||||
// place a platform at the destination. We also don't place a reverse
|
||||
// link at the destination, so it's a one-way trip. Good luck!
|
||||
|
||||
// To avoid loops, don't generate a destination if the player is
|
||||
// already in a non-pocket dimension.
|
||||
|
||||
NewDimData current = PocketManager.getDimensionData(link.link.point.getDimension());
|
||||
if (current.isPocketDimension())
|
||||
{
|
||||
Point4D source = link.source();
|
||||
World world = PocketManager.loadDimension(current.root().id());
|
||||
if (world == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Point3D destination = yCoordHelper.findDropPoint(world, source.getX(), source.getY() + 1, source.getZ());
|
||||
if (destination != null)
|
||||
{
|
||||
current.root().setDestination(link, destination.getX(), destination.getY(), destination.getZ());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void buildExitDoor(Block door,DimLink link, DDProperties prop)
|
||||
{
|
||||
World startWorld = PocketManager.loadDimension(link.source().getDimension());
|
||||
World destWorld = PocketManager.loadDimension(link.destination().getDimension());
|
||||
TileEntity doorTE = startWorld.getBlockTileEntity(link.source().getX(), link.source().getY(), link.link.point.getZ());
|
||||
if(doorTE instanceof TileEntityDimDoor)
|
||||
{
|
||||
if((TileEntityDimDoor.class.cast(doorTE).hasGennedPair))
|
||||
{
|
||||
return;
|
||||
}
|
||||
TileEntityDimDoor.class.cast(doorTE).hasGennedPair=true;
|
||||
Block blockToReplace = Block.blocksList[destWorld.getBlockId(link.destination().getX(), link.destination().getY(), link.destination().getZ())];
|
||||
|
||||
if(!destWorld.isAirBlock(link.destination().getX(), link.destination().getY(), link.destination().getZ()))
|
||||
{
|
||||
if(!blockToReplace.isBlockReplaceable(destWorld, link.destination().getX(), link.destination().getY(), link.destination().getZ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseItemDoor.placeDoorBlock(destWorld, link.destination().getX(), link.destination().getY()-1, link.destination().getZ(),link.getDestinationOrientation(), door);
|
||||
TileEntity doorDestTE = startWorld.getBlockTileEntity(link.destination().getX(), link.destination().getY(), link.destination().getZ());
|
||||
|
||||
if(doorDestTE instanceof TileEntityDimDoor)
|
||||
{
|
||||
TileEntityDimDoor.class.cast(doorDestTE).hasGennedPair=true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
private static boolean generateSafeExit(DimLink link, DDProperties properties)
|
||||
{
|
||||
NewDimData current = PocketManager.getDimensionData(link.link.point.getDimension());
|
||||
return generateSafeExit(current.root(), link, properties);
|
||||
}
|
||||
|
||||
private static boolean generateDungeonExit(DimLink link, DDProperties properties)
|
||||
{
|
||||
// A dungeon exit acts the same as a safe exit, but has the chance of
|
||||
// taking the user to any non-pocket dimension, excluding Limbo and The End.
|
||||
|
||||
NewDimData current = PocketManager.getDimensionData(link.link.point.getDimension());
|
||||
ArrayList<NewDimData> roots = PocketManager.getRootDimensions();
|
||||
int shiftChance = START_ROOT_SHIFT_CHANCE + ROOT_SHIFT_CHANCE_PER_LEVEL * (current.packDepth() - 1);
|
||||
|
||||
if (random.nextInt(MAX_ROOT_SHIFT_CHANCE) < shiftChance)
|
||||
{
|
||||
for (int attempts = 0; attempts < 10; attempts++)
|
||||
{
|
||||
NewDimData selection = roots.get( random.nextInt(roots.size()) );
|
||||
if (selection.id() != END_DIMENSION_ID &&
|
||||
selection.id() != properties.LimboDimensionID &&
|
||||
selection != current.root())
|
||||
{
|
||||
return generateSafeExit(selection, link, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Yes, this could lead you back into Limbo. That's intentional.
|
||||
return generateSafeExit(current.root(), link, properties);
|
||||
}
|
||||
|
||||
private static boolean generateSafeExit(NewDimData destinationDim, DimLink link, DDProperties properties)
|
||||
{
|
||||
// A safe exit attempts to place a Warp Door in a dimension with
|
||||
// some precautions to protect the player. The X and Z coordinates
|
||||
// are fixed to match the source (mostly - may be shifted a little),
|
||||
// but the Y coordinate is chosen by searching for the nearest
|
||||
// a safe location to place the door.
|
||||
|
||||
Point4D source = link.source();
|
||||
World world = PocketManager.loadDimension(destinationDim.id());
|
||||
if (world == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int startY = source.getY() - 2;
|
||||
Point3D destination;
|
||||
Point3D locationUp = yCoordHelper.findSafeCubeUp(world, source.getX(), startY, source.getZ());
|
||||
Point3D locationDown = yCoordHelper.findSafeCubeDown(world, source.getX(), startY, source.getZ());
|
||||
|
||||
if (locationUp == null)
|
||||
{
|
||||
destination = locationDown;
|
||||
}
|
||||
else if (locationDown == null)
|
||||
{
|
||||
destination = locationUp;
|
||||
}
|
||||
else if (locationUp.getY() - startY <= startY - locationDown.getY())
|
||||
{
|
||||
destination = locationUp;
|
||||
}
|
||||
else
|
||||
{
|
||||
destination = locationDown;
|
||||
}
|
||||
if (destination != null)
|
||||
{
|
||||
// Set up a 3x3 platform at the destination
|
||||
int x = destination.getX();
|
||||
int y = destination.getY();
|
||||
int z = destination.getZ();
|
||||
for (int dx = -1; dx <= 1; dx++)
|
||||
{
|
||||
for (int dz = -1; dz <= 1; dz++)
|
||||
{
|
||||
world.setBlock(x + dx, y, z + dz, properties.FabricBlockID);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a reverse link for returning
|
||||
int orientation = getDestinationOrientation(source, properties);
|
||||
NewDimData sourceDim = PocketManager.getDimensionData(link.source().getDimension());
|
||||
DimLink reverse = destinationDim.createLink(x, y + 2, z, LinkTypes.REVERSE,orientation);
|
||||
sourceDim.setDestination(reverse, source.getX(), source.getY(), source.getZ());
|
||||
|
||||
// Set up the warp door at the destination
|
||||
orientation = BlockRotator.transformMetadata(orientation, 2, properties.WarpDoorID);
|
||||
ItemDimensionalDoor.placeDoorBlock(world, x, y + 1, z, orientation, mod_pocketDim.warpDoor);
|
||||
|
||||
// Complete the link to the destination
|
||||
// This comes last so the destination isn't set unless everything else works first
|
||||
destinationDim.setDestination(link, x, y + 2, z);
|
||||
}
|
||||
|
||||
return (destination != null);
|
||||
}
|
||||
}
|
||||
96
src/main/java/StevenDimDoors/mod_pocketDim/core/DimLink.java
Normal file
96
src/main/java/StevenDimDoors/mod_pocketDim/core/DimLink.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||
|
||||
public abstract class DimLink
|
||||
{
|
||||
protected ClientLinkData link;
|
||||
protected DimLink parent;
|
||||
protected LinkTail tail;
|
||||
protected List<DimLink> children;
|
||||
|
||||
protected DimLink(ClientLinkData link, DimLink parent)
|
||||
{
|
||||
|
||||
if (parent.link.point.getDimension() != link.point.getDimension())
|
||||
{
|
||||
// Ban having children in other dimensions to avoid serialization issues with cross-dimensional tails
|
||||
throw new IllegalArgumentException("source and parent.source must have the same dimension.");
|
||||
}
|
||||
this.parent = parent;
|
||||
this.link = link;
|
||||
this.tail = parent.tail;
|
||||
this.children = new LinkedList<DimLink>();
|
||||
parent.children.add(this);
|
||||
}
|
||||
|
||||
protected DimLink(ClientLinkData link, int linkType)
|
||||
{
|
||||
if ((linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX) && linkType != LinkTypes.CLIENT_SIDE)
|
||||
{
|
||||
throw new IllegalArgumentException("The specified link type is invalid.");
|
||||
}
|
||||
|
||||
this.parent = null;
|
||||
this.link = link;
|
||||
this.tail = new LinkTail(linkType, null);
|
||||
this.children = new LinkedList<DimLink>();
|
||||
}
|
||||
|
||||
public Point4D source()
|
||||
{
|
||||
return link.point;
|
||||
}
|
||||
|
||||
public int orientation()
|
||||
{
|
||||
return link.orientation;
|
||||
}
|
||||
|
||||
public ClientLinkData link()
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
public Point4D destination()
|
||||
{
|
||||
return tail.getDestination();
|
||||
}
|
||||
public int getDestinationOrientation()
|
||||
{
|
||||
return PocketManager.getLink(link.point.getX(), link.point.getY(), link.point.getZ(), link.point.getDimension()).link().orientation;
|
||||
}
|
||||
public boolean hasDestination()
|
||||
{
|
||||
return (tail.getDestination() != null);
|
||||
}
|
||||
|
||||
public Iterable<DimLink> children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public int childCount()
|
||||
{
|
||||
return children.size();
|
||||
}
|
||||
|
||||
public DimLink parent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
public int linkType()
|
||||
{
|
||||
return tail.getLinkType();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return link.point + " -> " + (hasDestination() ? destination() : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
public interface IDimRegistrationCallback
|
||||
{
|
||||
public NewDimData registerDimension(int dimensionID, int rootID);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
class LinkTail
|
||||
{
|
||||
private Point4D destination;
|
||||
private int linkType;
|
||||
|
||||
public LinkTail(int linkType, Point4D destination)
|
||||
{
|
||||
this.linkType = linkType;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public Point4D getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(Point4D destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public int getLinkType() {
|
||||
return linkType;
|
||||
}
|
||||
|
||||
public void setLinkType(int linkType) {
|
||||
this.linkType = linkType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
public class LinkTypes
|
||||
{
|
||||
private LinkTypes() { }
|
||||
|
||||
public static final int ENUM_MIN = 0;
|
||||
public static final int ENUM_MAX = 7;
|
||||
|
||||
public static final int CLIENT_SIDE = -1337;
|
||||
|
||||
// WARNING: Don't modify these values carelessly or you'll risk breaking links in existing worlds!
|
||||
public static final int NORMAL = 0;
|
||||
public static final int POCKET = 1;
|
||||
public static final int DUNGEON = 2;
|
||||
public static final int RANDOM = 3;
|
||||
public static final int DUNGEON_EXIT = 4;
|
||||
public static final int SAFE_EXIT = 5;
|
||||
public static final int UNSAFE_EXIT = 6;
|
||||
public static final int REVERSE = 7;
|
||||
}
|
||||
553
src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java
Normal file
553
src/main/java/StevenDimDoors/mod_pocketDim/core/NewDimData.java
Normal file
@@ -0,0 +1,553 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class NewDimData
|
||||
{
|
||||
private static class InnerDimLink extends DimLink
|
||||
{
|
||||
public InnerDimLink(Point4D source, DimLink parent,int orientation)
|
||||
{
|
||||
super(new ClientLinkData(source, orientation), parent);
|
||||
}
|
||||
|
||||
public InnerDimLink(Point4D source, int linkType, int orientation)
|
||||
{
|
||||
super(new ClientLinkData(source, orientation), linkType);
|
||||
}
|
||||
|
||||
public void setDestination(int x, int y, int z, NewDimData dimension)
|
||||
{
|
||||
tail.setDestination(new Point4D(x, y, z, dimension.id()));
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
((InnerDimLink) child).parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
parent = null;
|
||||
link = null;
|
||||
tail = new LinkTail(0, null);
|
||||
}
|
||||
|
||||
public boolean overwrite(InnerDimLink nextParent,int orientation)
|
||||
{
|
||||
if (nextParent == null)
|
||||
{
|
||||
throw new IllegalArgumentException("nextParent cannot be null.");
|
||||
}
|
||||
if (this == nextParent)
|
||||
{
|
||||
//Ignore this request silently
|
||||
return false;
|
||||
}
|
||||
if (nextParent.link.point.getDimension() != link.point.getDimension())
|
||||
{
|
||||
// Ban having children in other dimensions to avoid serialization issues with cross-dimensional tails
|
||||
throw new IllegalArgumentException("source and parent.source must have the same dimension.");
|
||||
}
|
||||
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
((InnerDimLink) child).parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
//Attach to new parent
|
||||
parent = nextParent;
|
||||
tail = nextParent.tail;
|
||||
nextParent.children.add(this);
|
||||
this.link.orientation=orientation;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void overwrite(int linkType, int orientation)
|
||||
{
|
||||
//Release children
|
||||
for (DimLink child : children)
|
||||
{
|
||||
((InnerDimLink) child).parent = null;
|
||||
}
|
||||
children.clear();
|
||||
|
||||
//Release parent
|
||||
if (parent != null)
|
||||
{
|
||||
parent.children.remove(this);
|
||||
}
|
||||
|
||||
//Attach to new parent
|
||||
parent = null;
|
||||
tail = new LinkTail(linkType, null);
|
||||
//Set new orientation
|
||||
this.link.orientation=orientation;
|
||||
}
|
||||
}
|
||||
|
||||
protected static Random random = new Random();
|
||||
|
||||
protected int id;
|
||||
protected Map<Point4D, InnerDimLink> linkMapping;
|
||||
protected List<InnerDimLink> linkList;
|
||||
protected boolean isDungeon;
|
||||
protected boolean isFilled;
|
||||
protected int depth;
|
||||
protected int packDepth;
|
||||
protected NewDimData parent;
|
||||
protected NewDimData root;
|
||||
protected List<NewDimData> children;
|
||||
protected Point4D origin;
|
||||
protected int orientation;
|
||||
protected DungeonData dungeon;
|
||||
protected IUpdateWatcher<ClientLinkData> linkWatcher;
|
||||
|
||||
protected NewDimData(int id, NewDimData parent, boolean isPocket, boolean isDungeon,
|
||||
IUpdateWatcher<ClientLinkData> linkWatcher)
|
||||
{
|
||||
// The isPocket flag is redundant. It's meant as an integrity safeguard.
|
||||
if (isPocket && (parent == null))
|
||||
{
|
||||
throw new NullPointerException("Dimensions can be pocket dimensions if and only if they have a parent dimension.");
|
||||
}
|
||||
if (isDungeon && !isPocket)
|
||||
{
|
||||
throw new IllegalArgumentException("A dimensional dungeon must also be a pocket dimension.");
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
this.linkMapping = new TreeMap<Point4D, InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||
this.linkList = new ArrayList<InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||
this.children = new ArrayList<NewDimData>();
|
||||
this.parent = parent;
|
||||
this.packDepth = 0;
|
||||
this.isDungeon = isDungeon;
|
||||
this.isFilled = false;
|
||||
this.orientation = 0;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.linkWatcher = linkWatcher;
|
||||
|
||||
//Register with parent
|
||||
if (parent != null)
|
||||
{
|
||||
//We don't need to raise an update event for adding a child because the child's creation will be signaled.
|
||||
this.root = parent.root;
|
||||
this.depth = parent.depth + 1;
|
||||
parent.children.add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.root = this;
|
||||
this.depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected NewDimData(int id, NewDimData root)
|
||||
{
|
||||
// This constructor is meant for client-side code only
|
||||
if (root == null)
|
||||
{
|
||||
throw new IllegalArgumentException("root cannot be null.");
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
this.linkMapping = new TreeMap<Point4D, InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||
this.linkList = new ArrayList<InnerDimLink>(); //Should be stored in oct tree -- temporary solution
|
||||
this.children = new ArrayList<NewDimData>();
|
||||
this.parent = null;
|
||||
this.packDepth = 0;
|
||||
this.isDungeon = false;
|
||||
this.isFilled = false;
|
||||
this.orientation = 0;
|
||||
this.origin = null;
|
||||
this.dungeon = null;
|
||||
this.linkWatcher = null;
|
||||
this.depth = 0;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public DimLink findNearestRift(World world, int range, int x, int y, int z)
|
||||
{
|
||||
//TODO: Rewrite this later to use an octtree
|
||||
|
||||
//Sanity check...
|
||||
if (world.provider.dimensionId != id)
|
||||
{
|
||||
throw new IllegalArgumentException("Attempted to search for links in a World instance for a different dimension!");
|
||||
}
|
||||
|
||||
//Note: Only detect rifts at a distance > 1, so we ignore the rift
|
||||
//that called this function and any adjacent rifts.
|
||||
|
||||
DimLink nearest = null;
|
||||
DimLink link;
|
||||
|
||||
int distance;
|
||||
int minDistance = Integer.MAX_VALUE;
|
||||
int i, j, k;
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
for (i = -range; i <= range; i++)
|
||||
{
|
||||
for (j = -range; j <= range; j++)
|
||||
{
|
||||
for (k = -range; k <= range; k++)
|
||||
{
|
||||
distance = getAbsoluteSum(i, j, k);
|
||||
if (distance > 1 && distance < minDistance && world.getBlockId(x + i, y + j, z + k) == properties.RiftBlockID)
|
||||
{
|
||||
link = getLink(x+i, y+j, z+k);
|
||||
if (link != null)
|
||||
{
|
||||
nearest = link;
|
||||
minDistance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
private static int getAbsoluteSum(int i, int j, int k)
|
||||
{
|
||||
return Math.abs(i) + Math.abs(j) + Math.abs(k);
|
||||
}
|
||||
public DimLink createLink(int x, int y, int z, int linkType,int orientation)
|
||||
{
|
||||
return createLink(new Point4D(x, y, z, id), linkType,orientation);
|
||||
}
|
||||
|
||||
public DimLink createLink(Point4D source, int linkType,int orientation)
|
||||
{
|
||||
//Return an existing link if there is one to avoid creating multiple links starting at the same point.
|
||||
InnerDimLink link = linkMapping.get(source);
|
||||
if (link == null)
|
||||
{
|
||||
link = new InnerDimLink(source, linkType,orientation);
|
||||
linkMapping.put(source, link);
|
||||
linkList.add(link);
|
||||
}
|
||||
else
|
||||
{
|
||||
link.overwrite(linkType,orientation);
|
||||
}
|
||||
//Link created!
|
||||
if(linkType!=LinkTypes.CLIENT_SIDE)
|
||||
{
|
||||
linkWatcher.onCreated(link.link);
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
public DimLink createChildLink(int x, int y, int z, DimLink parent)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
throw new IllegalArgumentException("parent cannot be null.");
|
||||
}
|
||||
|
||||
return createChildLink(new Point4D(x, y, z, id), (InnerDimLink) parent);
|
||||
}
|
||||
|
||||
private DimLink createChildLink(Point4D source, InnerDimLink parent)
|
||||
{
|
||||
//To avoid having multiple links at a single point, if we find an existing link then we overwrite
|
||||
//its destination data instead of creating a new instance.
|
||||
|
||||
InnerDimLink link = linkMapping.get(source);
|
||||
if (link == null)
|
||||
{
|
||||
link = new InnerDimLink(source, parent, parent.link.orientation);
|
||||
linkMapping.put(source, link);
|
||||
linkList.add(link);
|
||||
|
||||
//Link created!
|
||||
linkWatcher.onCreated(link.link);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.overwrite(parent, parent.link.orientation))
|
||||
{
|
||||
//Link created!
|
||||
linkWatcher.onCreated(link.link);
|
||||
}
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
public boolean deleteLink(DimLink link)
|
||||
{
|
||||
if (link.source().getDimension() != id)
|
||||
{
|
||||
throw new IllegalArgumentException("Attempted to delete a link from another dimension.");
|
||||
}
|
||||
InnerDimLink target = linkMapping.remove(link.source());
|
||||
if (target != null)
|
||||
{
|
||||
linkList.remove(target);
|
||||
//Raise deletion event
|
||||
linkWatcher.onDeleted(target.link);
|
||||
target.clear();
|
||||
}
|
||||
return (target != null);
|
||||
}
|
||||
|
||||
public boolean deleteLink(int x, int y, int z)
|
||||
{
|
||||
Point4D location = new Point4D(x, y, z, id);
|
||||
InnerDimLink target = linkMapping.remove(location);
|
||||
if (target != null)
|
||||
{
|
||||
linkList.remove(target);
|
||||
//Raise deletion event
|
||||
//TODO why is source null here?
|
||||
if(target.link!=null)
|
||||
{
|
||||
linkWatcher.onDeleted(target.link);
|
||||
}
|
||||
target.clear();
|
||||
}
|
||||
return (target != null);
|
||||
}
|
||||
|
||||
public DimLink getLink(int x, int y, int z)
|
||||
{
|
||||
Point4D location = new Point4D(x, y, z, id);
|
||||
return linkMapping.get(location);
|
||||
}
|
||||
|
||||
public DimLink getLink(Point3D location)
|
||||
{
|
||||
return linkMapping.get(new Point4D(location.getX(),location.getY(),location.getZ(),this.id));
|
||||
}
|
||||
|
||||
public DimLink getLink(Point4D location)
|
||||
{
|
||||
if (location.getDimension() != id)
|
||||
return null;
|
||||
|
||||
return linkMapping.get(location);
|
||||
}
|
||||
|
||||
public ArrayList<DimLink> getAllLinks()
|
||||
{
|
||||
ArrayList<DimLink> results = new ArrayList<DimLink>(linkMapping.size());
|
||||
results.addAll(linkMapping.values());
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean isPocketDimension()
|
||||
{
|
||||
return (root != this);
|
||||
}
|
||||
|
||||
public boolean isDungeon()
|
||||
{
|
||||
return isDungeon;
|
||||
}
|
||||
|
||||
public boolean isFilled()
|
||||
{
|
||||
return isFilled;
|
||||
}
|
||||
|
||||
public void setFilled(boolean isFilled)
|
||||
{
|
||||
this.isFilled = isFilled;
|
||||
}
|
||||
|
||||
public int id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public int depth()
|
||||
{
|
||||
return depth;
|
||||
}
|
||||
|
||||
public int packDepth()
|
||||
{
|
||||
return packDepth;
|
||||
}
|
||||
|
||||
public Point4D origin()
|
||||
{
|
||||
return origin;
|
||||
}
|
||||
|
||||
public NewDimData parent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
public NewDimData root()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
public int orientation()
|
||||
{
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public DungeonData dungeon()
|
||||
{
|
||||
return dungeon;
|
||||
}
|
||||
|
||||
public boolean isInitialized()
|
||||
{
|
||||
return (origin != null);
|
||||
}
|
||||
|
||||
public int linkCount()
|
||||
{
|
||||
return linkList.size();
|
||||
}
|
||||
|
||||
public Iterable<NewDimData> children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public Iterable<? extends DimLink> links()
|
||||
{
|
||||
return linkList;
|
||||
}
|
||||
|
||||
public void initializeDungeon(int originX, int originY, int originZ, int orientation, DimLink incoming, DungeonData dungeon)
|
||||
{
|
||||
if (!isDungeon)
|
||||
{
|
||||
throw new IllegalStateException("Cannot invoke initializeDungeon() on a non-dungeon dimension.");
|
||||
}
|
||||
if (isInitialized())
|
||||
{
|
||||
throw new IllegalStateException("The dimension has already been initialized.");
|
||||
}
|
||||
if (orientation < 0 || orientation > 3)
|
||||
{
|
||||
throw new IllegalArgumentException("orientation must be between 0 and 3, inclusive.");
|
||||
}
|
||||
setDestination(incoming, originX, originY, originZ);
|
||||
this.origin = incoming.destination();
|
||||
this.orientation = orientation;
|
||||
this.dungeon = dungeon;
|
||||
this.packDepth = calculatePackDepth(parent, dungeon);
|
||||
}
|
||||
|
||||
/**
|
||||
* effectivly moves the dungeon to the 'top' of a chain as far as dungeon generation is concerend.
|
||||
*/
|
||||
public void setParentToRoot()
|
||||
{
|
||||
this.depth=1;
|
||||
this.parent=this.root;
|
||||
this.root.children.add(this);
|
||||
}
|
||||
|
||||
public static int calculatePackDepth(NewDimData parent, DungeonData current)
|
||||
{
|
||||
DungeonData predecessor = parent.dungeon();
|
||||
if (current == null)
|
||||
{
|
||||
throw new IllegalArgumentException("current cannot be null.");
|
||||
}
|
||||
if (predecessor == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
DungeonPack predOwner = predecessor.dungeonType().Owner;
|
||||
DungeonPack currentOwner = current.dungeonType().Owner;
|
||||
if (currentOwner == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (predOwner == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (predOwner == currentOwner)
|
||||
{
|
||||
return parent.packDepth + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void initializePocket(int originX, int originY, int originZ, int orientation, DimLink incoming)
|
||||
{
|
||||
if (!isPocketDimension())
|
||||
{
|
||||
throw new IllegalStateException("Cannot invoke initializePocket() on a non-pocket dimension.");
|
||||
}
|
||||
if (isInitialized())
|
||||
{
|
||||
throw new IllegalStateException("The dimension has already been initialized.");
|
||||
}
|
||||
|
||||
setDestination(incoming, originX, originY, originZ);
|
||||
this.origin = incoming.destination();
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public void setDestination(DimLink incoming, int x, int y, int z)
|
||||
{
|
||||
InnerDimLink link = (InnerDimLink) incoming;
|
||||
link.setDestination(x, y, z, this);
|
||||
}
|
||||
|
||||
public DimLink getRandomLink()
|
||||
{
|
||||
if (linkMapping.isEmpty())
|
||||
{
|
||||
throw new IllegalStateException("There are no links to select from in this dimension.");
|
||||
}
|
||||
if (linkList.size() > 1)
|
||||
{
|
||||
return linkList.get(random.nextInt(linkList.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return linkList.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,710 @@
|
||||
package StevenDimDoors.mod_pocketDim.core;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.Compactor;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DeleteFolder;
|
||||
import StevenDimDoors.mod_pocketDim.saving.DDSaveHandler;
|
||||
import StevenDimDoors.mod_pocketDim.saving.IPackable;
|
||||
import StevenDimDoors.mod_pocketDim.saving.OldSaveImporter;
|
||||
import StevenDimDoors.mod_pocketDim.saving.PackedDimData;
|
||||
import StevenDimDoors.mod_pocketDim.saving.PackedDungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.saving.PackedLinkData;
|
||||
import StevenDimDoors.mod_pocketDim.saving.PackedLinkTail;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientDimData;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateSource;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.IUpdateWatcher;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.UpdateWatcherProxy;
|
||||
|
||||
/**
|
||||
* This class regulates all the operations involving the storage and manipulation of dimensions. It handles saving dim data, teleporting the player, and
|
||||
* creating/registering new dimensions as well as loading old dimensions on startup
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PocketManager
|
||||
{
|
||||
private static class InnerDimData extends NewDimData implements IPackable<PackedDimData>
|
||||
{
|
||||
// This class allows us to instantiate NewDimData indirectly without exposing
|
||||
// a public constructor from NewDimData. It's meant to stop us from constructing
|
||||
// instances of NewDimData going through PocketManager. In turn, that enforces
|
||||
// that any link destinations must be real dimensions controlled by PocketManager.
|
||||
|
||||
public InnerDimData(int id, InnerDimData parent, boolean isPocket, boolean isDungeon,
|
||||
IUpdateWatcher<ClientLinkData> linkWatcher)
|
||||
{
|
||||
super(id, parent, isPocket, isDungeon, linkWatcher);
|
||||
}
|
||||
|
||||
public InnerDimData(int id, InnerDimData root)
|
||||
{
|
||||
// This constructor is meant for client-side code only
|
||||
super(id, root);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
// If this dimension has a parent, remove it from its parent's list of children
|
||||
if (parent != null)
|
||||
{
|
||||
parent.children.remove(this);
|
||||
}
|
||||
// Remove this dimension as the parent of its children
|
||||
for (NewDimData child : children)
|
||||
{
|
||||
child.parent = null;
|
||||
}
|
||||
// Clear all fields
|
||||
id = Integer.MIN_VALUE;
|
||||
linkMapping.clear();
|
||||
linkMapping = null;
|
||||
linkList.clear();
|
||||
linkList = null;
|
||||
children.clear();
|
||||
children = null;
|
||||
isDungeon = false;
|
||||
isFilled = false;
|
||||
depth = Integer.MIN_VALUE;
|
||||
packDepth = Integer.MIN_VALUE;
|
||||
origin = null;
|
||||
orientation = Integer.MIN_VALUE;
|
||||
dungeon = null;
|
||||
linkWatcher = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name()
|
||||
{
|
||||
return String.valueOf(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackedDimData pack()
|
||||
{
|
||||
ArrayList<Integer> ChildIDs = new ArrayList<Integer>();
|
||||
ArrayList<PackedLinkData> Links = new ArrayList<PackedLinkData>();
|
||||
ArrayList<PackedLinkTail> Tails = new ArrayList<PackedLinkTail>();
|
||||
PackedDungeonData packedDungeon=null;
|
||||
|
||||
if(this.dungeon!=null)
|
||||
{
|
||||
packedDungeon= new PackedDungeonData(dungeon.weight(), dungeon.isOpen(), dungeon.isInternal(),
|
||||
dungeon.schematicPath(), dungeon.schematicName(), dungeon.dungeonType().Name,
|
||||
dungeon.dungeonType().Owner.getName());
|
||||
}
|
||||
//Make a list of children
|
||||
for(NewDimData data : this.children)
|
||||
{
|
||||
ChildIDs.add(data.id);
|
||||
}
|
||||
for(DimLink link:this.links())
|
||||
{
|
||||
ArrayList<Point3D> children = new ArrayList<Point3D>();
|
||||
Point3D parentPoint = new Point3D(-1,-1,-1);
|
||||
if(link.parent!=null)
|
||||
{
|
||||
parentPoint=link.parent.link.point.toPoint3D();
|
||||
}
|
||||
|
||||
for(DimLink childLink : link.children)
|
||||
{
|
||||
children.add(childLink.source().toPoint3D());
|
||||
}
|
||||
PackedLinkTail tail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType());
|
||||
Links.add(new PackedLinkData(link.link.point,parentPoint,tail,link.link.orientation,children));
|
||||
|
||||
PackedLinkTail tempTail = new PackedLinkTail(link.tail.getDestination(),link.tail.getLinkType());
|
||||
if(Tails.contains(tempTail))
|
||||
{
|
||||
Tails.add(tempTail);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
int parentID=this.id;
|
||||
Point3D originPoint=new Point3D(0,0,0);
|
||||
if(this.parent!=null)
|
||||
{
|
||||
parentID = this.parent.id;
|
||||
}
|
||||
if(this.origin!=null)
|
||||
{
|
||||
originPoint=this.origin.toPoint3D();
|
||||
}
|
||||
return new PackedDimData(this.id, depth, this.packDepth, parentID, this.root().id(), orientation,
|
||||
isDungeon, isFilled,packedDungeon, originPoint, ChildIDs, Links, Tails);
|
||||
// FIXME: IMPLEMENTATION PLZTHX
|
||||
//I tried
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClientLinkWatcher implements IUpdateWatcher<ClientLinkData>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(ClientLinkData link)
|
||||
{
|
||||
Point4D source = link.point;
|
||||
NewDimData dimension = getDimensionData(source.getDimension());
|
||||
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE,link.orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(ClientLinkData link)
|
||||
{
|
||||
Point4D source = link.point;
|
||||
NewDimData dimension = getDimensionData(source.getDimension());
|
||||
dimension.deleteLink(source.getX(), source.getY(), source.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClientDimWatcher implements IUpdateWatcher<ClientDimData>
|
||||
{
|
||||
@Override
|
||||
public void onCreated(ClientDimData data)
|
||||
{
|
||||
registerClientDimension(data.ID, data.RootID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleted(ClientDimData data)
|
||||
{
|
||||
deletePocket(getDimensionData(data.ID), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DimRegistrationCallback implements IDimRegistrationCallback
|
||||
{
|
||||
// We use this class to provide Compactor with the ability to send us dim data without
|
||||
// having to instantiate a bunch of data containers and without exposing an "unsafe"
|
||||
// creation method for anyone to call. Integrity protection for the win! It's like
|
||||
// exposing a private constructor ONLY to a very specific trusted class.
|
||||
|
||||
@Override
|
||||
public NewDimData registerDimension(int dimensionID, int rootID)
|
||||
{
|
||||
return registerClientDimension(dimensionID, rootID);
|
||||
}
|
||||
}
|
||||
|
||||
private static int OVERWORLD_DIMENSION_ID = 0;
|
||||
|
||||
private static volatile boolean isLoading = false;
|
||||
private static volatile boolean isLoaded = false;
|
||||
private static volatile boolean isSaving = false;
|
||||
/**
|
||||
* Set as true if we are a client that has connected to a dedicated server
|
||||
*/
|
||||
public static volatile boolean isConnected = false;
|
||||
private static final UpdateWatcherProxy<ClientLinkData> linkWatcher = new UpdateWatcherProxy<ClientLinkData>();
|
||||
private static final UpdateWatcherProxy<ClientDimData> dimWatcher = new UpdateWatcherProxy<ClientDimData>();
|
||||
private static ArrayList<NewDimData> rootDimensions = null;
|
||||
|
||||
//HashMap that maps all the dimension IDs registered with DimDoors to their DD data.
|
||||
private static HashMap<Integer, InnerDimData> dimensionData = null;
|
||||
//ArrayList that stores the dimension IDs of any dimension that has been deleted.
|
||||
private static ArrayList<Integer> dimensionIDBlackList = null;
|
||||
|
||||
public static boolean isLoaded()
|
||||
{
|
||||
return isLoaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* simple method called on startup to register all dims saved in the dim list. Only tries to register pocket dims, though. Also calls load()
|
||||
* @return
|
||||
*/
|
||||
public static void load()
|
||||
{
|
||||
if (isLoaded)
|
||||
{
|
||||
throw new IllegalStateException("Pocket dimensions have already been loaded!");
|
||||
}
|
||||
if (isLoading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isLoading = true;
|
||||
|
||||
dimensionData = new HashMap<Integer, InnerDimData>();
|
||||
rootDimensions = new ArrayList<NewDimData>();
|
||||
dimensionIDBlackList = new ArrayList<Integer>();
|
||||
|
||||
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
|
||||
{
|
||||
//Shouldnt try to load everything if we are a client
|
||||
//This was preventing onPacket from loading properly
|
||||
isLoading=false;
|
||||
return;
|
||||
}
|
||||
//Register Limbo
|
||||
DDProperties properties = DDProperties.instance();
|
||||
registerDimension(properties.LimboDimensionID, null, false, false);
|
||||
|
||||
loadInternal();
|
||||
|
||||
//Register pocket dimensions
|
||||
registerPockets(properties);
|
||||
|
||||
isLoaded = true;
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
public static boolean registerPackedDimData(PackedDimData packedData)
|
||||
{
|
||||
InnerDimData dimData;
|
||||
|
||||
if(packedData.ID==packedData.ParentID)
|
||||
{
|
||||
dimData = new InnerDimData(packedData.ID, null, false, false, linkWatcher);
|
||||
dimData.root=dimData;
|
||||
dimData.parent=dimData;
|
||||
dimData.isFilled=packedData.IsFilled;
|
||||
dimData.origin = new Point4D(packedData.Origin.getX(),packedData.Origin.getY(),packedData.Origin.getZ(),packedData.ID);
|
||||
|
||||
PocketManager.rootDimensions.add(dimData);
|
||||
}
|
||||
else
|
||||
{
|
||||
InnerDimData test = PocketManager.dimensionData.get(packedData.ParentID);
|
||||
dimData = new InnerDimData(packedData.ID, test,true, packedData.IsDungeon, linkWatcher);
|
||||
dimData.isFilled=packedData.IsFilled;
|
||||
dimData.origin = new Point4D(packedData.Origin.getX(),packedData.Origin.getY(),packedData.Origin.getZ(),packedData.ID);
|
||||
|
||||
dimData.root=PocketManager.getDimensionData(packedData.RootID);
|
||||
|
||||
if(packedData.DungeonData!=null)
|
||||
{
|
||||
dimData.dungeon=DDSaveHandler.unpackDungeonData(packedData.DungeonData);
|
||||
}
|
||||
|
||||
}
|
||||
PocketManager.dimensionData.put(dimData.id, dimData);
|
||||
dimWatcher.onCreated(new ClientDimData(dimData));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
public static boolean deletePocket(NewDimData target, boolean deleteFolder)
|
||||
{
|
||||
// We can't delete the dimension if it's currently loaded or if it's not actually a pocket.
|
||||
// We cast to InnerDimData so that if anyone tries to be a smartass and create their
|
||||
// own version of NewDimData, this will throw an exception.
|
||||
InnerDimData dimension = (InnerDimData) target;
|
||||
if (dimension.isPocketDimension() && DimensionManager.getWorld(dimension.id()) == null)
|
||||
{
|
||||
if (deleteFolder)
|
||||
{
|
||||
deleteDimensionFolder(target);
|
||||
}
|
||||
dimensionIDBlackList.add(dimension.id);
|
||||
deleteDimensionData(dimension.id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static boolean deleteDimensionFolder(NewDimData target)
|
||||
{
|
||||
InnerDimData dimension = (InnerDimData) target;
|
||||
if (dimension.isPocketDimension() && DimensionManager.getWorld(dimension.id()) == null)
|
||||
{
|
||||
File saveDirectory = new File(DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/pocketDimID" + dimension.id());
|
||||
DeleteFolder.deleteFolder(saveDirectory);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static boolean deleteDimensionData(int dimensionID)
|
||||
{
|
||||
if(dimensionData.containsKey(dimensionID)&& DimensionManager.getWorld(dimensionID) == null)
|
||||
{
|
||||
NewDimData target = PocketManager.getDimensionData(dimensionID);
|
||||
InnerDimData dimension = (InnerDimData) target;
|
||||
|
||||
dimensionData.remove(dimensionID);
|
||||
// Raise the dim deleted event
|
||||
dimWatcher.onDeleted(new ClientDimData(dimension));
|
||||
dimension.clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void registerPockets(DDProperties properties)
|
||||
{
|
||||
for (NewDimData dimension : dimensionData.values())
|
||||
{
|
||||
if (dimension.isPocketDimension())
|
||||
{
|
||||
try
|
||||
{
|
||||
DimensionManager.registerDimension(dimension.id(), properties.PocketProviderID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Could not register pocket dimension #" + dimension.id() + ". Probably caused by a version update/save data corruption/other mods.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void unregisterPockets()
|
||||
{
|
||||
for (NewDimData dimension : dimensionData.values())
|
||||
{
|
||||
if (dimension.isPocketDimension())
|
||||
{
|
||||
try
|
||||
{
|
||||
DimensionManager.unregisterDimension(dimension.id());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("An unexpected error occurred while unregistering pocket dimension #" + dimension.id() + ":");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Integer dimID : dimensionIDBlackList)
|
||||
{
|
||||
try
|
||||
{
|
||||
DimensionManager.unregisterDimension(dimID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("An unexpected error occurred while unregistering blacklisted dim #" + dimID + ":");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* loads the dim data from the saved hashMap. Also handles compatibility with old saves, see OldSaveHandler
|
||||
*/
|
||||
private static void loadInternal()
|
||||
{
|
||||
System.out.println(!FMLCommonHandler.instance().getSide().isClient());
|
||||
|
||||
File saveDir = DimensionManager.getCurrentSaveRootDirectory();
|
||||
if (saveDir != null)
|
||||
{
|
||||
//Try to import data from old DD versions
|
||||
//TODO - remove this code in a few versions
|
||||
File oldSaveData = new File(saveDir+"/DimensionalDoorsData");
|
||||
if(oldSaveData.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Importing old DD save data...");
|
||||
OldSaveImporter.importOldSave(oldSaveData);
|
||||
oldSaveData.delete();
|
||||
|
||||
System.out.println("Import Succesful!");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//TODO handle fail cases
|
||||
System.out.println("Import failed!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Load save data
|
||||
System.out.println("Loading Dimensional Doors save data...");
|
||||
if (DDSaveHandler.loadAll())
|
||||
{
|
||||
System.out.println("Loaded successfully!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void save()
|
||||
{
|
||||
if (!isLoaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
World world = DimensionManager.getWorld(OVERWORLD_DIMENSION_ID);
|
||||
if (world == null || world.isRemote || DimensionManager.getCurrentSaveRootDirectory() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Check this last to make sure we set the flag shortly after.
|
||||
if (isSaving)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isSaving = true;
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Writing Dimensional Doors save data...");
|
||||
if ( DDSaveHandler.saveAll(dimensionData.values(),dimensionIDBlackList) )
|
||||
{
|
||||
System.out.println("Saved successfully!");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Wrap the exception in a RuntimeException so functions that call
|
||||
// PocketManager.save() don't need to catch it. We want MC to
|
||||
// crash if something really bad happens rather than ignoring it!
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isSaving = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static WorldServer loadDimension(int id)
|
||||
{
|
||||
WorldServer world = DimensionManager.getWorld(id);
|
||||
if (world == null)
|
||||
{
|
||||
DimensionManager.initDimension(id);
|
||||
world = DimensionManager.getWorld(id);
|
||||
}
|
||||
else if (world.provider == null)
|
||||
{
|
||||
DimensionManager.initDimension(id);
|
||||
world = DimensionManager.getWorld(id);
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
public static NewDimData registerDimension(World world)
|
||||
{
|
||||
return registerDimension(world.provider.dimensionId, null, false, false);
|
||||
}
|
||||
|
||||
public static NewDimData registerPocket(NewDimData parent, boolean isDungeon)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
throw new IllegalArgumentException("parent cannot be null. A pocket dimension must always have a parent dimension.");
|
||||
}
|
||||
|
||||
DDProperties properties = DDProperties.instance();
|
||||
int dimensionID = DimensionManager.getNextFreeDimId();
|
||||
DimensionManager.registerDimension(dimensionID, properties.PocketProviderID);
|
||||
return registerDimension(dimensionID, (InnerDimData) parent, true, isDungeon);
|
||||
}
|
||||
|
||||
private static NewDimData registerDimension(int dimensionID, InnerDimData parent, boolean isPocket, boolean isDungeon)
|
||||
{
|
||||
if (dimensionData.containsKey(dimensionID))
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot register a dimension with ID = " + dimensionID + " because it has already been registered.");
|
||||
}
|
||||
//TODO blacklist stuff probably should happen here
|
||||
InnerDimData dimension = new InnerDimData(dimensionID, parent, isPocket, isDungeon, linkWatcher);
|
||||
dimensionData.put(dimensionID, dimension);
|
||||
if (!dimension.isPocketDimension())
|
||||
{
|
||||
rootDimensions.add(dimension);
|
||||
}
|
||||
dimWatcher.onCreated(new ClientDimData(dimension));
|
||||
|
||||
return dimension;
|
||||
}
|
||||
|
||||
private static NewDimData registerClientDimension(int dimensionID, int rootID)
|
||||
{
|
||||
// No need to raise events heres since this code should only run on the client side
|
||||
// getDimensionData() always handles root dimensions properly, even if the weren't defined before
|
||||
|
||||
// SenseiKiwi: I'm a little worried about how getDimensionData will raise
|
||||
// an event when it creates any root dimensions... Needs checking later.
|
||||
|
||||
InnerDimData root = (InnerDimData) getDimensionData(rootID);
|
||||
InnerDimData dimension;
|
||||
|
||||
if (rootID != dimensionID)
|
||||
{
|
||||
dimension = dimensionData.get(dimensionID);
|
||||
if (dimension == null)
|
||||
{
|
||||
dimension = new InnerDimData(dimensionID, root);
|
||||
dimensionData.put(dimension.id(), dimension);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dimension = root;
|
||||
}
|
||||
if(dimension.isPocketDimension())
|
||||
{
|
||||
//Im registering pocket dims here. I *think* we can assume that if its a pocket and we are
|
||||
//registering its dim data, we also need to register it with forge.
|
||||
DimensionManager.registerDimension(dimensionID, mod_pocketDim.properties.PocketProviderID);
|
||||
}
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public static NewDimData getDimensionData(World world)
|
||||
{
|
||||
return getDimensionData(world.provider.dimensionId);
|
||||
}
|
||||
|
||||
public static NewDimData getDimensionData(int dimensionID)
|
||||
{
|
||||
//Retrieve the data for a dimension. If we don't have a record for that dimension,
|
||||
//assume it's a non-pocket dimension that hasn't been initialized with us before
|
||||
//and create a NewDimData instance for it.
|
||||
//Any pocket dimension must be listed with PocketManager to have a dimension ID
|
||||
//assigned, so it's safe to assume that any unknown dimensions don't belong to us.
|
||||
|
||||
if(PocketManager.dimensionData == null)
|
||||
{
|
||||
System.out.println("Something odd happend during shutdown");
|
||||
}
|
||||
NewDimData dimension = PocketManager.dimensionData.get(dimensionID);
|
||||
if (dimension == null)
|
||||
{
|
||||
dimension = registerDimension(dimensionID, null, false, false);
|
||||
}
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public static Iterable<? extends NewDimData> getDimensions()
|
||||
{
|
||||
return dimensionData.values();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ArrayList<NewDimData> getRootDimensions()
|
||||
{
|
||||
return (ArrayList<NewDimData>) rootDimensions.clone();
|
||||
}
|
||||
|
||||
public static void unload()
|
||||
{
|
||||
System.out.println("Unloading Pocket Dimensions...");
|
||||
if (!isLoaded)
|
||||
{
|
||||
throw new IllegalStateException("Pocket dimensions have already been unloaded!");
|
||||
}
|
||||
|
||||
save();
|
||||
unregisterPockets();
|
||||
dimensionData = null;
|
||||
rootDimensions = null;
|
||||
isLoaded = false;
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
public static DimLink getLink(int x, int y, int z, World world)
|
||||
{
|
||||
return getLink(x, y, z, world.provider.dimensionId);
|
||||
}
|
||||
|
||||
public static DimLink getLink(Point4D point)
|
||||
{
|
||||
return getLink(point.getX(), point.getY(), point.getZ(), point.getDimension());
|
||||
}
|
||||
|
||||
public static DimLink getLink(int x, int y, int z, int dimensionID)
|
||||
{
|
||||
NewDimData dimension = dimensionData.get(dimensionID);
|
||||
if (dimension != null)
|
||||
{
|
||||
return dimension.getLink(x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBlackListed(int dimensionID)
|
||||
{
|
||||
return PocketManager.dimensionIDBlackList.contains(dimensionID);
|
||||
}
|
||||
public static void registerDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||
{
|
||||
dimWatcher.registerReceiver(watcher);
|
||||
}
|
||||
|
||||
public static boolean unregisterDimWatcher(IUpdateWatcher<ClientDimData> watcher)
|
||||
{
|
||||
return dimWatcher.unregisterReceiver(watcher);
|
||||
}
|
||||
|
||||
public static void registerLinkWatcher(IUpdateWatcher<ClientLinkData> watcher)
|
||||
{
|
||||
linkWatcher.registerReceiver(watcher);
|
||||
}
|
||||
|
||||
public static boolean unregisterLinkWatcher(IUpdateWatcher<ClientLinkData> watcher)
|
||||
{
|
||||
return linkWatcher.unregisterReceiver(watcher);
|
||||
}
|
||||
|
||||
public static void getWatchers(IUpdateSource updateSource)
|
||||
{
|
||||
updateSource.registerWatchers(new ClientDimWatcher(), new ClientLinkWatcher());
|
||||
}
|
||||
|
||||
public static void writePacket(DataOutputStream output) throws IOException
|
||||
{
|
||||
// Write a very compact description of our dimensions and links to be sent to a client
|
||||
Compactor.write(dimensionData.values(), output);
|
||||
}
|
||||
|
||||
public static boolean isRegisteredInternally(int dimensionID)
|
||||
{
|
||||
return dimensionData.containsKey(dimensionID);
|
||||
}
|
||||
|
||||
public static void createAndRegisterBlacklist(List<Integer> blacklist)
|
||||
{
|
||||
//TODO - create a special blacklist provider
|
||||
for(Integer dimID : blacklist)
|
||||
{
|
||||
PocketManager.dimensionIDBlackList.add(dimID);
|
||||
DimensionManager.registerDimension(dimID, DDProperties.instance().PocketProviderID);
|
||||
}
|
||||
}
|
||||
public static void readPacket(DataInputStream input) throws IOException
|
||||
{
|
||||
//TODO- figure out why this is getting called so frequently
|
||||
if (isLoaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (isLoading)
|
||||
{
|
||||
throw new IllegalStateException("Pocket dimensions are already loading!");
|
||||
}
|
||||
// Load compacted client-side dimension data
|
||||
load();
|
||||
Compactor.readDimensions(input, new DimRegistrationCallback());
|
||||
|
||||
// Register pocket dimensions
|
||||
DDProperties properties = DDProperties.instance();
|
||||
|
||||
isLoaded = true;
|
||||
isLoading = false;
|
||||
isConnected = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
||||
|
||||
public class DungeonData
|
||||
{
|
||||
private final int weight;
|
||||
private final boolean isOpen;
|
||||
private final boolean isInternal;
|
||||
private final String schematicPath;
|
||||
private final String schematicName;
|
||||
private final DungeonType dungeonType;
|
||||
|
||||
public DungeonData(String schematicPath, boolean isInternal, DungeonType dungeonType, boolean isOpen, int weight)
|
||||
{
|
||||
this.schematicPath = schematicPath;
|
||||
this.schematicName = getSchematicName(schematicPath);
|
||||
this.dungeonType = dungeonType;
|
||||
this.isInternal = isInternal;
|
||||
this.isOpen = isOpen;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
private static String getSchematicName(String schematicPath)
|
||||
{
|
||||
int indexA = schematicPath.lastIndexOf('\\');
|
||||
int indexB = schematicPath.lastIndexOf('/');
|
||||
indexA = Math.max(indexA, indexB) + 1;
|
||||
|
||||
return schematicPath.substring(indexA, schematicPath.length() - DungeonHelper.SCHEMATIC_FILE_EXTENSION.length());
|
||||
}
|
||||
|
||||
public int weight()
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
|
||||
public boolean isOpen()
|
||||
{
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public boolean isInternal()
|
||||
{
|
||||
return isInternal;
|
||||
}
|
||||
|
||||
public String schematicPath()
|
||||
{
|
||||
return schematicPath;
|
||||
}
|
||||
|
||||
public DungeonType dungeonType()
|
||||
{
|
||||
return dungeonType;
|
||||
}
|
||||
|
||||
public String schematicName()
|
||||
{
|
||||
return schematicName;
|
||||
}
|
||||
|
||||
public DungeonSchematic loadSchematic() throws InvalidSchematicException, FileNotFoundException
|
||||
{
|
||||
if (isInternal)
|
||||
{
|
||||
return DungeonSchematic.readFromResource(schematicPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DungeonSchematic.readFromFile(schematicPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.BlockRotator;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.CompoundFilter;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.ReplacementFilter;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.Schematic;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class DungeonSchematic extends Schematic {
|
||||
|
||||
private static final short MAX_VANILLA_BLOCK_ID = 158;
|
||||
private static final short STANDARD_FABRIC_OF_REALITY_ID = 1973;
|
||||
private static final short STANDARD_ETERNAL_FABRIC_ID = 220;
|
||||
private static final short STANDARD_WARP_DOOR_ID = 1975;
|
||||
private static final short STANDARD_DIMENSIONAL_DOOR_ID = 1970;
|
||||
private static final short MONOLITH_SPAWN_MARKER_ID = (short) Block.endPortalFrame.blockID;
|
||||
private static final short EXIT_DOOR_MARKER_ID = (short) Block.sandStone.blockID;
|
||||
|
||||
private int orientation;
|
||||
private Point3D entranceDoorLocation;
|
||||
private ArrayList<Point3D> exitDoorLocations;
|
||||
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||
private ArrayList<Point3D> monolithSpawnLocations;
|
||||
|
||||
private static final short[] MOD_BLOCK_FILTER_EXCEPTIONS = new short[] {
|
||||
STANDARD_FABRIC_OF_REALITY_ID,
|
||||
STANDARD_ETERNAL_FABRIC_ID,
|
||||
STANDARD_WARP_DOOR_ID,
|
||||
STANDARD_DIMENSIONAL_DOOR_ID
|
||||
};
|
||||
|
||||
private DungeonSchematic(Schematic source)
|
||||
{
|
||||
super(source);
|
||||
}
|
||||
|
||||
public int getOrientation()
|
||||
{
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public Point3D getEntranceDoorLocation()
|
||||
{
|
||||
return entranceDoorLocation.clone();
|
||||
}
|
||||
|
||||
private DungeonSchematic()
|
||||
{
|
||||
//Used to create a dummy instance for readFromResource()
|
||||
super((short) 0, (short) 0, (short) 0, null, null, null);
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
return readFromFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
// TODO: fix resource leak
|
||||
return readFromStream(new FileInputStream(schematicFile));
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromResource(String resourcePath) throws InvalidSchematicException
|
||||
{
|
||||
//We need an instance of a class in the mod to retrieve a resource
|
||||
DungeonSchematic empty = new DungeonSchematic();
|
||||
InputStream schematicStream = empty.getClass().getResourceAsStream(resourcePath);
|
||||
return readFromStream(schematicStream);
|
||||
}
|
||||
|
||||
public static DungeonSchematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
||||
{
|
||||
return new DungeonSchematic(Schematic.readFromStream(schematicStream));
|
||||
}
|
||||
|
||||
public void applyImportFilters(DDProperties properties)
|
||||
{
|
||||
//Search for special blocks (warp doors, dim doors, and end portal frames that mark Monolith spawn points)
|
||||
SpecialBlockFinder finder = new SpecialBlockFinder(STANDARD_WARP_DOOR_ID, STANDARD_DIMENSIONAL_DOOR_ID,
|
||||
MONOLITH_SPAWN_MARKER_ID, EXIT_DOOR_MARKER_ID);
|
||||
applyFilter(finder);
|
||||
|
||||
//Flip the entrance's orientation to get the dungeon's orientation
|
||||
orientation = BlockRotator.transformMetadata(finder.getEntranceOrientation(), 2, Block.doorWood.blockID);
|
||||
|
||||
entranceDoorLocation = finder.getEntranceDoorLocation();
|
||||
exitDoorLocations = finder.getExitDoorLocations();
|
||||
dimensionalDoorLocations = finder.getDimensionalDoorLocations();
|
||||
monolithSpawnLocations = finder.getMonolithSpawnLocations();
|
||||
|
||||
//Filter out mod blocks except some of our own
|
||||
CompoundFilter standardizer = new CompoundFilter();
|
||||
standardizer.addFilter(new ModBlockFilter(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS,
|
||||
(short) properties.FabricBlockID, (byte) 0));
|
||||
|
||||
//Also convert standard DD block IDs to local versions
|
||||
Map<Short, Short> mapping = getAssignedToStandardIDMapping(properties);
|
||||
|
||||
for (Entry<Short, Short> entry : mapping.entrySet())
|
||||
{
|
||||
if (entry.getKey() != entry.getValue())
|
||||
{
|
||||
standardizer.addFilter(new ReplacementFilter(entry.getValue(), entry.getKey()));
|
||||
}
|
||||
}
|
||||
applyFilter(standardizer);
|
||||
}
|
||||
|
||||
public void applyExportFilters(DDProperties properties)
|
||||
{
|
||||
//Check if some block IDs assigned by Forge differ from our standard IDs
|
||||
//If so, change the IDs to standard values
|
||||
CompoundFilter standardizer = new CompoundFilter();
|
||||
Map<Short, Short> mapping = getAssignedToStandardIDMapping(properties);
|
||||
|
||||
for (Entry<Short, Short> entry : mapping.entrySet())
|
||||
{
|
||||
if (entry.getKey() != entry.getValue())
|
||||
{
|
||||
standardizer.addFilter(new ReplacementFilter(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
//Filter out mod blocks except some of our own
|
||||
//This comes after ID standardization because the mod block filter relies on standardized IDs
|
||||
standardizer.addFilter(new ModBlockFilter(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS,
|
||||
STANDARD_FABRIC_OF_REALITY_ID, (byte) 0));
|
||||
|
||||
applyFilter(standardizer);
|
||||
}
|
||||
|
||||
private Map<Short, Short> getAssignedToStandardIDMapping(DDProperties properties)
|
||||
{
|
||||
//If we ever need this broadly or support other mods, this should be moved to a separate class
|
||||
TreeMap<Short, Short> mapping = new TreeMap<Short, Short>();
|
||||
mapping.put((short) properties.FabricBlockID, STANDARD_FABRIC_OF_REALITY_ID);
|
||||
mapping.put((short) properties.PermaFabricBlockID, STANDARD_ETERNAL_FABRIC_ID);
|
||||
mapping.put((short) properties.WarpDoorID, STANDARD_WARP_DOOR_ID);
|
||||
mapping.put((short) properties.DimensionalDoorID, STANDARD_DIMENSIONAL_DOOR_ID);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public static DungeonSchematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length, boolean doCompactBounds)
|
||||
{
|
||||
return new DungeonSchematic(Schematic.copyFromWorld(world, x, y, z, width, height, length, doCompactBounds));
|
||||
}
|
||||
|
||||
public void copyToWorld(World world, Point3D pocketCenter, int targetOrientation, DimLink entryLink, Random random)
|
||||
{
|
||||
//TODO: This function is an improvised solution so we can get the release moving. In the future,
|
||||
//we should generalize block transformations and implement support for them at the level of Schematic,
|
||||
//then just use that support from DungeonSchematic instead of making this local fix.
|
||||
//It might be easiest to support transformations using a WorldOperation
|
||||
|
||||
final int turnAngle = targetOrientation - this.orientation;
|
||||
|
||||
int index;
|
||||
int count;
|
||||
int blockID;
|
||||
int blockMeta;
|
||||
int dx, dy, dz;
|
||||
Point3D pocketPoint = new Point3D(0, 0, 0);
|
||||
|
||||
//Copy blocks and metadata into the world
|
||||
index = 0;
|
||||
for (dy = 0; dy < height; dy++)
|
||||
{
|
||||
for (dz = 0; dz < length; dz++)
|
||||
{
|
||||
for (dx = 0; dx < width; dx++)
|
||||
{
|
||||
pocketPoint.setX(dx);
|
||||
pocketPoint.setY(dy);
|
||||
pocketPoint.setZ(dz);
|
||||
blockID = blocks[index];
|
||||
BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter);
|
||||
blockMeta = BlockRotator.transformMetadata(metadata[index], turnAngle, blockID);
|
||||
|
||||
//In the future, we might want to make this more efficient by building whole chunks at a time
|
||||
setBlockDirectly(world, pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), blockID, blockMeta);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Copy tile entities into the world
|
||||
count = tileEntities.tagCount();
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
NBTTagCompound tileTag = (NBTTagCompound) tileEntities.tagAt(index);
|
||||
//Rewrite its location to be in world coordinates
|
||||
pocketPoint.setX(tileTag.getInteger("x"));
|
||||
pocketPoint.setY(tileTag.getInteger("y"));
|
||||
pocketPoint.setZ(tileTag.getInteger("z"));
|
||||
BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter);
|
||||
tileTag.setInteger("x", pocketPoint.getX());
|
||||
tileTag.setInteger("y", pocketPoint.getY());
|
||||
tileTag.setInteger("z", pocketPoint.getZ());
|
||||
//Load the tile entity and put it in the world
|
||||
world.setBlockTileEntity(pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), TileEntity.createAndLoadEntity(tileTag));
|
||||
}
|
||||
|
||||
setUpDungeon(PocketManager.getDimensionData(world), world, pocketCenter, turnAngle, entryLink, random);
|
||||
}
|
||||
|
||||
private void setUpDungeon(NewDimData dimension, World world, Point3D pocketCenter, int turnAngle, DimLink entryLink, Random random)
|
||||
{
|
||||
//Transform dungeon corners
|
||||
Point3D minCorner = new Point3D(0, 0, 0);
|
||||
Point3D maxCorner = new Point3D(width - 1, height - 1, length - 1);
|
||||
transformCorners(entranceDoorLocation, pocketCenter, turnAngle, minCorner, maxCorner);
|
||||
|
||||
//Fill empty chests and dispensers
|
||||
FillContainersOperation filler = new FillContainersOperation(random);
|
||||
filler.apply(world, minCorner, maxCorner);
|
||||
|
||||
//Set up entrance door rift
|
||||
createEntranceReverseLink(dimension, pocketCenter, entryLink, world);
|
||||
|
||||
//Set up link data for dimensional doors
|
||||
for (Point3D location : dimensionalDoorLocations)
|
||||
{
|
||||
createDimensionalDoorLink(dimension, location, entranceDoorLocation, turnAngle, pocketCenter,world);
|
||||
}
|
||||
|
||||
//Set up link data for exit door
|
||||
for (Point3D location : exitDoorLocations)
|
||||
{
|
||||
createExitDoorLink(world, dimension, location, entranceDoorLocation, turnAngle, pocketCenter);
|
||||
}
|
||||
|
||||
//Remove end portal frames and spawn Monoliths, if allowed
|
||||
boolean canSpawn = MonolithSpawner.isMobSpawningAllowed();
|
||||
for (Point3D location : monolithSpawnLocations)
|
||||
{
|
||||
spawnMonolith(world, location, entranceDoorLocation, turnAngle, pocketCenter, canSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
private static void transformCorners(Point3D schematicEntrance, Point3D pocketCenter, int turnAngle, Point3D minCorner, Point3D maxCorner)
|
||||
{
|
||||
int temp;
|
||||
BlockRotator.transformPoint(minCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||
BlockRotator.transformPoint(maxCorner, schematicEntrance, turnAngle, pocketCenter);
|
||||
if (minCorner.getX() > maxCorner.getX())
|
||||
{
|
||||
temp = minCorner.getX();
|
||||
minCorner.setX(maxCorner.getX());
|
||||
maxCorner.setX(temp);
|
||||
}
|
||||
if (minCorner.getY() > maxCorner.getY())
|
||||
{
|
||||
temp = minCorner.getY();
|
||||
minCorner.setY(maxCorner.getY());
|
||||
maxCorner.setY(temp);
|
||||
}
|
||||
if (minCorner.getZ() > maxCorner.getZ())
|
||||
{
|
||||
temp = minCorner.getZ();
|
||||
minCorner.setZ(maxCorner.getZ());
|
||||
maxCorner.setZ(temp);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createEntranceReverseLink(NewDimData dimension, Point3D pocketCenter, DimLink entryLink,World world)
|
||||
{
|
||||
int orientation = world.getBlockMetadata(pocketCenter.getX(), pocketCenter.getY()-1, pocketCenter.getZ());
|
||||
DimLink reverseLink = dimension.createLink(pocketCenter.getX(), pocketCenter.getY(), pocketCenter.getZ(), LinkTypes.REVERSE,orientation);
|
||||
Point4D destination = entryLink.source();
|
||||
NewDimData prevDim = PocketManager.getDimensionData(destination.getDimension());
|
||||
prevDim.setDestination(reverseLink, destination.getX(), destination.getY(), destination.getZ());
|
||||
}
|
||||
|
||||
private static void createExitDoorLink(World world, NewDimData dimension, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter)
|
||||
{
|
||||
|
||||
//Transform the door's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
int orientation = world.getBlockMetadata(location.getX(), location.getY()-1, location.getZ());
|
||||
dimension.createLink(location.getX(), location.getY(), location.getZ(), LinkTypes.DUNGEON_EXIT,orientation);
|
||||
//Replace the sandstone block under the exit door with the same block as the one underneath it
|
||||
int x = location.getX();
|
||||
int y = location.getY() - 3;
|
||||
int z = location.getZ();
|
||||
if (y >= 0)
|
||||
{
|
||||
int blockID = world.getBlockId(x, y, z);
|
||||
int metadata = world.getBlockMetadata(x, y, z);
|
||||
setBlockDirectly(world, x, y + 1, z, blockID, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createDimensionalDoorLink(NewDimData dimension, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter,World world)
|
||||
{
|
||||
//Transform the door's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
int orientation = world.getBlockMetadata(location.getX(), location.getY()-1, location.getZ());
|
||||
|
||||
dimension.createLink(location.getX(), location.getY(), location.getZ(), LinkTypes.DUNGEON,orientation);
|
||||
}
|
||||
|
||||
private static void spawnMonolith(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, boolean canSpawn)
|
||||
{
|
||||
//Transform the frame block's location to the pocket coordinate system
|
||||
Point3D location = point.clone();
|
||||
BlockRotator.transformPoint(location, entrance, rotation, pocketCenter);
|
||||
//Remove frame block
|
||||
setBlockDirectly(world, location.getX(), location.getY(), location.getZ(), 0, 0);
|
||||
//Spawn Monolith
|
||||
if (canSpawn)
|
||||
{
|
||||
Entity mob = new MobMonolith(world);
|
||||
mob.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), 1, 1);
|
||||
world.spawnEntityInWorld(mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockContainer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityChest;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDLoot;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.WorldOperation;
|
||||
|
||||
public class FillContainersOperation extends WorldOperation
|
||||
{
|
||||
private Random random;
|
||||
|
||||
public FillContainersOperation(Random random)
|
||||
{
|
||||
super("FillContainersOperation");
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||
{
|
||||
int blockID = world.getBlockId(x, y, z);
|
||||
|
||||
//Fill empty chests and dispensers
|
||||
if (Block.blocksList[blockID] instanceof BlockContainer)
|
||||
{
|
||||
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
|
||||
|
||||
//Fill chests
|
||||
if (tileEntity instanceof TileEntityChest)
|
||||
{
|
||||
TileEntityChest chest = (TileEntityChest) tileEntity;
|
||||
if (isInventoryEmpty(chest))
|
||||
{
|
||||
DDLoot.generateChestContents(DDLoot.DungeonChestInfo, chest, random);
|
||||
}
|
||||
}
|
||||
|
||||
//Fill dispensers
|
||||
if (tileEntity instanceof TileEntityDispenser)
|
||||
{
|
||||
TileEntityDispenser dispenser = (TileEntityDispenser) tileEntity;
|
||||
if (isInventoryEmpty(dispenser))
|
||||
{
|
||||
dispenser.addItem(new ItemStack(Item.arrow, 64));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isInventoryEmpty(IInventory inventory)
|
||||
{
|
||||
int size = inventory.getSizeInventory();
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
if (inventory.getStackInSlot(index) != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.SchematicFilter;
|
||||
|
||||
public class ModBlockFilter extends SchematicFilter {
|
||||
|
||||
private short maxVanillaBlockID;
|
||||
private short[] exceptions;
|
||||
private short replacementBlockID;
|
||||
private byte replacementMetadata;
|
||||
|
||||
public ModBlockFilter(short maxVanillaBlockID, short[] exceptions, short replacementBlockID, byte replacementMetadata)
|
||||
{
|
||||
super("ModBlockFilter");
|
||||
this.maxVanillaBlockID = maxVanillaBlockID;
|
||||
this.exceptions = exceptions;
|
||||
this.replacementBlockID = replacementBlockID;
|
||||
this.replacementMetadata = replacementMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||
{
|
||||
int k;
|
||||
short currentID = blocks[index];
|
||||
if (currentID > maxVanillaBlockID || (currentID != 0 && Block.blocksList[currentID] == null))
|
||||
{
|
||||
//This might be a mod block. Check if an exception exists.
|
||||
for (k = 0; k < exceptions.length; k++)
|
||||
{
|
||||
if (currentID == exceptions[k])
|
||||
{
|
||||
//Exception found, not considered a mod block
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//No matching exception found. Replace the block.
|
||||
blocks[index] = replacementBlockID;
|
||||
metadata[index] = replacementMetadata;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean terminates()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.Schematic;
|
||||
import StevenDimDoors.mod_pocketDim.schematic.SchematicFilter;
|
||||
|
||||
public class SpecialBlockFinder extends SchematicFilter {
|
||||
|
||||
private short warpDoorID;
|
||||
private short dimensionalDoorID;
|
||||
private short monolithSpawnMarkerID;
|
||||
private short exitMarkerID;
|
||||
private int entranceOrientation;
|
||||
private Schematic schematic;
|
||||
private Point3D entranceDoorLocation;
|
||||
private ArrayList<Point3D> exitDoorLocations;
|
||||
private ArrayList<Point3D> dimensionalDoorLocations;
|
||||
private ArrayList<Point3D> monolithSpawnLocations;
|
||||
|
||||
public SpecialBlockFinder(short warpDoorID, short dimensionalDoorID, short monolithSpawnMarkerID, short exitMarkerID)
|
||||
{
|
||||
super("SpecialBlockFinder");
|
||||
this.warpDoorID = warpDoorID;
|
||||
this.dimensionalDoorID = dimensionalDoorID;
|
||||
this.monolithSpawnMarkerID = monolithSpawnMarkerID;
|
||||
this.exitMarkerID = exitMarkerID;
|
||||
this.entranceDoorLocation = null;
|
||||
this.entranceOrientation = 0;
|
||||
this.exitDoorLocations = new ArrayList<Point3D>();
|
||||
this.dimensionalDoorLocations = new ArrayList<Point3D>();
|
||||
this.monolithSpawnLocations = new ArrayList<Point3D>();
|
||||
this.schematic = null;
|
||||
}
|
||||
|
||||
public int getEntranceOrientation() {
|
||||
return entranceOrientation;
|
||||
}
|
||||
|
||||
public Point3D getEntranceDoorLocation() {
|
||||
return entranceDoorLocation;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getExitDoorLocations() {
|
||||
return exitDoorLocations;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getDimensionalDoorLocations() {
|
||||
return dimensionalDoorLocations;
|
||||
}
|
||||
|
||||
public ArrayList<Point3D> getMonolithSpawnLocations() {
|
||||
return monolithSpawnLocations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||
{
|
||||
this.schematic = schematic;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||
{
|
||||
int indexBelow;
|
||||
int indexDoubleBelow;
|
||||
|
||||
if (blocks[index] == monolithSpawnMarkerID)
|
||||
{
|
||||
monolithSpawnLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
if (blocks[index] == dimensionalDoorID)
|
||||
{
|
||||
indexBelow = schematic.calculateIndexBelow(index);
|
||||
if (indexBelow >= 0 && blocks[indexBelow] == dimensionalDoorID)
|
||||
{
|
||||
dimensionalDoorLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (blocks[index] == warpDoorID)
|
||||
{
|
||||
indexBelow = schematic.calculateIndexBelow(index);
|
||||
if (indexBelow >= 0 && blocks[indexBelow] == warpDoorID)
|
||||
{
|
||||
indexDoubleBelow = schematic.calculateIndexBelow(indexBelow);
|
||||
if (indexDoubleBelow >= 0 && blocks[indexDoubleBelow] == exitMarkerID)
|
||||
{
|
||||
exitDoorLocations.add(schematic.calculatePoint(index));
|
||||
return true;
|
||||
}
|
||||
else if (entranceDoorLocation == null)
|
||||
{
|
||||
entranceDoorLocation = schematic.calculatePoint(index);
|
||||
entranceOrientation = (metadata[indexBelow] & 3);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean terminates()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||
|
||||
public class DungeonChainRule
|
||||
{
|
||||
private final int[] condition;
|
||||
private final ArrayList<WeightedContainer<DungeonType>> products;
|
||||
|
||||
public DungeonChainRule(DungeonChainRuleDefinition source, HashMap<String, DungeonType> nameToTypeMapping)
|
||||
{
|
||||
ArrayList<String> conditionNames = source.getCondition();
|
||||
ArrayList<WeightedContainer<String>> productNames = source.getProducts();
|
||||
|
||||
//Validate the data, just in case
|
||||
if (conditionNames == null)
|
||||
{
|
||||
throw new NullPointerException("source cannot have null conditions");
|
||||
}
|
||||
if (productNames == null)
|
||||
{
|
||||
throw new NullPointerException("source cannot have null products");
|
||||
}
|
||||
if (productNames.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("products cannot be an empty list");
|
||||
}
|
||||
for (WeightedContainer<String> product : productNames)
|
||||
{
|
||||
//Check for weights less than 1. Those could cause Minecraft's random selection algorithm to throw an exception.
|
||||
//At the very least, they're useless values.
|
||||
if (product.itemWeight < 1)
|
||||
{
|
||||
throw new IllegalArgumentException("products cannot contain items with weights less than 1");
|
||||
}
|
||||
}
|
||||
|
||||
//Obtain the IDs of dungeon types in reverse order. Reverse order makes comparing against chain histories easy.
|
||||
condition = new int[conditionNames.size()];
|
||||
for (int src = 0, dst = condition.length - 1; src < condition.length; src++, dst--)
|
||||
{
|
||||
condition[dst] = nameToTypeMapping.get(conditionNames.get(src)).ID;
|
||||
}
|
||||
products = new ArrayList<WeightedContainer<DungeonType>>(productNames.size());
|
||||
for (WeightedContainer<String> product : productNames)
|
||||
{
|
||||
products.add(new WeightedContainer<DungeonType>(nameToTypeMapping.get(product.getData()), product.itemWeight ));
|
||||
}
|
||||
}
|
||||
|
||||
public int length()
|
||||
{
|
||||
return condition.length;
|
||||
}
|
||||
|
||||
public boolean evaluate(int[] typeHistory)
|
||||
{
|
||||
if (typeHistory.length >= condition.length)
|
||||
{
|
||||
for (int k = 0; k < condition.length; k++)
|
||||
{
|
||||
if (condition[k] != 0 && typeHistory[k] != condition[k])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<WeightedContainer<DungeonType>> products()
|
||||
{
|
||||
//Create a deep copy of the internal list of products. That way, if the list is modified externally,
|
||||
//it won't affect the reference copy inside this rule.
|
||||
ArrayList<WeightedContainer<DungeonType>> copy = new ArrayList<WeightedContainer<DungeonType>>(products.size());
|
||||
for (WeightedContainer<DungeonType> container : products)
|
||||
{
|
||||
copy.add(container.clone());
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||
|
||||
public class DungeonChainRuleDefinition
|
||||
{
|
||||
private ArrayList<String> conditions;
|
||||
private ArrayList<WeightedContainer<String>> products;
|
||||
|
||||
public DungeonChainRuleDefinition(ArrayList<String> conditions, ArrayList<WeightedContainer<String>> products)
|
||||
{
|
||||
//Validate the arguments, just in case
|
||||
if (conditions == null)
|
||||
{
|
||||
throw new NullPointerException("conditions cannot be null");
|
||||
}
|
||||
if (products.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("products cannot be an empty list");
|
||||
}
|
||||
for (WeightedContainer<String> product : products)
|
||||
{
|
||||
//Check for weights less than 1. Those could cause Minecraft's random selection algorithm to throw an exception.
|
||||
//At the very least, they're useless values.
|
||||
if (product.itemWeight < 1)
|
||||
{
|
||||
throw new IllegalArgumentException("products cannot contain items with weights less than 1");
|
||||
}
|
||||
}
|
||||
|
||||
this.conditions = conditions;
|
||||
this.products = products;
|
||||
}
|
||||
|
||||
public ArrayList<String> getCondition()
|
||||
{
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public ArrayList<WeightedContainer<String>> getProducts()
|
||||
{
|
||||
return products;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.util.WeightedRandom;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||
|
||||
public class DungeonPack
|
||||
{
|
||||
//There is no precaution against having a dungeon type removed from a config file after dungeons of that type
|
||||
//have been generated. That would likely cause one or two problems. It's hard to guard against when I don't know
|
||||
//what the save format will be like completely. How should this class behave if it finds a "disowned" type?
|
||||
//The ID numbers would be a problem since it couldn't have a valid number, since it wasn't initialized by the pack instance.
|
||||
//FIXME: Do not release this code as an update without dealing with disowned types!
|
||||
|
||||
private static final int MAX_HISTORY_LENGTH = 30;
|
||||
|
||||
private final String name;
|
||||
private final HashMap<String, DungeonType> nameToTypeMapping;
|
||||
private final ArrayList<ArrayList<DungeonData>> groupedDungeons;
|
||||
private final ArrayList<DungeonData> allDungeons;
|
||||
private final DungeonPackConfig config;
|
||||
private final int maxRuleLength;
|
||||
private final ArrayList<DungeonChainRule> rules;
|
||||
|
||||
public DungeonPack(DungeonPackConfig config)
|
||||
{
|
||||
config.validate();
|
||||
this.config = config.clone(); //Store a clone of the config so that the caller can't change it externally later
|
||||
this.name = config.getName();
|
||||
|
||||
int index;
|
||||
int maxLength = 0;
|
||||
int typeCount = config.getTypeNames().size();
|
||||
this.allDungeons = new ArrayList<DungeonData>();
|
||||
this.nameToTypeMapping = new HashMap<String, DungeonType>(typeCount);
|
||||
this.groupedDungeons = new ArrayList<ArrayList<DungeonData>>(typeCount);
|
||||
|
||||
this.groupedDungeons.add(allDungeons); //Make sure the list of all dungeons is placed at index 0
|
||||
this.nameToTypeMapping.put(DungeonType.WILDCARD_TYPE.Name, DungeonType.WILDCARD_TYPE);
|
||||
|
||||
index = 1;
|
||||
for (String typeName : config.getTypeNames())
|
||||
{
|
||||
String standardName = typeName.toUpperCase();
|
||||
this.nameToTypeMapping.put(standardName, new DungeonType(this, standardName, index));
|
||||
this.groupedDungeons.add(new ArrayList<DungeonData>());
|
||||
index++;
|
||||
}
|
||||
|
||||
//Construct optimized rules from definitions
|
||||
ArrayList<DungeonChainRuleDefinition> definitions = config.getRules();
|
||||
this.rules = new ArrayList<DungeonChainRule>(definitions.size());
|
||||
for (DungeonChainRuleDefinition definition : definitions)
|
||||
{
|
||||
DungeonChainRule rule = new DungeonChainRule(definition, nameToTypeMapping);
|
||||
this.rules.add(rule);
|
||||
if (maxLength < rule.length())
|
||||
{
|
||||
maxLength = rule.length();
|
||||
}
|
||||
}
|
||||
this.maxRuleLength = maxLength;
|
||||
|
||||
//Remove unnecessary references to save a little memory - we won't need them here
|
||||
this.config.setRules(null);
|
||||
this.config.setTypeNames(null);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public DungeonPackConfig getConfig()
|
||||
{
|
||||
return config.clone();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return allDungeons.isEmpty();
|
||||
}
|
||||
|
||||
public DungeonType getType(String typeName)
|
||||
{
|
||||
DungeonType result = nameToTypeMapping.get(typeName.toUpperCase());
|
||||
if (result.Owner == this) //Filter out the wildcard dungeon type
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isKnownType(String typeName)
|
||||
{
|
||||
return (this.getType(typeName) != null);
|
||||
}
|
||||
|
||||
public void addDungeon(DungeonData dungeon)
|
||||
{
|
||||
//Make sure this dungeon really belongs in this pack
|
||||
DungeonType type = dungeon.dungeonType();
|
||||
if (type.Owner == this)
|
||||
{
|
||||
allDungeons.add(dungeon);
|
||||
groupedDungeons.get(type.ID).add(dungeon);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("The dungeon type of generator must belong to this instance of DungeonPack.");
|
||||
}
|
||||
}
|
||||
|
||||
public DungeonData getNextDungeon(NewDimData dimension, Random random)
|
||||
{
|
||||
if (allDungeons.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//Retrieve a list of the previous dungeons in this chain.
|
||||
//If we're not going to check for duplicates in chains, restrict the length of the history to the length
|
||||
//of the longest rule we have. Getting any more data would be useless. This optimization could be significant
|
||||
//for dungeon packs that can extend arbitrarily deep. We should probably set a reasonable limit anyway.
|
||||
|
||||
int maxSearchLength = config.allowDuplicatesInChain() ? maxRuleLength : MAX_HISTORY_LENGTH;
|
||||
ArrayList<DungeonData> history = DungeonHelper.getDungeonChainHistory(dimension.parent(), this, maxSearchLength);
|
||||
return getNextDungeon(history, random);
|
||||
}
|
||||
|
||||
private DungeonData getNextDungeon(ArrayList<DungeonData> history, Random random)
|
||||
{
|
||||
//Extract the dungeon types that have been used from history and convert them into an array of IDs
|
||||
int index;
|
||||
int[] typeHistory = new int[history.size()];
|
||||
HashSet<DungeonData> excludedDungeons = null;
|
||||
for (index = 0; index < typeHistory.length; index++)
|
||||
{
|
||||
typeHistory[index] = history.get(index).dungeonType().ID;
|
||||
}
|
||||
|
||||
for (DungeonChainRule rule : rules)
|
||||
{
|
||||
if (rule.evaluate(typeHistory))
|
||||
{
|
||||
//Pick a random dungeon type to be generated next based on the rule's products
|
||||
ArrayList<WeightedContainer<DungeonType>> products = rule.products();
|
||||
DungeonType nextType;
|
||||
do
|
||||
{
|
||||
nextType = getRandomDungeonType(random, products, groupedDungeons);
|
||||
if (nextType != null)
|
||||
{
|
||||
//Initialize the set of excluded dungeons if needed
|
||||
if (excludedDungeons == null && !config.allowDuplicatesInChain())
|
||||
{
|
||||
excludedDungeons = new HashSet<DungeonData>(history);
|
||||
}
|
||||
|
||||
//List which dungeons are allowed
|
||||
ArrayList<DungeonData> candidates;
|
||||
ArrayList<DungeonData> group = groupedDungeons.get(nextType.ID);
|
||||
if (excludedDungeons != null && !excludedDungeons.isEmpty())
|
||||
{
|
||||
candidates = new ArrayList<DungeonData>(group.size());
|
||||
for (DungeonData dungeon : group)
|
||||
{
|
||||
if (!excludedDungeons.contains(dungeon))
|
||||
{
|
||||
candidates.add(dungeon);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
candidates = group;
|
||||
}
|
||||
if (!candidates.isEmpty())
|
||||
{
|
||||
return getRandomDungeon(random, candidates);
|
||||
}
|
||||
//If we've reached this point, then a dungeon was not selected. Discard the type and try again.
|
||||
products.remove(nextType);
|
||||
}
|
||||
}
|
||||
while (nextType != null);
|
||||
}
|
||||
}
|
||||
|
||||
//None of the rules were applicable. Simply return a random dungeon.
|
||||
return getRandomDungeon(random);
|
||||
}
|
||||
|
||||
public DungeonData getRandomDungeon(Random random)
|
||||
{
|
||||
if (!allDungeons.isEmpty())
|
||||
{
|
||||
return getRandomDungeon(random, allDungeons);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static DungeonType getRandomDungeonType(Random random, Collection<WeightedContainer<DungeonType>> types,
|
||||
ArrayList<ArrayList<DungeonData>> groupedDungeons)
|
||||
{
|
||||
//TODO: Make this faster? This algorithm runs in quadratic time in the worst case because of the random-selection
|
||||
//process and the removal search. Might be okay for normal use, though. ~SenseiKiwi
|
||||
|
||||
//Pick a random dungeon type based on weights. Repeat this process until a non-empty group is found or all groups are checked.
|
||||
while (!types.isEmpty())
|
||||
{
|
||||
//Pick a random dungeon type
|
||||
@SuppressWarnings("unchecked")
|
||||
WeightedContainer<DungeonType> resultContainer = (WeightedContainer<DungeonType>) WeightedRandom.getRandomItem(random, types);
|
||||
|
||||
//Check if there are any dungeons of that type
|
||||
DungeonType selectedType = resultContainer.getData();
|
||||
if (!groupedDungeons.get(selectedType.ID).isEmpty())
|
||||
{
|
||||
//Choose this type
|
||||
return selectedType;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We can't use this type because there are no dungeons of this type
|
||||
//Remove it from the list of types and try again
|
||||
types.remove(resultContainer);
|
||||
}
|
||||
}
|
||||
|
||||
//We have run out of types to try
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DungeonData getRandomDungeon(Random random, Collection<DungeonData> dungeons)
|
||||
{
|
||||
//Use Minecraft's WeightedRandom to select our dungeon. =D
|
||||
ArrayList<WeightedContainer<DungeonData>> weights =
|
||||
new ArrayList<WeightedContainer<DungeonData>>(dungeons.size());
|
||||
for (DungeonData dungeon : dungeons)
|
||||
{
|
||||
weights.add(new WeightedContainer<DungeonData>(dungeon, dungeon.weight()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
WeightedContainer<DungeonData> resultContainer = (WeightedContainer<DungeonData>) WeightedRandom.getRandomItem(random, weights);
|
||||
return (resultContainer != null) ? resultContainer.getData() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DungeonPackConfig
|
||||
{
|
||||
private String name;
|
||||
private ArrayList<String> typeNames;
|
||||
private boolean allowDuplicatesInChain;
|
||||
private boolean allowPackChangeIn;
|
||||
private boolean allowPackChangeOut;
|
||||
private boolean distortDoorCoordinates;
|
||||
private int packWeight;
|
||||
private ArrayList<DungeonChainRuleDefinition> rules;
|
||||
|
||||
public DungeonPackConfig() { }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DungeonPackConfig(DungeonPackConfig source)
|
||||
{
|
||||
this.name = (source.name != null) ? source.name : null;
|
||||
this.typeNames = (source.typeNames != null) ? (ArrayList<String>) source.typeNames.clone() : null;
|
||||
this.allowDuplicatesInChain = source.allowDuplicatesInChain;
|
||||
this.allowPackChangeIn = source.allowPackChangeIn;
|
||||
this.allowPackChangeOut = source.allowPackChangeOut;
|
||||
this.distortDoorCoordinates = source.distortDoorCoordinates;
|
||||
this.packWeight = source.packWeight;
|
||||
this.rules = (source.rules != null) ? (ArrayList<DungeonChainRuleDefinition>) source.rules.clone() : null;
|
||||
}
|
||||
|
||||
public void validate()
|
||||
{
|
||||
if (this.name == null)
|
||||
throw new NullPointerException("name cannot be null");
|
||||
if (this.typeNames == null)
|
||||
throw new NullPointerException("typeNames cannot be null");
|
||||
if (this.rules == null)
|
||||
throw new NullPointerException("rules cannot be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DungeonPackConfig clone()
|
||||
{
|
||||
return new DungeonPackConfig(this);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ArrayList<String> getTypeNames()
|
||||
{
|
||||
return typeNames;
|
||||
}
|
||||
|
||||
public void setTypeNames(ArrayList<String> typeNames)
|
||||
{
|
||||
this.typeNames = typeNames;
|
||||
}
|
||||
|
||||
public boolean allowDuplicatesInChain()
|
||||
{
|
||||
return allowDuplicatesInChain;
|
||||
}
|
||||
|
||||
public void setAllowDuplicatesInChain(boolean value)
|
||||
{
|
||||
allowDuplicatesInChain = value;
|
||||
}
|
||||
|
||||
public void setRules(ArrayList<DungeonChainRuleDefinition> rules)
|
||||
{
|
||||
this.rules = rules;
|
||||
}
|
||||
|
||||
public ArrayList<DungeonChainRuleDefinition> getRules()
|
||||
{
|
||||
return rules;
|
||||
}
|
||||
|
||||
public boolean allowPackChangeIn()
|
||||
{
|
||||
return allowPackChangeIn;
|
||||
}
|
||||
|
||||
public void setAllowPackChangeIn(boolean value)
|
||||
{
|
||||
this.allowPackChangeIn = value;
|
||||
}
|
||||
|
||||
public boolean allowPackChangeOut()
|
||||
{
|
||||
return allowPackChangeOut;
|
||||
}
|
||||
|
||||
public void setAllowPackChangeOut(boolean value)
|
||||
{
|
||||
this.allowPackChangeOut = value;
|
||||
}
|
||||
|
||||
public int getPackWeight()
|
||||
{
|
||||
return packWeight;
|
||||
}
|
||||
|
||||
public void setPackWeight(int packWeight)
|
||||
{
|
||||
this.packWeight = packWeight;
|
||||
}
|
||||
|
||||
public boolean doDistortDoorCoordinates()
|
||||
{
|
||||
return distortDoorCoordinates;
|
||||
}
|
||||
|
||||
public void setDistortDoorCoordinates(boolean value)
|
||||
{
|
||||
this.distortDoorCoordinates = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.BaseConfigurationProcessor;
|
||||
import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException;
|
||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
public class DungeonPackConfigReader extends BaseConfigurationProcessor<DungeonPackConfig>
|
||||
{
|
||||
private interface ILineProcessor
|
||||
{
|
||||
public void process(String line, DungeonPackConfig config) throws ConfigurationProcessingException;
|
||||
}
|
||||
|
||||
//Note: These constants aren't static so that the memory will be released once
|
||||
//we're done using it an instance. These aren't objects that we need to hold
|
||||
//onto throughout the lifetime of MC, only at loading time.
|
||||
|
||||
private final int CONFIG_VERSION = 1;
|
||||
private final int LOOKAHEAD_LIMIT = 1024;
|
||||
private final int MAX_PRODUCT_WEIGHT = 10000;
|
||||
private final int MIN_PRODUCT_WEIGHT = 1;
|
||||
private final int DEFAULT_PRODUCT_WEIGHT = 100;
|
||||
private final int MAX_DUNGEON_PACK_WEIGHT = 10000;
|
||||
private final int MIN_DUNGEON_PACK_WEIGHT = 1;
|
||||
private final int DEFAULT_DUNGEON_PACK_WEIGHT = 100;
|
||||
private final int MAX_CONDITION_LENGTH = 20;
|
||||
private final int MAX_PRODUCT_COUNT = MAX_CONDITION_LENGTH;
|
||||
private final String COMMENT_MARKER = "##";
|
||||
|
||||
private final Pattern DUNGEON_TYPE_PATTERN = Pattern.compile("[A-Za-z0-9_\\-]{1,20}");
|
||||
|
||||
private final Splitter WHITESPACE_SPLITTER = Splitter.on(CharMatcher.WHITESPACE).omitEmptyStrings();
|
||||
private final String SETTING_SEPARATOR = "=";
|
||||
private final String RULE_SEPARATOR = "->";
|
||||
private final String WEIGHT_SEPARATOR = "#";
|
||||
|
||||
public DungeonPackConfigReader() { }
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public DungeonPackConfig readFromStream(InputStream inputStream) throws ConfigurationProcessingException
|
||||
{
|
||||
BufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
DungeonPackConfig config = new DungeonPackConfig();
|
||||
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
//Check the config format version
|
||||
int version = readVersion(reader);
|
||||
if (version != CONFIG_VERSION)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has an incompatible version.");
|
||||
}
|
||||
|
||||
config.setTypeNames(new ArrayList<String>());
|
||||
config.setRules(new ArrayList<DungeonChainRuleDefinition>());
|
||||
|
||||
//Read the dungeon types
|
||||
if (findSection("Types", reader))
|
||||
{
|
||||
processLines(reader, config, new DungeonTypeProcessor());
|
||||
}
|
||||
|
||||
//Load default settings
|
||||
config.setAllowDuplicatesInChain(true);
|
||||
config.setAllowPackChangeIn(true);
|
||||
config.setAllowPackChangeOut(true);
|
||||
config.setDistortDoorCoordinates(false);
|
||||
config.setPackWeight(DEFAULT_DUNGEON_PACK_WEIGHT);
|
||||
|
||||
//Read the settings section
|
||||
if (findSection("Settings", reader))
|
||||
{
|
||||
processLines(reader, config, new DungeonSettingsParser());
|
||||
}
|
||||
|
||||
//Read the rules section
|
||||
if (findSection("Rules", reader))
|
||||
{
|
||||
processLines(reader, config, new RuleDefinitionParser());
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
catch (ConfigurationProcessingException ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ConfigurationProcessingException("An unexpected error occurred while trying to read the configuration file.", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (reader != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
catch (IOException ex) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int readVersion(BufferedReader reader) throws ConfigurationProcessingException, IOException
|
||||
{
|
||||
String firstLine = reader.readLine();
|
||||
String[] parts = firstLine.split("\\s", 0);
|
||||
Integer version = null;
|
||||
|
||||
if (parts.length == 2 && parts[0].equalsIgnoreCase("version"))
|
||||
{
|
||||
version = Ints.tryParse(parts[1]);
|
||||
}
|
||||
|
||||
if (version == null)
|
||||
{
|
||||
throw new ConfigurationProcessingException("Could not parse the config format version.");
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private void processLines(BufferedReader reader, DungeonPackConfig config, ILineProcessor processor) throws IOException, ConfigurationProcessingException
|
||||
{
|
||||
String line;
|
||||
|
||||
while (reader.ready())
|
||||
{
|
||||
reader.mark(LOOKAHEAD_LIMIT);
|
||||
line = reader.readLine();
|
||||
if (!line.startsWith(COMMENT_MARKER))
|
||||
{
|
||||
line = line.trim();
|
||||
if (line.length() > 0)
|
||||
{
|
||||
if (line.endsWith(":"))
|
||||
{
|
||||
//Consider this line a section header, reset the reader to undo consuming it
|
||||
reader.reset();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
processor.process(line, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean findSection(String name, BufferedReader reader) throws IOException, ConfigurationProcessingException
|
||||
{
|
||||
boolean found = false;
|
||||
boolean matched = false;
|
||||
String line = null;
|
||||
String label = name + ":";
|
||||
|
||||
//Find the next section header
|
||||
//Ignore blank lines and comment lines, stop for headers, and throw an exception for anything else
|
||||
while (!found && reader.ready())
|
||||
{
|
||||
reader.mark(LOOKAHEAD_LIMIT);
|
||||
line = reader.readLine();
|
||||
if (!line.startsWith(COMMENT_MARKER))
|
||||
{
|
||||
line = line.trim();
|
||||
if (line.length() > 0)
|
||||
{
|
||||
if (line.endsWith(":"))
|
||||
{
|
||||
//Consider this line a section header
|
||||
found = true;
|
||||
matched = line.equalsIgnoreCase(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
//This line is invalid
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has an incorrect line where a section was expected: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if the header matches the one we're looking for.
|
||||
//If it doesn't match, undo consuming the line so it can be read later.
|
||||
if (found && !matched)
|
||||
{
|
||||
reader.reset();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private class DungeonTypeProcessor implements ILineProcessor
|
||||
{
|
||||
@Override
|
||||
public void process(String line, DungeonPackConfig config) throws ConfigurationProcessingException
|
||||
{
|
||||
List<String> typeNames = config.getTypeNames();
|
||||
|
||||
//Check if the dungeon type has a name that meets our restrictions
|
||||
if (DUNGEON_TYPE_PATTERN.matcher(line).matches())
|
||||
{
|
||||
//Ignore duplicate dungeon types
|
||||
line = line.toUpperCase();
|
||||
if (!typeNames.contains(line))
|
||||
{
|
||||
typeNames.add(line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a dungeon type with illegal characters in its name: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DungeonSettingsParser implements ILineProcessor
|
||||
{
|
||||
@Override
|
||||
public void process(String line, DungeonPackConfig config) throws ConfigurationProcessingException
|
||||
{
|
||||
//The various settings that we support will be hardcoded here.
|
||||
//In the future, if we get more settings, then this should be
|
||||
//refactored to use a more lookup-driven approach.
|
||||
|
||||
boolean valid = true;
|
||||
String[] settingParts = line.split(SETTING_SEPARATOR, 2);
|
||||
if (settingParts.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = settingParts[0].trim();
|
||||
String value = settingParts[1].trim();
|
||||
if (name.equalsIgnoreCase("AllowDuplicatesInChain"))
|
||||
{
|
||||
config.setAllowDuplicatesInChain(parseBoolean(value));
|
||||
}
|
||||
else if (name.equalsIgnoreCase("AllowPackChangeOut"))
|
||||
{
|
||||
config.setAllowPackChangeOut(parseBoolean(value));
|
||||
}
|
||||
else if (name.equalsIgnoreCase("AllowPackChangeIn"))
|
||||
{
|
||||
config.setAllowPackChangeIn(parseBoolean(value));
|
||||
}
|
||||
else if (name.equalsIgnoreCase("DistortDoorCoordinates"))
|
||||
{
|
||||
config.setDistortDoorCoordinates(parseBoolean(value));
|
||||
}
|
||||
else if (name.equalsIgnoreCase("PackWeight"))
|
||||
{
|
||||
int weight = Integer.parseInt(value);
|
||||
if (weight >= MIN_DUNGEON_PACK_WEIGHT && weight <= MAX_DUNGEON_PACK_WEIGHT)
|
||||
{
|
||||
config.setPackWeight(weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has an invalid setting: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RuleDefinitionParser implements ILineProcessor
|
||||
{
|
||||
@Override
|
||||
public void process(String definition, DungeonPackConfig config) throws ConfigurationProcessingException
|
||||
{
|
||||
String[] ruleParts;
|
||||
String[] productParts;
|
||||
String ruleCondition;
|
||||
String ruleProduct;
|
||||
ArrayList<String> condition;
|
||||
ArrayList<WeightedContainer<String>> products;
|
||||
List<String> typeNames = config.getTypeNames();
|
||||
|
||||
ruleParts = definition.toUpperCase().split(RULE_SEPARATOR, -1);
|
||||
if (ruleParts.length != 2)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has an invalid rule: " + definition);
|
||||
}
|
||||
|
||||
ruleCondition = ruleParts[0];
|
||||
ruleProduct = ruleParts[1];
|
||||
condition = new ArrayList<String>();
|
||||
products = new ArrayList<WeightedContainer<String>>();
|
||||
|
||||
for (String typeName : WHITESPACE_SPLITTER.split(ruleCondition))
|
||||
{
|
||||
if (isKnownDungeonType(typeName, typeNames))
|
||||
{
|
||||
condition.add(typeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule condition with an unknown dungeon type: " + typeName);
|
||||
}
|
||||
|
||||
if (condition.size() > MAX_CONDITION_LENGTH)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule condition that is too long: " + definition);
|
||||
}
|
||||
}
|
||||
|
||||
for (String product : WHITESPACE_SPLITTER.split(ruleProduct))
|
||||
{
|
||||
Integer weight;
|
||||
String typeName;
|
||||
|
||||
productParts = product.split(WEIGHT_SEPARATOR, -1);
|
||||
if (productParts.length > 2 || productParts.length == 0)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule with an invalid product: " + product);
|
||||
}
|
||||
|
||||
typeName = productParts[0];
|
||||
if (isKnownDungeonType(typeName, typeNames))
|
||||
{
|
||||
if (productParts.length > 1)
|
||||
{
|
||||
weight = Ints.tryParse(productParts[1]);
|
||||
if (weight == null || (weight > MAX_PRODUCT_WEIGHT) || (weight < MIN_PRODUCT_WEIGHT))
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule with an invalid product weight: " + product);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = DEFAULT_PRODUCT_WEIGHT;
|
||||
}
|
||||
products.add(new WeightedContainer<String>(typeName, weight));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has an unknown dungeon type in a rule: " + typeName);
|
||||
}
|
||||
|
||||
if (products.size() > MAX_PRODUCT_COUNT)
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule with too many products: " + definition);
|
||||
}
|
||||
}
|
||||
if (products.isEmpty())
|
||||
{
|
||||
throw new ConfigurationProcessingException("The dungeon pack config has a rule with no products: " + definition);
|
||||
}
|
||||
|
||||
config.getRules().add( new DungeonChainRuleDefinition(condition, products) );
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isKnownDungeonType(String typeName, List<String> typeNames)
|
||||
{
|
||||
return typeName.equals(DungeonType.WILDCARD_TYPE.Name) || typeNames.contains(typeName);
|
||||
}
|
||||
|
||||
private static boolean parseBoolean(String value)
|
||||
{
|
||||
if (value.equalsIgnoreCase("true"))
|
||||
return true;
|
||||
if (value.equalsIgnoreCase("false"))
|
||||
return false;
|
||||
throw new IllegalArgumentException("The boolean value must be either \"true\" or \"false\", ignoring case.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(OutputStream outputStream, DungeonPackConfig data) throws ConfigurationProcessingException
|
||||
{
|
||||
throw new UnsupportedOperationException("DungeonPackConfigReader does not support writing.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package StevenDimDoors.mod_pocketDim.dungeon.pack;
|
||||
|
||||
public class DungeonType implements Comparable<DungeonType>
|
||||
{
|
||||
public static final DungeonType WILDCARD_TYPE = new DungeonType(null, "?", 0);
|
||||
public static final DungeonType UNKNOWN_TYPE = new DungeonType(null, "!", -1);
|
||||
|
||||
public final DungeonPack Owner;
|
||||
public final String Name;
|
||||
public final int ID;
|
||||
|
||||
public DungeonType(DungeonPack owner, String name, int id)
|
||||
{
|
||||
Owner = owner;
|
||||
Name = name;
|
||||
this.ID = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DungeonType other)
|
||||
{
|
||||
return this.ID - other.ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return equals((DungeonType) other);
|
||||
}
|
||||
|
||||
public boolean equals(DungeonType other)
|
||||
{
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
if (this == null || other == null)
|
||||
return false;
|
||||
|
||||
return (this.ID == other.ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 2039;
|
||||
return prime * ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
public class BlockRotationHelper
|
||||
{
|
||||
public HashMap<Integer,HashMap<Integer,HashMap<Integer,Integer>>> rotationMappings = new HashMap<Integer,HashMap<Integer,HashMap<Integer,Integer>>>();
|
||||
|
||||
public BlockRotationHelper()
|
||||
{
|
||||
this.InitializeRotationMap();
|
||||
}
|
||||
|
||||
public void InitializeRotationMap()
|
||||
{
|
||||
HashMap<Integer,HashMap<Integer, Integer>> orientation0 = new HashMap<Integer,HashMap<Integer, Integer>>();
|
||||
|
||||
HashMap<Integer,Integer> stairs0 = new HashMap<Integer,Integer>();
|
||||
|
||||
stairs0.put(0, 2);
|
||||
stairs0.put(1, 3);
|
||||
stairs0.put(2, 1);
|
||||
stairs0.put(3, 0);
|
||||
stairs0.put(7, 4);
|
||||
stairs0.put(6, 5);
|
||||
stairs0.put(5, 7);
|
||||
stairs0.put(4, 6);
|
||||
|
||||
HashMap<Integer,Integer> chestsLadders0 = new HashMap<Integer,Integer>();
|
||||
|
||||
chestsLadders0.put(2, 5);
|
||||
chestsLadders0.put(3, 4);
|
||||
chestsLadders0.put(4, 2);
|
||||
chestsLadders0.put(5, 3);
|
||||
|
||||
HashMap<Integer,Integer> vine0 = new HashMap<Integer,Integer>();
|
||||
|
||||
vine0.put(1, 2);
|
||||
vine0.put(2, 4);
|
||||
vine0.put(4, 8);
|
||||
vine0.put(8, 1);
|
||||
|
||||
HashMap<Integer,Integer> leverButtonTorch0 = new HashMap<Integer,Integer>();
|
||||
|
||||
leverButtonTorch0.put(12, 9);
|
||||
leverButtonTorch0.put(11, 10);
|
||||
leverButtonTorch0.put(10, 12);
|
||||
leverButtonTorch0.put(9, 11);
|
||||
leverButtonTorch0.put(2, 4);
|
||||
leverButtonTorch0.put(3, 2);
|
||||
leverButtonTorch0.put(1, 3);
|
||||
leverButtonTorch0.put(4, 1);
|
||||
|
||||
HashMap<Integer,Integer> pistonDropperDispenser0 = new HashMap<Integer,Integer>();
|
||||
|
||||
pistonDropperDispenser0.put(4, 2);
|
||||
pistonDropperDispenser0.put(5, 3);
|
||||
pistonDropperDispenser0.put(13, 11);
|
||||
pistonDropperDispenser0.put(3, 4);
|
||||
pistonDropperDispenser0.put(2, 5);
|
||||
pistonDropperDispenser0.put(11, 12);
|
||||
pistonDropperDispenser0.put(10, 13);
|
||||
pistonDropperDispenser0.put(12, 10);
|
||||
|
||||
HashMap<Integer,Integer> repeaterComparatorDoorTripwire0 = new HashMap<Integer,Integer>();
|
||||
|
||||
repeaterComparatorDoorTripwire0.put(0, 1);
|
||||
repeaterComparatorDoorTripwire0.put(1, 2);
|
||||
repeaterComparatorDoorTripwire0.put(2, 3);
|
||||
repeaterComparatorDoorTripwire0.put(3, 0);
|
||||
repeaterComparatorDoorTripwire0.put(4, 5);
|
||||
repeaterComparatorDoorTripwire0.put(5, 6);
|
||||
repeaterComparatorDoorTripwire0.put(6, 7);
|
||||
repeaterComparatorDoorTripwire0.put(7, 4);
|
||||
repeaterComparatorDoorTripwire0.put(8, 9);
|
||||
repeaterComparatorDoorTripwire0.put(9, 10);
|
||||
repeaterComparatorDoorTripwire0.put(10, 11);
|
||||
repeaterComparatorDoorTripwire0.put(11, 8);
|
||||
repeaterComparatorDoorTripwire0.put(12, 13);
|
||||
repeaterComparatorDoorTripwire0.put(13, 14);
|
||||
repeaterComparatorDoorTripwire0.put(14, 15);
|
||||
repeaterComparatorDoorTripwire0.put(15, 12);
|
||||
|
||||
HashMap<Integer,Integer> rails0 = new HashMap<Integer,Integer>();
|
||||
rails0.put(0, 1);
|
||||
rails0.put(1, 0);
|
||||
rails0.put(8, 9);
|
||||
rails0.put(9, 6);
|
||||
rails0.put(6, 7);
|
||||
rails0.put(7, 8);
|
||||
|
||||
|
||||
HashMap<Integer,Integer> railsSpecial0 = new HashMap<Integer,Integer>();
|
||||
railsSpecial0.put(0, 1);
|
||||
railsSpecial0.put(1, 0);
|
||||
railsSpecial0.put(8, 9);
|
||||
railsSpecial0.put(9, 8);
|
||||
|
||||
|
||||
HashMap<Integer,HashMap<Integer, Integer>> orientation1 = new HashMap<Integer,HashMap<Integer, Integer>>();
|
||||
|
||||
HashMap<Integer,Integer> stairs1 = new HashMap<Integer,Integer>();
|
||||
|
||||
stairs1.put(0, 1);
|
||||
stairs1.put(1, 0);
|
||||
stairs1.put(2, 3);
|
||||
stairs1.put(3, 2);
|
||||
stairs1.put(7, 6);
|
||||
stairs1.put(6, 7);
|
||||
stairs1.put(5, 4);
|
||||
stairs1.put(4, 5);
|
||||
|
||||
HashMap<Integer,Integer> chestsLadders1 = new HashMap<Integer,Integer>();
|
||||
|
||||
chestsLadders1.put(2, 3);
|
||||
chestsLadders1.put(3, 2);
|
||||
chestsLadders1.put(4, 5);
|
||||
chestsLadders1.put(5, 4);
|
||||
|
||||
HashMap<Integer,Integer> vine1 = new HashMap<Integer,Integer>();
|
||||
|
||||
vine1.put(1, 4);
|
||||
vine1.put(2, 8);
|
||||
vine1.put(4, 1);
|
||||
vine1.put(8, 2);
|
||||
|
||||
HashMap<Integer,Integer> leverButtonTorch1 = new HashMap<Integer,Integer>();
|
||||
|
||||
leverButtonTorch1.put(12, 9);
|
||||
leverButtonTorch1.put(11, 10);
|
||||
leverButtonTorch1.put(10, 12);
|
||||
leverButtonTorch1.put(9, 11);
|
||||
leverButtonTorch1.put(2, 4);
|
||||
leverButtonTorch1.put(3, 2);
|
||||
leverButtonTorch1.put(1, 3);
|
||||
leverButtonTorch1.put(4, 1);
|
||||
|
||||
HashMap<Integer,Integer> pistonDropperDispenser1 = new HashMap<Integer,Integer>();
|
||||
|
||||
pistonDropperDispenser1.put(12, 11);
|
||||
pistonDropperDispenser1.put(11, 12);
|
||||
pistonDropperDispenser1.put(10, 9);
|
||||
pistonDropperDispenser1.put(9, 10);
|
||||
pistonDropperDispenser1.put(2, 1);
|
||||
pistonDropperDispenser1.put(3, 4);
|
||||
pistonDropperDispenser1.put(1, 2);
|
||||
pistonDropperDispenser1.put(4,3);
|
||||
|
||||
|
||||
HashMap<Integer,Integer> repeaterComparatorDoorTripwire1 = new HashMap<Integer,Integer>();
|
||||
|
||||
repeaterComparatorDoorTripwire1.put(0, 2);
|
||||
repeaterComparatorDoorTripwire1.put(1, 3);
|
||||
repeaterComparatorDoorTripwire1.put(2, 0);
|
||||
repeaterComparatorDoorTripwire1.put(3, 1);
|
||||
repeaterComparatorDoorTripwire1.put(4, 6);
|
||||
repeaterComparatorDoorTripwire1.put(5, 7);
|
||||
repeaterComparatorDoorTripwire1.put(6, 4);
|
||||
repeaterComparatorDoorTripwire1.put(7, 5);
|
||||
repeaterComparatorDoorTripwire1.put(8, 10);
|
||||
repeaterComparatorDoorTripwire1.put(9, 11);
|
||||
repeaterComparatorDoorTripwire1.put(10, 8);
|
||||
repeaterComparatorDoorTripwire1.put(11, 9);
|
||||
repeaterComparatorDoorTripwire1.put(12, 14);
|
||||
repeaterComparatorDoorTripwire1.put(13, 15);
|
||||
repeaterComparatorDoorTripwire1.put(14, 12);
|
||||
repeaterComparatorDoorTripwire1.put(15, 13);
|
||||
|
||||
HashMap<Integer,Integer> rails1 = new HashMap<Integer,Integer>();
|
||||
rails1.put(0, 0);
|
||||
rails1.put(1, 1);
|
||||
rails1.put(8, 6);
|
||||
rails1.put(9, 7);
|
||||
rails1.put(6, 8);
|
||||
rails1.put(7, 9);
|
||||
|
||||
|
||||
HashMap<Integer,Integer> railsSpecial1 = new HashMap<Integer,Integer>();
|
||||
railsSpecial1.put(1, 1);
|
||||
railsSpecial1.put(0, 0);
|
||||
railsSpecial1.put(8, 8);
|
||||
railsSpecial1.put(9, 9);
|
||||
|
||||
HashMap<Integer,HashMap<Integer, Integer>> orientation2 = new HashMap<Integer,HashMap<Integer, Integer>>();
|
||||
|
||||
HashMap<Integer,Integer> stairs2 = new HashMap<Integer,Integer>();
|
||||
|
||||
stairs2.put(2, 0);
|
||||
stairs2.put(3, 1);
|
||||
stairs2.put(1, 2);
|
||||
stairs2.put(0, 3);
|
||||
stairs2.put(4, 7);
|
||||
stairs2.put(5, 6);
|
||||
stairs2.put(7, 5);
|
||||
stairs2.put(6, 4);
|
||||
|
||||
HashMap<Integer,Integer> chestsLadders2 = new HashMap<Integer,Integer>();
|
||||
|
||||
chestsLadders2.put(2, 4);
|
||||
chestsLadders2.put(3, 5);
|
||||
chestsLadders2.put(4, 3);
|
||||
chestsLadders2.put(5, 2);
|
||||
|
||||
HashMap<Integer,Integer> vine2 = new HashMap<Integer,Integer>();
|
||||
|
||||
vine2.put(1, 8);
|
||||
vine2.put(2, 1);
|
||||
vine2.put(4, 2);
|
||||
vine2.put(8, 4);
|
||||
|
||||
HashMap<Integer,Integer> leverButtonTorch2 = new HashMap<Integer,Integer>();
|
||||
|
||||
leverButtonTorch2.put(9, 12);
|
||||
leverButtonTorch2.put(10, 11);
|
||||
leverButtonTorch2.put(12, 10);
|
||||
leverButtonTorch2.put(11, 9);
|
||||
leverButtonTorch2.put(4, 2);
|
||||
leverButtonTorch2.put(2, 3);
|
||||
leverButtonTorch2.put(3, 1);
|
||||
leverButtonTorch2.put(1, 4);
|
||||
|
||||
HashMap<Integer,Integer> pistonDropperDispenser2 = new HashMap<Integer,Integer>();
|
||||
|
||||
pistonDropperDispenser2.put(2, 4);
|
||||
pistonDropperDispenser2.put(3, 5);
|
||||
pistonDropperDispenser2.put(11, 13);
|
||||
pistonDropperDispenser2.put(10, 12);
|
||||
pistonDropperDispenser2.put(4, 3);
|
||||
pistonDropperDispenser2.put(5, 2);
|
||||
pistonDropperDispenser2.put(12, 11);
|
||||
pistonDropperDispenser2.put(13,10);
|
||||
|
||||
|
||||
HashMap<Integer,Integer> repeaterComparatorDoorTripwire2 = new HashMap<Integer,Integer>();
|
||||
|
||||
repeaterComparatorDoorTripwire2.put(1, 0);
|
||||
repeaterComparatorDoorTripwire2.put(2, 1);
|
||||
repeaterComparatorDoorTripwire2.put(3, 2);
|
||||
repeaterComparatorDoorTripwire2.put(0, 3);
|
||||
repeaterComparatorDoorTripwire2.put(5, 4);
|
||||
repeaterComparatorDoorTripwire2.put(6, 5);
|
||||
repeaterComparatorDoorTripwire2.put(7, 6);
|
||||
repeaterComparatorDoorTripwire2.put(4, 7);
|
||||
repeaterComparatorDoorTripwire2.put(9, 8);
|
||||
repeaterComparatorDoorTripwire2.put(10, 9);
|
||||
repeaterComparatorDoorTripwire2.put(11, 10);
|
||||
repeaterComparatorDoorTripwire2.put(8, 11);
|
||||
repeaterComparatorDoorTripwire2.put(13, 12);
|
||||
repeaterComparatorDoorTripwire2.put(14, 13);
|
||||
repeaterComparatorDoorTripwire2.put(15, 14);
|
||||
repeaterComparatorDoorTripwire2.put(12, 15);
|
||||
|
||||
HashMap<Integer,Integer> rails2 = new HashMap<Integer,Integer>();
|
||||
rails2.put(0, 1);
|
||||
rails2.put(1, 0);
|
||||
rails2.put(8, 7);
|
||||
rails2.put(9, 8);
|
||||
rails2.put(6, 9);
|
||||
rails2.put(7, 6);
|
||||
|
||||
|
||||
HashMap<Integer,Integer> railsSpecial2 = new HashMap<Integer,Integer>();
|
||||
railsSpecial2.put(0, 1);
|
||||
railsSpecial2.put(1, 0);
|
||||
railsSpecial2.put(8, 9);
|
||||
railsSpecial2.put(9, 8);
|
||||
|
||||
|
||||
|
||||
|
||||
orientation0.put(Block.stairsBrick.blockID, stairs0);
|
||||
orientation0.put(Block.stairsCobblestone.blockID, stairs0);
|
||||
orientation0.put(Block.stairsNetherBrick.blockID, stairs0);
|
||||
orientation0.put(Block.stairsNetherQuartz.blockID, stairs0);
|
||||
orientation0.put(Block.stairsSandStone.blockID, stairs0);
|
||||
orientation0.put(Block.stairsStoneBrick.blockID, stairs0);
|
||||
orientation0.put(Block.stairsWoodBirch.blockID, stairs0);
|
||||
orientation0.put(Block.stairsWoodJungle.blockID, stairs0);
|
||||
orientation0.put(Block.stairsWoodOak.blockID, stairs0);
|
||||
orientation0.put(Block.stairsWoodSpruce.blockID, stairs0);
|
||||
orientation0.put(Block.stairsBrick.blockID, stairs0);
|
||||
orientation0.put(Block.vine.blockID, vine0);
|
||||
orientation0.put(Block.chest.blockID, chestsLadders0);
|
||||
orientation0.put(Block.chestTrapped.blockID, chestsLadders0);
|
||||
orientation0.put(Block.ladder.blockID, chestsLadders0);
|
||||
orientation0.put(Block.lever.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.stoneButton.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.woodenButton.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.torchRedstoneActive.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.torchRedstoneIdle.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.torchWood.blockID, leverButtonTorch0);
|
||||
orientation0.put(Block.pistonBase.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.pistonExtension.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.pistonMoving.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.pistonStickyBase.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.dropper.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.dispenser.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.redstoneComparatorActive.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.redstoneComparatorIdle.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.redstoneRepeaterActive.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.redstoneRepeaterIdle.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.doorWood.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.doorIron.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.tripWireSource.blockID,pistonDropperDispenser0);
|
||||
orientation0.put(Block.railDetector.blockID,railsSpecial0);
|
||||
orientation0.put(Block.railActivator.blockID,railsSpecial0);
|
||||
orientation0.put(Block.railPowered.blockID,railsSpecial0);
|
||||
orientation0.put(Block.rail.blockID,rails0);
|
||||
|
||||
orientation1.put(Block.stairsBrick.blockID, stairs1);
|
||||
orientation1.put(Block.stairsCobblestone.blockID, stairs1);
|
||||
orientation1.put(Block.stairsNetherBrick.blockID, stairs1);
|
||||
orientation1.put(Block.stairsNetherQuartz.blockID, stairs1);
|
||||
orientation1.put(Block.stairsSandStone.blockID, stairs1);
|
||||
orientation1.put(Block.stairsStoneBrick.blockID, stairs1);
|
||||
orientation1.put(Block.stairsWoodBirch.blockID, stairs1);
|
||||
orientation1.put(Block.stairsWoodJungle.blockID, stairs1);
|
||||
orientation1.put(Block.stairsWoodOak.blockID, stairs1);
|
||||
orientation1.put(Block.stairsWoodSpruce.blockID, stairs1);
|
||||
orientation1.put(Block.stairsBrick.blockID, stairs1);
|
||||
orientation1.put(Block.vine.blockID, vine1);
|
||||
orientation1.put(Block.chest.blockID, chestsLadders1);
|
||||
orientation1.put(Block.chestTrapped.blockID, chestsLadders1);
|
||||
orientation1.put(Block.ladder.blockID, chestsLadders1);
|
||||
orientation1.put(Block.lever.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.stoneButton.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.woodenButton.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.torchRedstoneActive.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.torchRedstoneIdle.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.torchWood.blockID, leverButtonTorch1);
|
||||
orientation1.put(Block.pistonBase.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.pistonExtension.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.pistonMoving.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.pistonStickyBase.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.dropper.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.dispenser.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.redstoneComparatorActive.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.redstoneComparatorIdle.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.redstoneRepeaterActive.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.redstoneRepeaterIdle.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.doorWood.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.doorIron.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.tripWireSource.blockID,pistonDropperDispenser1);
|
||||
orientation1.put(Block.railDetector.blockID,railsSpecial1);
|
||||
orientation1.put(Block.railActivator.blockID,railsSpecial1);
|
||||
orientation1.put(Block.railPowered.blockID,railsSpecial1);
|
||||
orientation1.put(Block.rail.blockID,rails1);
|
||||
|
||||
orientation2.put(Block.stairsBrick.blockID, stairs2);
|
||||
orientation2.put(Block.stairsCobblestone.blockID, stairs2);
|
||||
orientation2.put(Block.stairsNetherBrick.blockID, stairs2);
|
||||
orientation2.put(Block.stairsNetherQuartz.blockID, stairs2);
|
||||
orientation2.put(Block.stairsSandStone.blockID, stairs2);
|
||||
orientation2.put(Block.stairsStoneBrick.blockID, stairs2);
|
||||
orientation2.put(Block.stairsWoodBirch.blockID, stairs2);
|
||||
orientation2.put(Block.stairsWoodJungle.blockID, stairs2);
|
||||
orientation2.put(Block.stairsWoodOak.blockID, stairs2);
|
||||
orientation2.put(Block.stairsWoodSpruce.blockID, stairs2);
|
||||
orientation2.put(Block.stairsBrick.blockID, stairs2);
|
||||
orientation2.put(Block.vine.blockID, vine2);
|
||||
orientation2.put(Block.chest.blockID, chestsLadders2);
|
||||
orientation2.put(Block.chestTrapped.blockID, chestsLadders2);
|
||||
orientation2.put(Block.ladder.blockID, chestsLadders2);
|
||||
orientation2.put(Block.lever.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.stoneButton.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.woodenButton.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.torchRedstoneActive.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.torchRedstoneIdle.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.torchWood.blockID, leverButtonTorch2);
|
||||
orientation2.put(Block.pistonBase.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.pistonExtension.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.pistonMoving.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.pistonStickyBase.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.dropper.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.dispenser.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.redstoneComparatorActive.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.redstoneComparatorIdle.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.redstoneRepeaterActive.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.redstoneRepeaterIdle.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.doorWood.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.doorIron.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.tripWireSource.blockID,pistonDropperDispenser2);
|
||||
orientation2.put(Block.railDetector.blockID,railsSpecial2);
|
||||
orientation2.put(Block.railActivator.blockID,railsSpecial2);
|
||||
orientation2.put(Block.railPowered.blockID,railsSpecial2);
|
||||
orientation2.put(Block.rail.blockID,rails2);
|
||||
|
||||
this.rotationMappings.put(2, orientation2);
|
||||
this.rotationMappings.put(1, orientation1);
|
||||
this.rotationMappings.put(0, orientation0);
|
||||
}
|
||||
|
||||
public int getRotatedBlock(int metaData, int desiredOrientation, int blockID)
|
||||
{
|
||||
if(this.rotationMappings.containsKey(desiredOrientation))
|
||||
{
|
||||
if(this.rotationMappings.get(desiredOrientation).containsKey(blockID))
|
||||
{
|
||||
if(this.rotationMappings.get(desiredOrientation).get(blockID).containsKey(metaData))
|
||||
{
|
||||
return this.rotationMappings.get(desiredOrientation).get(blockID).get(metaData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return metaData ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.IChunkLoader;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.common.ForgeChunkManager.LoadingCallback;
|
||||
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
||||
|
||||
public class ChunkLoaderHelper implements LoadingCallback
|
||||
{
|
||||
|
||||
@Override
|
||||
public void ticketsLoaded(List<Ticket> tickets, World world)
|
||||
{
|
||||
for (Ticket ticket : tickets)
|
||||
{
|
||||
int goldDimDoorX = ticket.getModData().getInteger("goldDimDoorX");
|
||||
int goldDimDoorY = ticket.getModData().getInteger("goldDimDoorY");
|
||||
int goldDimDoorZ = ticket.getModData().getInteger("goldDimDoorZ");
|
||||
if(world.getBlockId(goldDimDoorX, goldDimDoorY, goldDimDoorZ)!=mod_pocketDim.properties.GoldDimDoorID)
|
||||
{
|
||||
ForgeChunkManager.releaseTicket(ticket);
|
||||
}
|
||||
else
|
||||
{
|
||||
IChunkLoader tile = (IChunkLoader) world.getBlockTileEntity(goldDimDoorX, goldDimDoorY, goldDimDoorZ);
|
||||
tile.forceChunkLoading(ticket,goldDimDoorX,goldDimDoorZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadChunkForcedWorlds(FMLServerStartingEvent event)
|
||||
{
|
||||
for(NewDimData data : PocketManager.getDimensions())
|
||||
{
|
||||
if(data.isPocketDimension())
|
||||
{
|
||||
String chunkDir = DimensionManager.getCurrentSaveRootDirectory()+"/DimensionalDoors/pocketDimID" + data.id();
|
||||
|
||||
File file = new File(chunkDir);
|
||||
|
||||
if(file.exists())
|
||||
{
|
||||
if(ForgeChunkManager.savedWorldHasForcedChunkTickets(file))
|
||||
{
|
||||
PocketManager.loadDimension(data.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.IDimRegistrationCallback;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import StevenDimDoors.mod_pocketDim.watcher.ClientLinkData;
|
||||
|
||||
public class Compactor
|
||||
{
|
||||
|
||||
@SuppressWarnings("unused") // ?
|
||||
private static class DimComparator implements Comparator<NewDimData>
|
||||
{
|
||||
@Override
|
||||
public int compare(NewDimData a, NewDimData b)
|
||||
{
|
||||
return a.id() - b.id();
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Collection<? extends NewDimData> values, DataOutputStream output) throws IOException
|
||||
{
|
||||
// SenseiKiwi: Just encode the data straight up for now. I'll implement fancier compression later.
|
||||
output.writeInt(values.size());
|
||||
for (NewDimData dimension : values)
|
||||
{
|
||||
output.writeInt(dimension.id());
|
||||
output.writeInt(dimension.root().id());
|
||||
output.writeInt(dimension.linkCount());
|
||||
for (DimLink link : dimension.links())
|
||||
{
|
||||
Point4D.write(link.source(), output);
|
||||
output.writeInt(link.orientation());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note to self: the root ID can be "compressed" by grouping
|
||||
// dimensions by their root ID and then only sending it once
|
||||
|
||||
/*
|
||||
// To compress the dimension IDs, we'll sort them by ID
|
||||
// and write the _difference_ between their ID numbers.
|
||||
NewDimData[] dimensions = new NewDimData[values.size()];
|
||||
dimensions = values.toArray(dimensions);
|
||||
Arrays.sort(dimensions, new DimComparator());
|
||||
*/
|
||||
}
|
||||
|
||||
public static void readDimensions(DataInputStream input, IDimRegistrationCallback callback) throws IOException
|
||||
{
|
||||
// Read in the dimensions one by one. Make sure we register root dimensions before
|
||||
// attempting to register the dimensions under them.
|
||||
|
||||
HashSet<Integer> rootIDs = new HashSet<Integer>();
|
||||
|
||||
int dimCount = input.readInt();
|
||||
for (int k = 0; k < dimCount; k++)
|
||||
{
|
||||
int id = input.readInt();
|
||||
int rootID = input.readInt();
|
||||
|
||||
if (rootIDs.add(rootID))
|
||||
{
|
||||
callback.registerDimension(rootID, rootID);
|
||||
}
|
||||
// Don't check if (id != rootID) - we want to retrieve the reference anyway
|
||||
NewDimData dimension = callback.registerDimension(id, rootID);
|
||||
int linkCount = input.readInt();
|
||||
for (int h = 0; h < linkCount; h++)
|
||||
{
|
||||
ClientLinkData link = ClientLinkData.read(input);
|
||||
Point4D source = link.point;
|
||||
dimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.CLIENT_SIDE,link.orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public class DeleteFolder
|
||||
{
|
||||
public static boolean deleteFolder(File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
File[] files = file.listFiles();
|
||||
|
||||
if(files==null)
|
||||
{
|
||||
file.delete();
|
||||
return true;
|
||||
}
|
||||
for(File inFile : files)
|
||||
{
|
||||
DeleteFolder.deleteFolder(inFile);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,659 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.util.WeightedRandom;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPackConfig;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPackConfigReader;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor;
|
||||
import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException;
|
||||
import StevenDimDoors.mod_pocketDim.util.FileFilters;
|
||||
import StevenDimDoors.mod_pocketDim.util.WeightedContainer;
|
||||
|
||||
public class DungeonHelper
|
||||
{
|
||||
private static DungeonHelper instance = null;
|
||||
private static DDProperties properties = null;
|
||||
|
||||
public static final Pattern SCHEMATIC_NAME_PATTERN = Pattern.compile("[A-Za-z0-9_\\-]+");
|
||||
public static final Pattern DUNGEON_NAME_PATTERN = Pattern.compile("[A-Za-z0-9\\-]+");
|
||||
|
||||
public static final String SCHEMATIC_FILE_EXTENSION = ".schematic";
|
||||
|
||||
private static final String DEFAULT_ERROR_SCHEMATIC_PATH = "/schematics/core/somethingBroke.schematic";
|
||||
private static final String DUNGEON_CREATION_GUIDE_SOURCE_PATH = "/mods/DimDoors/text/How_to_add_dungeons.txt";
|
||||
private static final String RUINS_PACK_PATH = "/schematics/ruins";
|
||||
private static final String BUNDLED_RUINS_LIST_PATH = "/schematics/ruins.txt";
|
||||
private static final String STANDARD_CONFIG_FILE_NAME = "rules.txt";
|
||||
|
||||
private static final int NETHER_DIMENSION_ID = -1;
|
||||
|
||||
private static final int MIN_PACK_SWITCH_CHANCE = 0;
|
||||
private static final int PACK_SWITCH_CHANCE_PER_LEVEL = 1;
|
||||
private static final int MAX_PACK_SWITCH_CHANCE = 500;
|
||||
private static final int START_PACK_SWITCH_CHANCE = MAX_PACK_SWITCH_CHANCE / 9;
|
||||
|
||||
private static final int DEFAULT_DUNGEON_WEIGHT = 100;
|
||||
public static final int MIN_DUNGEON_WEIGHT = 1; //Prevents MC's random selection algorithm from throwing an exception
|
||||
public static final int MAX_DUNGEON_WEIGHT = 10000; //Used to prevent overflows and math breaking down
|
||||
|
||||
private static final int MAX_EXPORT_RADIUS = 50;
|
||||
public static final short MAX_DUNGEON_WIDTH = 2 * MAX_EXPORT_RADIUS + 1;
|
||||
public static final short MAX_DUNGEON_HEIGHT = MAX_DUNGEON_WIDTH;
|
||||
public static final short MAX_DUNGEON_LENGTH = MAX_DUNGEON_WIDTH;
|
||||
|
||||
private ArrayList<DungeonData> untaggedDungeons = new ArrayList<DungeonData>();
|
||||
private ArrayList<DungeonData> registeredDungeons = new ArrayList<DungeonData>();
|
||||
|
||||
private DungeonPack RuinsPack;
|
||||
private HashMap<String, DungeonPack> dungeonPackMapping = new HashMap<String, DungeonPack>();
|
||||
private ArrayList<DungeonPack> dungeonPackList = new ArrayList<DungeonPack>();
|
||||
|
||||
private DungeonData defaultError;
|
||||
|
||||
private DungeonHelper()
|
||||
{
|
||||
//Load our reference to the DDProperties singleton
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
|
||||
registerDungeons();
|
||||
}
|
||||
|
||||
public static DungeonHelper initialize()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new DungeonHelper();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Cannot initialize DungeonHelper twice");
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static DungeonHelper instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
//This is to prevent some frustrating bugs that could arise when classes
|
||||
//are loaded in the wrong order. Trust me, I had to squash a few...
|
||||
throw new IllegalStateException("Instance of DungeonHelper requested before initialization");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void registerDungeons()
|
||||
{
|
||||
File file = new File(properties.CustomSchematicDirectory);
|
||||
if (file.exists() || file.mkdir())
|
||||
{
|
||||
copyfile.copyFile(DUNGEON_CREATION_GUIDE_SOURCE_PATH, file.getAbsolutePath() + "/How_to_add_dungeons.txt");
|
||||
}
|
||||
|
||||
DungeonPackConfigReader reader = new DungeonPackConfigReader();
|
||||
registerBundledDungeons(reader);
|
||||
registerCustomDungeons(properties.CustomSchematicDirectory, reader);
|
||||
}
|
||||
|
||||
private static DungeonPackConfig loadDungeonPackConfig(String configPath, String name, boolean isInternal, DungeonPackConfigReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
DungeonPackConfig config;
|
||||
if (isInternal)
|
||||
{
|
||||
config = reader.readFromResource(configPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
config = reader.readFromFile(configPath);
|
||||
}
|
||||
config.setName(name);
|
||||
return config;
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("Could not find a dungeon pack config file: " + configPath);
|
||||
}
|
||||
catch (Exception e) // handles IOException and ConfigurationProcessingException
|
||||
{
|
||||
System.err.println(e.getMessage());
|
||||
if (e.getCause() != null)
|
||||
{
|
||||
System.err.println(e.getCause());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void registerDungeonPack(String directory, Iterable<String> schematics, boolean isInternal, boolean verbose, DungeonPackConfigReader reader)
|
||||
{
|
||||
//First determine the pack's name and validate it
|
||||
File packDirectory = new File(directory);
|
||||
String name = packDirectory.getName().toUpperCase();
|
||||
//TODO: ADD VALIDATION HERE?
|
||||
|
||||
//Check for naming conflicts
|
||||
//That could happen if a user has a custom pack with a name that conflicts with a bundled pack,
|
||||
//or if a user is running Linux and has two directories with names differing only by capitalization.
|
||||
|
||||
DungeonPack pack = dungeonPackMapping.get(name);
|
||||
if (pack == null)
|
||||
{
|
||||
//Load the pack's configuration file
|
||||
|
||||
String configPath;
|
||||
if (isInternal)
|
||||
{
|
||||
configPath = directory + "/" + STANDARD_CONFIG_FILE_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
configPath = directory + File.separator + STANDARD_CONFIG_FILE_NAME;
|
||||
}
|
||||
DungeonPackConfig config = loadDungeonPackConfig(configPath, name, isInternal, reader);
|
||||
if (config == null)
|
||||
{
|
||||
System.err.println("Could not load config file: " + configPath);
|
||||
return;
|
||||
}
|
||||
|
||||
//Register the pack
|
||||
pack = new DungeonPack(config);
|
||||
dungeonPackMapping.put(name, pack);
|
||||
dungeonPackList.add(pack);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Show a warning that there is a naming conflict but keep going. People can use this to extend
|
||||
//our built-in packs with custom schematics without tampering with our mod's JAR file.
|
||||
System.err.println("A dungeon pack has the same name as another pack that has already been loaded: " + directory);
|
||||
System.err.println("We will try to load its schematics but will not check its config file.");
|
||||
}
|
||||
|
||||
//Register the dungeons! ^_^
|
||||
for (String schematicPath : schematics)
|
||||
{
|
||||
registerDungeon(schematicPath, pack, isInternal, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
public List<DungeonData> getRegisteredDungeons()
|
||||
{
|
||||
return Collections.unmodifiableList(this.registeredDungeons);
|
||||
}
|
||||
|
||||
public List<DungeonData> getUntaggedDungeons()
|
||||
{
|
||||
return Collections.unmodifiableList(this.untaggedDungeons);
|
||||
}
|
||||
|
||||
public DungeonData getDefaultErrorDungeon()
|
||||
{
|
||||
return defaultError;
|
||||
}
|
||||
|
||||
public DungeonPack getDungeonPack(String name)
|
||||
{
|
||||
//TODO: This function might be obsolete after the new save format is implemented.
|
||||
return dungeonPackMapping.get(name.toUpperCase());
|
||||
}
|
||||
|
||||
private DungeonPack getDimDungeonPack(NewDimData data)
|
||||
{
|
||||
DungeonPack pack;
|
||||
DungeonData dungeon = data.dungeon();
|
||||
if (dungeon != null)
|
||||
{
|
||||
pack = dungeon.dungeonType().Owner;
|
||||
|
||||
//Make sure the pack isn't null. This can happen for dungeons with the special UNKNOWN type.
|
||||
if (pack == null)
|
||||
{
|
||||
pack = RuinsPack;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.id() == NETHER_DIMENSION_ID)
|
||||
{
|
||||
//TODO: Change this to the nether-side pack later ^_^
|
||||
pack = RuinsPack;
|
||||
}
|
||||
else
|
||||
{
|
||||
pack = RuinsPack;
|
||||
}
|
||||
}
|
||||
return pack;
|
||||
}
|
||||
|
||||
public DimLink createCustomDungeonDoor(World world, int x, int y, int z)
|
||||
{
|
||||
//Create a link above the specified position. Link to a new pocket dimension.
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.createLink(x, y + 1, z, LinkTypes.POCKET,3);
|
||||
|
||||
//Place a Warp Door linked to that pocket
|
||||
ItemDimensionalDoor.placeDoorBlock(world, x, y, z, 3, mod_pocketDim.warpDoor);
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public boolean validateDungeonType(String type, DungeonPack pack)
|
||||
{
|
||||
return pack.isKnownType(type);
|
||||
}
|
||||
|
||||
public boolean validateSchematicName(String name, DungeonPack pack)
|
||||
{
|
||||
String[] dungeonData;
|
||||
|
||||
if (!name.endsWith(SCHEMATIC_FILE_EXTENSION))
|
||||
return false;
|
||||
|
||||
dungeonData = name.substring(0, name.length() - SCHEMATIC_FILE_EXTENSION.length()).split("_");
|
||||
|
||||
//Check for a valid number of parts
|
||||
if (dungeonData.length < 3 || dungeonData.length > 4)
|
||||
return false;
|
||||
|
||||
//Check if the dungeon type is valid
|
||||
if (!validateDungeonType(dungeonData[0], pack))
|
||||
return false;
|
||||
|
||||
//Check if the name is valid
|
||||
if (!SCHEMATIC_NAME_PATTERN.matcher(dungeonData[1]).matches())
|
||||
return false;
|
||||
|
||||
//Check if the open/closed flag is present
|
||||
if (!dungeonData[2].equalsIgnoreCase("open") && !dungeonData[2].equalsIgnoreCase("closed"))
|
||||
return false;
|
||||
|
||||
//If the weight is present, check that it is valid
|
||||
if (dungeonData.length == 4)
|
||||
{
|
||||
try
|
||||
{
|
||||
int weight = Integer.parseInt(dungeonData[3]);
|
||||
if (weight < MIN_DUNGEON_WEIGHT || weight > MAX_DUNGEON_WEIGHT)
|
||||
return false;
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
//Not a number
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void registerDungeon(String schematicPath, DungeonPack pack, boolean isInternal, boolean verbose)
|
||||
{
|
||||
//We use schematicPath as the real path for internal files (inside our JAR) because it seems
|
||||
//that File tries to interpret it as a local drive path and mangles it.
|
||||
File schematicFile = new File(schematicPath);
|
||||
String name = schematicFile.getName();
|
||||
String path = isInternal ? schematicPath : schematicFile.getAbsolutePath();
|
||||
try
|
||||
{
|
||||
if (validateSchematicName(name, pack))
|
||||
{
|
||||
//Strip off the file extension while splitting the file name
|
||||
String[] dungeonData = name.substring(0, name.length() - SCHEMATIC_FILE_EXTENSION.length()).split("_");
|
||||
|
||||
DungeonType dungeonType = pack.getType(dungeonData[0]);
|
||||
boolean isOpen = dungeonData[2].equalsIgnoreCase("open");
|
||||
int weight = (dungeonData.length == 4) ? Integer.parseInt(dungeonData[3]) : DEFAULT_DUNGEON_WEIGHT;
|
||||
|
||||
//Add this custom dungeon to the list corresponding to its type
|
||||
DungeonData dungeon = new DungeonData(path, isInternal, dungeonType, isOpen, weight);
|
||||
|
||||
pack.addDungeon(dungeon);
|
||||
registeredDungeons.add(dungeon);
|
||||
if (verbose)
|
||||
{
|
||||
System.out.println("Registered dungeon: " + name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
System.out.println("The following dungeon name is invalid for its given pack. It will not be generated naturally: " + schematicPath);
|
||||
}
|
||||
untaggedDungeons.add(new DungeonData(path, isInternal, DungeonType.UNKNOWN_TYPE, true, DEFAULT_DUNGEON_WEIGHT));
|
||||
System.out.println("Registered untagged dungeon: " + name);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Failed to register dungeon: " + name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCustomDungeons(String path, DungeonPackConfigReader reader)
|
||||
{
|
||||
File[] schematics;
|
||||
File[] packDirectories;
|
||||
File[] packFiles;
|
||||
ArrayList<String> packFilePaths;
|
||||
File directory = new File(path);
|
||||
FileFilter schematicFileFilter = new FileFilters.FileExtensionFilter(SCHEMATIC_FILE_EXTENSION);
|
||||
|
||||
//Check that the Ruins pack has been loaded
|
||||
if (RuinsPack == null)
|
||||
{
|
||||
throw new IllegalStateException("Cannot register custom dungeons without first loading the Ruins dungeon pack.");
|
||||
}
|
||||
|
||||
//Load stray dungeons directly in the custom dungeons folder
|
||||
schematics = directory.listFiles(schematicFileFilter);
|
||||
if (schematics != null)
|
||||
{
|
||||
for (File schematicFile : schematics)
|
||||
{
|
||||
registerDungeon(schematicFile.getPath(), RuinsPack, false, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Could not retrieve the list of schematics stored in the custom dungeons directory!");
|
||||
}
|
||||
schematics = null; //Release memory
|
||||
|
||||
//Load the custom dungeon packs
|
||||
packDirectories = directory.listFiles(new FileFilters.DirectoryFilter());
|
||||
if (packDirectories != null)
|
||||
{
|
||||
//Loop through each directory, which is assumed to be a dungeon pack
|
||||
for (File packDirectory : packDirectories)
|
||||
{
|
||||
//List the schematics within the dungeon pack directory
|
||||
packFiles = packDirectory.listFiles(schematicFileFilter);
|
||||
if (packFiles != null)
|
||||
{
|
||||
//Copy the pack files' paths into an ArrayList for use with registerDungeonPack()
|
||||
packFilePaths = new ArrayList<String>(packFiles.length);
|
||||
for (File packFile : packFiles)
|
||||
{
|
||||
packFilePaths.add(packFile.getPath());
|
||||
}
|
||||
|
||||
registerDungeonPack(packDirectory.getAbsolutePath(), packFilePaths, false, true, reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Could not retrieve the list of schematics in a dungeon pack: " + packDirectory.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Could not retrieve the list of dungeon pack directories in the custom dungeons directory!");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBundledDungeons(DungeonPackConfigReader reader)
|
||||
{
|
||||
//Register the core schematics
|
||||
//These are used for debugging and in case of unusual errors while loading dungeons
|
||||
defaultError = new DungeonData(DEFAULT_ERROR_SCHEMATIC_PATH, true, DungeonType.UNKNOWN_TYPE, true, DEFAULT_DUNGEON_WEIGHT);
|
||||
|
||||
//Open the list of dungeons packaged with our mod and register their schematics
|
||||
registerBundledPack(BUNDLED_RUINS_LIST_PATH, RUINS_PACK_PATH, "Ruins", reader);
|
||||
RuinsPack = getDungeonPack("Ruins");
|
||||
|
||||
System.out.println("Finished registering bundled dungeon packs");
|
||||
}
|
||||
|
||||
private void registerBundledPack(String listPath, String packPath, String name, DungeonPackConfigReader reader)
|
||||
{
|
||||
System.out.println("Registering bundled dungeon pack: " + name);
|
||||
|
||||
InputStream listStream = this.getClass().getResourceAsStream(listPath);
|
||||
// chance of leak?
|
||||
if (listStream == null)
|
||||
{
|
||||
System.err.println("Unable to open list of bundled dungeon schematics for " + name);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//Read the list of schematics that come with a bundled pack
|
||||
BufferedReader listReader = new BufferedReader(new InputStreamReader(listStream));
|
||||
ArrayList<String> schematics = new ArrayList<String>();
|
||||
String schematicPath = listReader.readLine();
|
||||
while (schematicPath != null)
|
||||
{
|
||||
schematicPath = schematicPath.trim();
|
||||
if (!schematicPath.isEmpty())
|
||||
{
|
||||
schematics.add(schematicPath);
|
||||
}
|
||||
schematicPath = listReader.readLine();
|
||||
}
|
||||
listReader.close();
|
||||
|
||||
//Register the pack
|
||||
registerDungeonPack(packPath, schematics, true, false, reader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("An exception occurred while reading the list of bundled dungeon schematics for " + name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean exportDungeon(World world, int centerX, int centerY, int centerZ, String exportPath)
|
||||
{
|
||||
//Write schematic data to a file
|
||||
try
|
||||
{
|
||||
DungeonSchematic dungeon = DungeonSchematic.copyFromWorld(world,
|
||||
centerX - MAX_EXPORT_RADIUS, centerY - MAX_EXPORT_RADIUS, centerZ - MAX_EXPORT_RADIUS,
|
||||
MAX_DUNGEON_WIDTH, MAX_DUNGEON_HEIGHT, MAX_DUNGEON_LENGTH, true);
|
||||
dungeon.applyExportFilters(properties);
|
||||
dungeon.writeToFile(exportPath);
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public DungeonData selectDungeon(NewDimData dimension, Random random)
|
||||
{
|
||||
DungeonPack pack = getDimDungeonPack(dimension);
|
||||
DungeonData selection;
|
||||
DungeonPackConfig config;
|
||||
DungeonPack selectedPack;
|
||||
|
||||
try
|
||||
{
|
||||
config = pack.getConfig();
|
||||
selectedPack = pack;
|
||||
|
||||
//Are we allowed to switch to another dungeon pack?
|
||||
if (config.allowPackChangeOut())
|
||||
{
|
||||
//Calculate the chance of switching to a different pack type
|
||||
int packSwitchChance;
|
||||
if (dimension.depth() == 1)
|
||||
{
|
||||
packSwitchChance = START_PACK_SWITCH_CHANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
packSwitchChance = MIN_PACK_SWITCH_CHANCE + dimension.parent().packDepth() * PACK_SWITCH_CHANCE_PER_LEVEL;
|
||||
}
|
||||
|
||||
//Decide randomly whether to switch packs or not
|
||||
if (random.nextInt(MAX_PACK_SWITCH_CHANCE) < packSwitchChance)
|
||||
{
|
||||
//Find another pack
|
||||
selectedPack = getRandomDungeonPack(pack, random);
|
||||
}
|
||||
}
|
||||
|
||||
//Pick the next dungeon
|
||||
selection = selectedPack.getNextDungeon(dimension, random);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("An exception occurred while selecting a dungeon:");
|
||||
e.printStackTrace();
|
||||
|
||||
if (!pack.isEmpty())
|
||||
{
|
||||
selection = pack.getRandomDungeon(random);
|
||||
}
|
||||
else
|
||||
{
|
||||
selection = defaultError;
|
||||
}
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DungeonPack getRandomDungeonPack(DungeonPack current, Random random)
|
||||
{
|
||||
DungeonPack selection = current;
|
||||
ArrayList<WeightedContainer<DungeonPack>> packs = new ArrayList<WeightedContainer<DungeonPack>>(dungeonPackList.size());
|
||||
|
||||
//Load up a list of weighted items with any usable dungeon packs that is not the current pack
|
||||
for (DungeonPack pack : dungeonPackList)
|
||||
{
|
||||
DungeonPackConfig config = pack.getConfig();
|
||||
if (pack != current && config.allowPackChangeIn() && !pack.isEmpty())
|
||||
{
|
||||
packs.add(new WeightedContainer<DungeonPack>(pack, config.getPackWeight()));
|
||||
}
|
||||
}
|
||||
if (!packs.isEmpty())
|
||||
{
|
||||
//Pick a random dungeon pack
|
||||
selection = ((WeightedContainer<DungeonPack>) WeightedRandom.getRandomItem(random, packs)).getData();
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
public Collection<String> getDungeonNames() {
|
||||
|
||||
//Use a HashSet to guarantee that all dungeon names will be distinct.
|
||||
//This shouldn't be necessary if we keep proper lists without repetitions,
|
||||
//but it's a fool-proof workaround.
|
||||
HashSet<String> dungeonNames = new HashSet<String>();
|
||||
dungeonNames.addAll( parseDungeonNames(registeredDungeons) );
|
||||
dungeonNames.addAll( parseDungeonNames(untaggedDungeons) );
|
||||
|
||||
//Sort dungeon names alphabetically
|
||||
ArrayList<String> sortedNames = new ArrayList<String>(dungeonNames);
|
||||
Collections.sort(sortedNames, String.CASE_INSENSITIVE_ORDER);
|
||||
return sortedNames;
|
||||
}
|
||||
|
||||
private static ArrayList<String> parseDungeonNames(ArrayList<DungeonData> dungeons)
|
||||
{
|
||||
String name;
|
||||
File schematic;
|
||||
ArrayList<String> names = new ArrayList<String>(dungeons.size());
|
||||
|
||||
for (DungeonData dungeon : dungeons)
|
||||
{
|
||||
//Retrieve the file name and strip off the file extension
|
||||
schematic = new File(dungeon.schematicPath());
|
||||
name = schematic.getName();
|
||||
name = name.substring(0, name.length() - SCHEMATIC_FILE_EXTENSION.length());
|
||||
names.add(name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public static ArrayList<DungeonData> getDungeonChainHistory(NewDimData dimension, DungeonPack pack, int maxSize)
|
||||
{
|
||||
if (dimension == null)
|
||||
{
|
||||
throw new IllegalArgumentException("dimension cannot be null.");
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
NewDimData tail = dimension;
|
||||
DungeonData dungeon = tail.dungeon();
|
||||
ArrayList<DungeonData> history = new ArrayList<DungeonData>();
|
||||
|
||||
while (count < maxSize && dungeon != null && dungeon.dungeonType().Owner == pack)
|
||||
{
|
||||
history.add(dungeon);
|
||||
tail = tail.parent();
|
||||
dungeon = tail.dungeon();
|
||||
count++;
|
||||
}
|
||||
return history;
|
||||
}
|
||||
|
||||
public static ArrayList<DungeonData> getFlatDungeonTree(NewDimData dimension, int maxSize)
|
||||
{
|
||||
NewDimData root = dimension;
|
||||
ArrayList<DungeonData> dungeons = new ArrayList<DungeonData>();
|
||||
Queue<NewDimData> pendingDimensions = new LinkedList<NewDimData>();
|
||||
|
||||
if (root.dungeon() == null)
|
||||
{
|
||||
return dungeons;
|
||||
}
|
||||
pendingDimensions.add(root);
|
||||
|
||||
while (dungeons.size() < maxSize && !pendingDimensions.isEmpty())
|
||||
{
|
||||
NewDimData current = pendingDimensions.remove();
|
||||
for (NewDimData child : current.children())
|
||||
{
|
||||
if (child.dungeon() != null)
|
||||
{
|
||||
dungeons.add(child.dungeon());
|
||||
pendingDimensions.add(child);
|
||||
}
|
||||
if (dungeons.size() == maxSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dungeons;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class copyfile
|
||||
{
|
||||
public static boolean copyFile(String ori, String dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Note: For this to work properly, you must use getClass() on an instance of the class,
|
||||
//not on the value obtained from .class. That was what caused this code to fail before.
|
||||
//SchematicLoader didn't have this problem because we used instances of it.
|
||||
InputStream in = mod_pocketDim.instance.getClass().getResourceAsStream(ori);
|
||||
OutputStream out = new FileOutputStream(dest);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Unable to get resource: " + ori);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package StevenDimDoors.mod_pocketDim.helpers;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
|
||||
public class yCoordHelper
|
||||
{
|
||||
private static final int MAXIMUM_UNCOVERED_Y = 245;
|
||||
|
||||
private yCoordHelper() { }
|
||||
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z)
|
||||
{
|
||||
return getFirstUncovered(world, x, yStart, z, false);
|
||||
}
|
||||
|
||||
public static int getFirstUncovered(World world, int x, int yStart, int z, boolean fromTop)
|
||||
{
|
||||
Chunk chunk = world.getChunkProvider().loadChunk(x >> 4, z >> 4);
|
||||
|
||||
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
|
||||
int height = MAXIMUM_UNCOVERED_Y;
|
||||
int y;
|
||||
|
||||
if (!fromTop)
|
||||
{
|
||||
boolean covered = true;
|
||||
for (y = yStart; y < height && covered; y++)
|
||||
{
|
||||
covered = isCoveredBlock(chunk, localX, y - 1, localZ) || isCoveredBlock(chunk, localX, y, localZ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean covered = false;
|
||||
for (y = MAXIMUM_UNCOVERED_Y; y > 1 && !covered; y--)
|
||||
{
|
||||
covered = isCoveredBlock(chunk, localX, y - 1, localZ);
|
||||
}
|
||||
if (!covered) y = 63;
|
||||
y++;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
public static boolean isCoveredBlock(Chunk chunk, int localX, int y, int localZ)
|
||||
{
|
||||
int blockID;
|
||||
Block block;
|
||||
Material material;
|
||||
|
||||
if (y < 0)
|
||||
return false;
|
||||
|
||||
blockID = chunk.getBlockID(localX, y, localZ);
|
||||
if (blockID == 0)
|
||||
return false;
|
||||
|
||||
block = Block.blocksList[blockID];
|
||||
if (block == null)
|
||||
return false;
|
||||
|
||||
material = block.blockMaterial;
|
||||
return (material.isLiquid() || !material.isReplaceable());
|
||||
}
|
||||
|
||||
public static Point3D findSafeCubeUp(World world, int x, int startY, int z)
|
||||
{
|
||||
// Search for a 3x3x3 cube of air with blocks underneath
|
||||
// We can also match against a 3x2x3 box with
|
||||
// We shift the search area into the bounds of a chunk for the sake of simplicity,
|
||||
// so that we don't need to worry about working across chunks.
|
||||
|
||||
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
|
||||
int cornerX = x - localX;
|
||||
int cornerZ = z - localZ;
|
||||
localX = MathHelper.clamp_int(localX, 1, 14);
|
||||
localZ = MathHelper.clamp_int(localZ, 1, 14);
|
||||
|
||||
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
|
||||
|
||||
int height = world.getActualHeight();
|
||||
int y, dx, dz, blockID;
|
||||
boolean isSafe;
|
||||
Block block;
|
||||
|
||||
// Initialize layers to a huge negative number so that we won't
|
||||
// consider an area as usable unless it gets reset to 0 first
|
||||
// when we find a foundation upon which to build.
|
||||
int layers = -1000000;
|
||||
|
||||
// Check if a 3x3 layer of blocks is empty
|
||||
// If we find a layer that contains replaceable blocks, it can
|
||||
// serve as the base where we'll place the player and door.
|
||||
for (y = Math.max(startY - 1, 0); y < height; y++)
|
||||
{
|
||||
isSafe = true;
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++)
|
||||
{
|
||||
blockID = chunk.getBlockID(localX + dx, y, localZ + dz);
|
||||
if (blockID != 0)
|
||||
{
|
||||
block = Block.blocksList[blockID];
|
||||
if (!block.blockMaterial.isReplaceable())
|
||||
{
|
||||
isSafe = false;
|
||||
}
|
||||
layers = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSafe)
|
||||
{
|
||||
layers++;
|
||||
if (layers == 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y - 2, localZ + cornerZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Point3D findSafeCubeDown(World world, int x, int startY, int z)
|
||||
{
|
||||
// Search for a 3x3x3 cube of air with blocks underneath
|
||||
// We can also match against a 3x2x3 box with
|
||||
// We shift the search area into the bounds of a chunk for the sake of simplicity,
|
||||
// so that we don't need to worry about working across chunks.
|
||||
|
||||
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
|
||||
int cornerX = x - localX;
|
||||
int cornerZ = z - localZ;
|
||||
localX = MathHelper.clamp_int(localX, 1, 14);
|
||||
localZ = MathHelper.clamp_int(localZ, 1, 14);
|
||||
|
||||
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
|
||||
|
||||
int height = world.getActualHeight();
|
||||
int y, dx, dz, blockID;
|
||||
boolean isSafe;
|
||||
boolean hasBlocks;
|
||||
Block block;
|
||||
int layers = 0;
|
||||
|
||||
// Check if a 3x3 layer of blocks is empty
|
||||
// If we find a layer that contains replaceable blocks, it can
|
||||
// serve as the base where we'll place the player and door.
|
||||
for (y = Math.min(startY + 2, height - 1); y >= 0; y--)
|
||||
{
|
||||
isSafe = true;
|
||||
hasBlocks = false;
|
||||
for (dx = -1; dx <= 1 && isSafe; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1 && isSafe; dz++)
|
||||
{
|
||||
blockID = chunk.getBlockID(localX + dx, y, localZ + dz);
|
||||
if (blockID != 0)
|
||||
{
|
||||
block = Block.blocksList[blockID];
|
||||
if (!block.blockMaterial.isReplaceable())
|
||||
{
|
||||
if (layers >= 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y + 1, localZ + cornerZ);
|
||||
}
|
||||
isSafe = false;
|
||||
}
|
||||
hasBlocks = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSafe)
|
||||
{
|
||||
layers++;
|
||||
if (hasBlocks)
|
||||
{
|
||||
if (layers >= 3)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y, localZ + cornerZ);
|
||||
}
|
||||
layers = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Chunk initializeChunkArea(World world, int chunkX, int chunkZ)
|
||||
{
|
||||
// We initialize a 3x3 area of chunks instead of just initializing
|
||||
// the target chunk because things generated in adjacent chunks
|
||||
// (e.g. trees) might intrude into the target chunk.
|
||||
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk target = provider.loadChunk(chunkX, chunkZ);
|
||||
for (int dx = -1; dx <= 1; dx++)
|
||||
{
|
||||
for (int dz = -1; dz <= 1; dz++)
|
||||
{
|
||||
if (!provider.chunkExists(chunkX + dx, chunkZ + dz))
|
||||
{
|
||||
provider.loadChunk(chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public static Point3D findDropPoint(World world, int x, int startY, int z)
|
||||
{
|
||||
// Find a simple 2-block-high air gap
|
||||
// Search across a 3x3 column
|
||||
final int GAP_HEIGHT = 2;
|
||||
|
||||
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
|
||||
int cornerX = x - localX;
|
||||
int cornerZ = z - localZ;
|
||||
localX = MathHelper.clamp_int(localX, 1, 14);
|
||||
localZ = MathHelper.clamp_int(localZ, 1, 14);
|
||||
|
||||
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
|
||||
|
||||
int y, dx, dz, index;
|
||||
int height = world.getActualHeight();
|
||||
int[] gaps = new int[9];
|
||||
|
||||
// Check 3x3 layers of blocks for air spaces
|
||||
for (y = Math.min(startY, height - 1); y > 0; y--)
|
||||
{
|
||||
for (dx = -1, index = 0; dx <= 1; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1; dz++, index++)
|
||||
{
|
||||
if (chunk.getBlockID(localX + dx, y, localZ + dz) != 0)
|
||||
{
|
||||
gaps[index] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gaps[index]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if an acceptable gap exists in the center of the search column
|
||||
if (gaps[index / 2] == GAP_HEIGHT)
|
||||
{
|
||||
return new Point3D(localX + cornerX, y + GAP_HEIGHT - 1, localZ + cornerZ);
|
||||
}
|
||||
// Check the other positions in the column
|
||||
for (dx = -1, index = 0; dx <= 1; dx++)
|
||||
{
|
||||
for (dz = -1; dz <= 1; dz++, index++)
|
||||
{
|
||||
if (gaps[index] == GAP_HEIGHT)
|
||||
{
|
||||
return new Point3D(localX + cornerX + dx, y + GAP_HEIGHT - 1, localZ + cornerZ + dz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight)
|
||||
{
|
||||
//The goal here is to guarantee that the dungeon fits within the vertical bounds
|
||||
//of the world while shifting it as little as possible.
|
||||
int destY = y;
|
||||
|
||||
//Is the top of the dungeon going to be at Y < worldHeight?
|
||||
int pocketTop = (dungeonHeight - 1) + destY - entranceY;
|
||||
if (pocketTop >= worldHeight)
|
||||
{
|
||||
destY = (worldHeight - 1) - (dungeonHeight - 1) + entranceY;
|
||||
}
|
||||
|
||||
//Is the bottom of the dungeon at Y >= 0?
|
||||
if (destY < entranceY)
|
||||
{
|
||||
destY = entranceY;
|
||||
}
|
||||
return destY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemDoor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
|
||||
public abstract class BaseItemDoor extends ItemDoor
|
||||
{
|
||||
private static DDProperties properties = null;
|
||||
|
||||
public BaseItemDoor(int itemID, Material material)
|
||||
{
|
||||
super(itemID, material);
|
||||
this.setMaxStackSize(64);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
if (properties == null)
|
||||
properties = DDProperties.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", ""));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@Override
|
||||
public abstract void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4);
|
||||
|
||||
@Override
|
||||
public abstract boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ);
|
||||
|
||||
public static boolean tryItemUse(Block doorBlock, ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, boolean requireLink, boolean reduceStack)
|
||||
{
|
||||
// Only place doors on top of blocks - check if we're targeting the top side
|
||||
if (side == 1 && !world.isRemote)
|
||||
{
|
||||
int blockID = world.getBlockId(x, y, z);
|
||||
if (blockID != 0)
|
||||
{
|
||||
if (!Block.blocksList[blockID].isBlockReplaceable(world, x, y, z))
|
||||
{
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
if (canPlace(world, x, y, z) && canPlace(world, x, y + 1, z) &&
|
||||
player.canPlayerEdit(x, y, z, side, stack) && player.canPlayerEdit(x, y + 1, z, side, stack) &&
|
||||
(!requireLink || PocketManager.getLink(x, y + 1, z, world) != null)&&stack.stackSize>0)
|
||||
{
|
||||
int orientation = MathHelper.floor_double((player.rotationYaw + 180.0F) * 4.0F / 360.0F - 0.5D) & 3;
|
||||
placeDoorBlock(world, x, y, z, orientation, doorBlock);
|
||||
|
||||
if (!player.capabilities.isCreativeMode && reduceStack)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player);
|
||||
|
||||
public boolean tryPlacingDoor(Block doorBlock, World world, EntityPlayer player, ItemStack item)
|
||||
{
|
||||
if (world.isRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MovingObjectPosition hit = this.getMovingObjectPositionFromPlayer(player.worldObj, player, true);
|
||||
if (hit != null)
|
||||
{
|
||||
if (world.getBlockId(hit.blockX, hit.blockY, hit.blockZ) == properties.RiftBlockID)
|
||||
{
|
||||
DimLink link = PocketManager.getLink(hit.blockX, hit.blockY, hit.blockZ, world.provider.dimensionId);
|
||||
if (link != null)
|
||||
{
|
||||
int x = hit.blockX;
|
||||
int y = hit.blockY;
|
||||
int z = hit.blockZ;
|
||||
|
||||
if (player.canPlayerEdit(x, y, z, hit.sideHit, item) && player.canPlayerEdit(x, y - 1, z, hit.sideHit, item))
|
||||
{
|
||||
if (canPlace(world, x, y, z) && canPlace(world, x, y - 1, z))
|
||||
{
|
||||
int orientation = MathHelper.floor_double(((player.rotationYaw + 180.0F) * 4.0F / 360.0F) - 0.5D) & 3;
|
||||
placeDoorBlock(world, x, y - 1, z, orientation, doorBlock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean canPlace(World world, int x, int y, int z)
|
||||
{
|
||||
int id = world.getBlockId(x, y, z);
|
||||
|
||||
return (id == properties.RiftBlockID || id == 0 || Block.blocksList[id].blockMaterial.isReplaceable());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemBlockDimWall extends ItemBlock
|
||||
{
|
||||
private final static String[] subNames = {"Fabric of Reality", "Ancient Fabric"};
|
||||
|
||||
public ItemBlockDimWall(int par1)
|
||||
{
|
||||
super(par1);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
setHasSubtypes(true);
|
||||
}
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("tile.", ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetadata (int damageValue)
|
||||
{
|
||||
return damageValue;
|
||||
}
|
||||
|
||||
public String getUnlocalizedName(ItemStack par1ItemStack)
|
||||
{
|
||||
return subNames[this.getDamage(par1ItemStack)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemDimensionalDoor extends BaseItemDoor
|
||||
{
|
||||
public ItemDimensionalDoor(int itemID, Material material)
|
||||
{
|
||||
super(itemID, material);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Place on the block under a rift");
|
||||
par3List.add("to activate that rift or place");
|
||||
par3List.add("anywhere else to create a");
|
||||
par3List.add("pocket dimension.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
if (tryPlacingDoor(mod_pocketDim.dimensionalDoor, world, player, stack) &&
|
||||
!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y,
|
||||
int z, int par7, float par8, float par9, float par10)
|
||||
{
|
||||
return tryItemUse(mod_pocketDim.dimensionalDoor, stack, player, world, x, y, z, par7, false, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemGoldDimDoor extends BaseItemDoor
|
||||
{
|
||||
|
||||
public ItemGoldDimDoor(int itemID, Material material) {
|
||||
super(itemID, material);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Similar to a Iron Dim Door");
|
||||
par3List.add("But if present in a pocket dim");
|
||||
par3List.add("it will keep it loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y,
|
||||
int z, int par7, float par8, float par9, float par10)
|
||||
{
|
||||
return tryItemUse(mod_pocketDim.goldDimDoor, stack, player, world, x, y, z, par7, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
if (tryPlacingDoor(mod_pocketDim.goldDimDoor, world, player, stack) &&
|
||||
!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemDoor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ItemGoldDoor extends ItemDoor
|
||||
{
|
||||
public ItemGoldDoor(int par1, Material par2Material)
|
||||
{
|
||||
super(par1, par2Material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
|
||||
{
|
||||
if (par7 != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++par5;
|
||||
Block block = mod_pocketDim.goldDoor;
|
||||
|
||||
if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack) && par2EntityPlayer.canPlayerEdit(par4, par5 + 1, par6, par7, par1ItemStack))
|
||||
{
|
||||
if (!block.canPlaceBlockAt(par3World, par4, par5, par6))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i1 = MathHelper.floor_double((par2EntityPlayer.rotationYaw + 180.0F) * 4.0F / 360.0F - 0.5D) & 3;
|
||||
placeDoorBlock(par3World, par4, par5, par6, i1, block);
|
||||
--par1ItemStack.stackSize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.SharedMonsterAttributes;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.EnumToolMaterial;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemSword;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import com.google.common.collect.Multimap;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ItemRiftBlade extends ItemSword
|
||||
{
|
||||
private final DDProperties properties;
|
||||
|
||||
public ItemRiftBlade(int itemID, EnumToolMaterial material, DDProperties properties)
|
||||
{
|
||||
super(itemID, material);
|
||||
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
this.setMaxStackSize(1);
|
||||
this.setMaxDamage(500);
|
||||
this.hasSubtypes = false;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isFull3D()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block)
|
||||
{
|
||||
if (par2Block.blockID == Block.web.blockID)
|
||||
{
|
||||
return 15.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
Material material = par2Block.blockMaterial;
|
||||
return material != Material.plants && material != Material.vine && material != Material.coral && material != Material.leaves && material != Material.pumpkin ? 1.0F : 1.5F;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap getItemAttributeModifiers()
|
||||
{
|
||||
Multimap multimap = super.getItemAttributeModifiers();
|
||||
multimap.put(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName(), new AttributeModifier(field_111210_e, "Weapon modifier", (double)7, 0));
|
||||
return multimap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean hasEffect(ItemStack par1ItemStack)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hitEntity(ItemStack par1ItemStack, EntityLivingBase par2EntityLiving, EntityLivingBase par3EntityLiving)
|
||||
{
|
||||
par1ItemStack.damageItem(1, par3EntityLiving);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovingObjectPosition getMovingObjectPositionFromPlayer(World par1World, EntityPlayer par2EntityPlayer, boolean par3)
|
||||
{
|
||||
float var4 = 1.0F;
|
||||
float var5 = par2EntityPlayer.prevRotationPitch + (par2EntityPlayer.rotationPitch - par2EntityPlayer.prevRotationPitch) * var4;
|
||||
float var6 = par2EntityPlayer.prevRotationYaw + (par2EntityPlayer.rotationYaw - par2EntityPlayer.prevRotationYaw) * var4;
|
||||
double var7 = par2EntityPlayer.prevPosX + (par2EntityPlayer.posX - par2EntityPlayer.prevPosX) * var4;
|
||||
double var9 = par2EntityPlayer.prevPosY + (par2EntityPlayer.posY - par2EntityPlayer.prevPosY) * var4 + 1.62D - par2EntityPlayer.yOffset;
|
||||
double var11 = par2EntityPlayer.prevPosZ + (par2EntityPlayer.posZ - par2EntityPlayer.prevPosZ) * var4;
|
||||
Vec3 var13 = par1World.getWorldVec3Pool().getVecFromPool(var7, var9, var11);
|
||||
float var14 = MathHelper.cos(-var6 * 0.017453292F - (float)Math.PI);
|
||||
float var15 = MathHelper.sin(-var6 * 0.017453292F - (float)Math.PI);
|
||||
float var16 = -MathHelper.cos(-var5 * 0.017453292F);
|
||||
float var17 = MathHelper.sin(-var5 * 0.017453292F);
|
||||
float var18 = var15 * var16;
|
||||
float var20 = var14 * var16;
|
||||
double var21 = 5.0D;
|
||||
if (par2EntityPlayer instanceof EntityPlayerMP)
|
||||
{
|
||||
var21 = 7;
|
||||
}
|
||||
Vec3 var23 = var13.addVector(var18 * var21, var17 * var21, var20 * var21);
|
||||
return par1World.rayTraceBlocks_do_do(var13, var23, true, false);
|
||||
}
|
||||
|
||||
private boolean teleportToEntity(ItemStack item, Entity par1Entity, EntityPlayer holder)
|
||||
{
|
||||
Vec3 var2 = holder.worldObj.getWorldVec3Pool().getVecFromPool(holder.posX - par1Entity.posX, holder.boundingBox.minY + holder.height / 2.0F - par1Entity.posY + par1Entity.getEyeHeight(), holder.posZ - par1Entity.posZ);
|
||||
|
||||
double cooef =( var2.lengthVector()-2.5)/var2.lengthVector();
|
||||
var2.xCoord*=cooef;
|
||||
var2.yCoord*=cooef;
|
||||
var2.zCoord*=cooef;
|
||||
double var5 = holder.posX - var2.xCoord;
|
||||
double var9 = holder.posZ - var2.zCoord;
|
||||
|
||||
|
||||
double var7 = MathHelper.floor_double(holder.posY - var2.yCoord) ;
|
||||
|
||||
int var14 = MathHelper.floor_double(var5);
|
||||
int var15 = MathHelper.floor_double(var7);
|
||||
int var16 = MathHelper.floor_double(var9);
|
||||
while(!holder.worldObj.isAirBlock(var14, var15, var16))
|
||||
{
|
||||
var15++;
|
||||
}
|
||||
var7=var15;
|
||||
|
||||
|
||||
holder.setPositionAndUpdate(var5, var7, var9);
|
||||
holder.playSound("mob.endermen.portal", 1.0F, 1.0F);
|
||||
holder.worldObj.playSoundEffect(holder.posX, holder.posY, holder.posZ, "mob.endermen.portal", 1.0F, 1.0F);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<EntityLiving> list = world.getEntitiesWithinAABB(EntityLiving.class, AxisAlignedBB.getBoundingBox(player.posX-8,player.posY-8, player.posZ-8, player.posX+8,player.posY+8, player.posZ+8));
|
||||
list.remove(player);
|
||||
|
||||
for (EntityLiving ent : list)
|
||||
{
|
||||
Vec3 var3 = player.getLook(1.0F).normalize();
|
||||
Vec3 var4 = player.worldObj.getWorldVec3Pool().getVecFromPool(ent.posX - player.posX, ent.boundingBox.minY + (ent.height) / 2.0F - ( player.posY + player.getEyeHeight()), ent.posZ - player.posZ);
|
||||
double var5 = var4.lengthVector();
|
||||
var4 = var4.normalize();
|
||||
double var7 = var3.dotProduct(var4);
|
||||
if( (var7+.1) > 1.0D - 0.025D / var5 ? player.canEntityBeSeen(ent) : false)
|
||||
{
|
||||
teleportToEntity(stack, ent, player);
|
||||
stack.damageItem(3, player);
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
MovingObjectPosition hit = this.getMovingObjectPositionFromPlayer(world, player, false);
|
||||
if (hit != null)
|
||||
{
|
||||
int x = hit.blockX;
|
||||
int y = hit.blockY;
|
||||
int z = hit.blockZ;
|
||||
if (world.getBlockId(x, y, z) == properties.RiftBlockID)
|
||||
{
|
||||
if (PocketManager.getLink(x, y, z, world) != null)
|
||||
{
|
||||
if (player.canPlayerEdit(x, y, z, hit.sideHit, stack) &&
|
||||
player.canPlayerEdit(x, y + 1, z, hit.sideHit, stack))
|
||||
{
|
||||
int orientation = MathHelper.floor_double((player.rotationYaw + 180.0F) * 4.0F / 360.0F - 0.5D) & 3;
|
||||
|
||||
if (BaseItemDoor.canPlace(world, x, y, z) &&
|
||||
BaseItemDoor.canPlace(world, x, y - 1, z))
|
||||
{
|
||||
ItemDimensionalDoor.placeDoorBlock(world, x, y - 1, z, orientation, mod_pocketDim.transientDoor);
|
||||
player.worldObj.playSoundAtEntity(player,mod_pocketDim.modid+":riftDoor", 0.6f, 1);
|
||||
stack.damageItem(3, player);
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.setItemInUse(stack, this.getMaxItemUseDuration(stack));
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this item is repairable in an anvil.
|
||||
*/
|
||||
@Override
|
||||
public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack)
|
||||
{
|
||||
//Don't include a call to super.getIsRepairable()!
|
||||
//That would cause this sword to accept gold as a repair material (since we set material = Gold).
|
||||
return mod_pocketDim.itemStableFabric.itemID == par2ItemStack.itemID ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* allows items to add custom lines of information to the mouseover description
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Creates temporary doors");
|
||||
par3List.add("on rifts, rotates doors,");
|
||||
par3List.add("and has a teleport attack.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.EnumArmorMaterial;
|
||||
import net.minecraft.item.ItemArmor;
|
||||
|
||||
public class ItemRiftGoggles extends ItemArmor
|
||||
{
|
||||
|
||||
public ItemRiftGoggles(int par1, int par2, int par3)
|
||||
{
|
||||
super(par1, EnumArmorMaterial.IRON, par1, par1);
|
||||
this.setCreativeTab(CreativeTabs.tabRedstone);
|
||||
// this.setIconIndex(Item.doorWood.getIconFromDamage(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BaseDimDoor;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ItemRiftSignature extends Item
|
||||
{
|
||||
public ItemRiftSignature(int itemID)
|
||||
{
|
||||
super(itemID);
|
||||
this.setMaxStackSize(1);
|
||||
this.setMaxDamage(0);
|
||||
this.hasSubtypes = true;
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public boolean hasEffect(ItemStack stack)
|
||||
{
|
||||
//Make the item glow if it has one endpoint stored
|
||||
return (stack.getItemDamage() != 0);
|
||||
}
|
||||
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
//TODO- recognize doors and intelligently place rifts on them.
|
||||
// We must use onItemUseFirst() instead of onItemUse() because Minecraft checks
|
||||
// whether the user is in creative mode after calling onItemUse() and undoes any
|
||||
// damage we might set to indicate the rift sig has been activated. Otherwise,
|
||||
// we would need to rely on checking NBT tags for hasEffect() and that function
|
||||
// gets called constantly. Avoiding NBT lookups reduces our performance impact.
|
||||
|
||||
// Return false on the client side to pass this request to the server
|
||||
if (world.isRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
y += 2; //Increase y by 2 to place the rift at head level
|
||||
if (!player.canPlayerEdit(x, y, z, side, stack))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int adjustedY = adjustYForSpecialBlocks(world,x,y,z);
|
||||
Point4DOrientation source = getSource(stack);
|
||||
int orientation = MathHelper.floor_double((double) ((player.rotationYaw + 180.0F) * 4.0F / 360.0F) - 0.5D) & 3;
|
||||
if (source != null)
|
||||
{
|
||||
//The link was used before and already has an endpoint stored. Create links connecting the two endpoints.
|
||||
NewDimData sourceDimension = PocketManager.getDimensionData(source.getDimension());
|
||||
NewDimData destinationDimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = sourceDimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.NORMAL,source.getOrientation());
|
||||
DimLink reverse = destinationDimension.createLink(x, adjustedY, z, LinkTypes.NORMAL,orientation);
|
||||
destinationDimension.setDestination(link, x, adjustedY, z);
|
||||
sourceDimension.setDestination(reverse, source.getX(), source.getY(), source.getZ());
|
||||
|
||||
//Try placing a rift at the destination point
|
||||
if (!mod_pocketDim.blockRift.isBlockImmune(world, x, adjustedY, z))
|
||||
{
|
||||
world.setBlock(x, adjustedY, z, mod_pocketDim.blockRift.blockID);
|
||||
}
|
||||
|
||||
//Try placing a rift at the source point, but check if its world is loaded first
|
||||
World sourceWorld = DimensionManager.getWorld(sourceDimension.id());
|
||||
if (sourceWorld != null &&
|
||||
!mod_pocketDim.blockRift.isBlockImmune(sourceWorld, source.getX(), source.getY(), source.getZ()))
|
||||
{
|
||||
sourceWorld.setBlock(source.getX(), source.getY(), source.getZ(), mod_pocketDim.blockRift.blockID);
|
||||
}
|
||||
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
clearSource(stack);
|
||||
mod_pocketDim.sendChat(player,("Rift Created"));
|
||||
world.playSoundAtEntity(player,mod_pocketDim.modid+":riftEnd", 0.6f, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//The link signature has not been used. Store its current target as the first location.
|
||||
setSource(stack, x, adjustedY, z,orientation, PocketManager.getDimensionData(world));
|
||||
mod_pocketDim.sendChat(player,("Location Stored in Rift Signature"));
|
||||
world.playSoundAtEntity(player,mod_pocketDim.modid+":riftStart", 0.6f, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* allows items to add custom lines of information to the mouseover description
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
Point4DOrientation source = getSource(par1ItemStack);
|
||||
if (source != null)
|
||||
{
|
||||
par3List.add("Leads to (" + source.getX() + ", " + source.getY() + ", " + source.getZ() + ") at dimension #" + source.getDimension());
|
||||
}
|
||||
else
|
||||
{
|
||||
par3List.add("First click stores a location;");
|
||||
par3List.add("second click creates a pair of");
|
||||
par3List.add("rifts linking the two locations.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the rift placement account for replaceable blocks and doors.
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return the adjusted y coord
|
||||
*/
|
||||
public static int adjustYForSpecialBlocks(World world, int x, int y, int z)
|
||||
{
|
||||
y=y-2;//get the block the player actually clicked on
|
||||
Block block = Block.blocksList[world.getBlockId(x, y, z)];
|
||||
if(block.isBlockReplaceable(world, x, y, z))
|
||||
{
|
||||
return y+1;//move block placement down (-2+1) one so its directly over things like snow
|
||||
}
|
||||
if(block instanceof BaseDimDoor)
|
||||
{
|
||||
if(world.getBlockId(x, y-1, z)==block.blockID&&world.getBlockMetadata(x, y, z)==8)
|
||||
{
|
||||
return y;//move rift placement down two so its in the right place on the door.
|
||||
}
|
||||
return y+1;
|
||||
}
|
||||
return y+2;
|
||||
}
|
||||
public static void setSource(ItemStack itemStack, int x, int y, int z, int orientation, NewDimData dimension)
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
|
||||
tag.setInteger("linkX", x);
|
||||
tag.setInteger("linkY", y);
|
||||
tag.setInteger("linkZ", z);
|
||||
tag.setInteger("orientation", orientation);
|
||||
tag.setInteger("linkDimID", dimension.id());
|
||||
|
||||
itemStack.setTagCompound(tag);
|
||||
itemStack.setItemDamage(1);
|
||||
}
|
||||
|
||||
public static void clearSource(ItemStack itemStack)
|
||||
{
|
||||
//Don't just set the tag to null since there may be other data there (e.g. for renamed items)
|
||||
NBTTagCompound tag = itemStack.getTagCompound();
|
||||
tag.removeTag("linkX");
|
||||
tag.removeTag("linkY");
|
||||
tag.removeTag("linkZ");
|
||||
tag.removeTag("orientation");
|
||||
tag.removeTag("linkDimID");
|
||||
itemStack.setItemDamage(0);
|
||||
}
|
||||
|
||||
public static Point4DOrientation getSource(ItemStack itemStack)
|
||||
{
|
||||
if (itemStack.getItemDamage() != 0)
|
||||
{
|
||||
if (itemStack.hasTagCompound())
|
||||
{
|
||||
NBTTagCompound tag = itemStack.getTagCompound();
|
||||
|
||||
Integer x = tag.getInteger("linkX");
|
||||
Integer y = tag.getInteger("linkY");
|
||||
Integer z = tag.getInteger("linkZ");
|
||||
Integer orientation = tag.getInteger("orientation");
|
||||
Integer dimID = tag.getInteger("linkDimID");
|
||||
|
||||
if (x != null && y != null && z != null && dimID != null)
|
||||
{
|
||||
return new Point4DOrientation(x, y, z,orientation, dimID);
|
||||
}
|
||||
}
|
||||
itemStack.setItemDamage(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class Point4DOrientation
|
||||
{
|
||||
private Point4D point;
|
||||
private int orientation;
|
||||
Point4DOrientation(int x, int y, int z, int orientation, int dimID)
|
||||
{
|
||||
this.point= new Point4D(x,y,z,dimID);
|
||||
this.orientation=orientation;
|
||||
}
|
||||
|
||||
int getX()
|
||||
{
|
||||
return point.getX();
|
||||
}
|
||||
|
||||
int getY()
|
||||
{
|
||||
return point.getY();
|
||||
}
|
||||
|
||||
int getZ()
|
||||
{
|
||||
return point.getZ();
|
||||
}
|
||||
|
||||
int getDimension()
|
||||
{
|
||||
return point.getDimension();
|
||||
}
|
||||
int getOrientation()
|
||||
{
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ItemStabilizedRiftSignature extends ItemRiftSignature
|
||||
{
|
||||
public ItemStabilizedRiftSignature(int itemID)
|
||||
{
|
||||
super(itemID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
// Return false on the client side to pass this request to the server
|
||||
if (world.isRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't check for replaceable blocks. The user can deal with that. <_<
|
||||
y += 2; //Increase y by 2 to place the rift at head level
|
||||
if (!player.canPlayerEdit(x, y, z, side, stack))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Point4DOrientation source = getSource(stack);
|
||||
int adjustedY = adjustYForSpecialBlocks(world,x,y,z);
|
||||
|
||||
// Check if the Stabilized Rift Signature has been initialized
|
||||
int orientation = MathHelper.floor_double((player.rotationYaw + 180.0F) * 4.0F / 360.0F - 0.5D) & 3;
|
||||
if (source != null)
|
||||
{
|
||||
// Yes, it's initialized. Check if the player is in creative
|
||||
// or if the player can pay an Ender Pearl to create a rift.
|
||||
if (!player.capabilities.isCreativeMode && !player.inventory.hasItem(Item.enderPearl.itemID))
|
||||
{
|
||||
mod_pocketDim.sendChat(player,"You don't have any Ender Pearls!");
|
||||
// I won't do this, but this is the chance to localize chat
|
||||
// messages sent to the player; look at ChatMessageComponent
|
||||
// and how MFR does it with items like the safari net launcher
|
||||
return true;
|
||||
}
|
||||
|
||||
//The link was used before and already has an endpoint stored. Create links connecting the two endpoints.
|
||||
NewDimData sourceDimension = PocketManager.getDimensionData(source.getDimension());
|
||||
NewDimData destinationDimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = sourceDimension.createLink(source.getX(), source.getY(), source.getZ(), LinkTypes.NORMAL,source.getOrientation());
|
||||
DimLink reverse = destinationDimension.createLink(x, adjustedY, z, LinkTypes.NORMAL,orientation);
|
||||
destinationDimension.setDestination(link, x, adjustedY, z);
|
||||
sourceDimension.setDestination(reverse, source.getX(), source.getY(), source.getZ());
|
||||
|
||||
//Try placing a rift at the destination point
|
||||
if (!mod_pocketDim.blockRift.isBlockImmune(world, x, adjustedY, z))
|
||||
{
|
||||
world.setBlock(x, adjustedY, z, mod_pocketDim.blockRift.blockID);
|
||||
}
|
||||
|
||||
//Try placing a rift at the source point, but check if its world is loaded first
|
||||
World sourceWorld = DimensionManager.getWorld(sourceDimension.id());
|
||||
if (sourceWorld != null &&
|
||||
!mod_pocketDim.blockRift.isBlockImmune(sourceWorld, source.getX(), source.getY(), source.getZ()))
|
||||
{
|
||||
sourceWorld.setBlock(source.getX(), source.getY(), source.getZ(), mod_pocketDim.blockRift.blockID);
|
||||
}
|
||||
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
{
|
||||
player.inventory.consumeInventoryItem(Item.enderPearl.itemID);
|
||||
}
|
||||
mod_pocketDim.sendChat(player,"Rift Created");
|
||||
world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftEnd", 0.6f, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//The link signature has not been used. Store its current target as the first location.
|
||||
setSource(stack, x, adjustedY, z, orientation, PocketManager.getDimensionData(world));
|
||||
mod_pocketDim.sendChat(player,"Location Stored in Rift Signature");
|
||||
world.playSoundAtEntity(player,"mods.DimDoors.sfx.riftStart", 0.6f, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* allows items to add custom lines of information to the mouseover description
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
Point4DOrientation source = getSource(par1ItemStack);
|
||||
if (source != null)
|
||||
{
|
||||
par3List.add("Leads to (" + source.getX() + ", " + source.getY() + ", " + source.getZ() + ") at dimension #" + source.getDimension());
|
||||
}
|
||||
else
|
||||
{
|
||||
par3List.add("First click stores a location,");
|
||||
par3List.add("second click creates two rifts");
|
||||
par3List.add("that link the locations together.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.item.Item;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemStableFabric extends Item
|
||||
{
|
||||
public ItemStableFabric(int itemID, int par2)
|
||||
{
|
||||
super(itemID);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", ""));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemUnstableDoor extends BaseItemDoor
|
||||
{
|
||||
public ItemUnstableDoor(int itemID, Material material)
|
||||
{
|
||||
super(itemID, material);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Caution: Leads to random destination");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
if (tryPlacingDoor(mod_pocketDim.unstableDoor, world, player, stack) &&
|
||||
!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y,
|
||||
int z, int par7, float par8, float par9, float par10)
|
||||
{
|
||||
return tryItemUse(mod_pocketDim.unstableDoor, stack, player, world, x, y, z, par7, false, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemWarpDoor extends BaseItemDoor
|
||||
{
|
||||
public ItemWarpDoor(int itemID, Material material)
|
||||
{
|
||||
super(itemID, material);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Place on the block under");
|
||||
par3List.add("a rift to create a portal,");
|
||||
par3List.add("or place anywhere in a");
|
||||
par3List.add("pocket dimension to exit.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
if (!world.isRemote)
|
||||
{
|
||||
if (tryPlacingDoor(mod_pocketDim.warpDoor, world, player, stack) &&
|
||||
!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.stackSize--;
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y,
|
||||
int z, int par7, float par8, float par9, float par10)
|
||||
{
|
||||
return tryItemUse(mod_pocketDim.warpDoor, stack, player, world, x, y, z, par7, false, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.item.Item;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class ItemWorldThread extends Item
|
||||
{
|
||||
public ItemWorldThread(int itemID)
|
||||
{
|
||||
super(itemID);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName().replace("item.", ""));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package StevenDimDoors.mod_pocketDim.items;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class itemRiftRemover extends Item
|
||||
{
|
||||
public itemRiftRemover(int itemID, Material par2Material)
|
||||
{
|
||||
super(itemID);
|
||||
this.setMaxStackSize(1);
|
||||
this.setCreativeTab(mod_pocketDim.dimDoorsCreativeTab);
|
||||
this.setMaxDamage(4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IconRegister par1IconRegister)
|
||||
{
|
||||
this.itemIcon = par1IconRegister.registerIcon(mod_pocketDim.modid + ":" + this.getUnlocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
|
||||
{
|
||||
// We invoke PlayerControllerMP.onPlayerRightClick() from here so that Minecraft
|
||||
// will invoke onItemUseFirst() on the client side. We'll tell it to pass the
|
||||
// request to the server, which will make sure that rift-related changes are
|
||||
// reflected on the server.
|
||||
|
||||
if (!world.isRemote)
|
||||
{
|
||||
return stack;
|
||||
}
|
||||
|
||||
MovingObjectPosition hit = this.getMovingObjectPositionFromPlayer(world, player, true);
|
||||
if (hit != null)
|
||||
{
|
||||
int hx = hit.blockX;
|
||||
int hy = hit.blockY;
|
||||
int hz = hit.blockZ;
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(hx, hy, hz);
|
||||
if (world.getBlockId(hx, hy, hz) == mod_pocketDim.blockRift.blockID && link != null &&
|
||||
player.canPlayerEdit(hx, hy, hz, hit.sideHit, stack))
|
||||
{
|
||||
// Invoke onPlayerRightClick()
|
||||
FMLClientHandler.instance().getClient().playerController.onPlayerRightClick(
|
||||
player, world, stack, hx, hy, hz, hit.sideHit, hit.hitVec);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
|
||||
{
|
||||
|
||||
// We want to use onItemUseFirst() here so that this code will run on the server side,
|
||||
// so we don't need the client to send link-related updates to the server. Still,
|
||||
// check whether we have a rift in sight before passing the request over.
|
||||
|
||||
// On integrated servers, the link won't be removed immediately because of the rift
|
||||
// removal animation. That means we'll have a chance to check for the link before
|
||||
// it's deleted. Otherwise the Rift Remover's durability wouldn't drop.
|
||||
MovingObjectPosition hit = this.getMovingObjectPositionFromPlayer(world, player, true);
|
||||
if (hit != null)
|
||||
{
|
||||
x = hit.blockX;
|
||||
y = hit.blockY;
|
||||
z = hit.blockZ;
|
||||
|
||||
NewDimData dimension = PocketManager.getDimensionData(world);
|
||||
DimLink link = dimension.getLink(x, y, z);
|
||||
if (world.getBlockId(x, y, z) == mod_pocketDim.blockRift.blockID && link != null &&
|
||||
player.canPlayerEdit(x, y, z, side, stack))
|
||||
{
|
||||
// Tell the rift's tile entity to do its removal animation
|
||||
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
|
||||
if (tileEntity != null && tileEntity instanceof TileEntityRift)
|
||||
{
|
||||
((TileEntityRift) tileEntity).shouldClose = true;
|
||||
tileEntity.onInventoryChanged();
|
||||
}
|
||||
else if (!world.isRemote)
|
||||
{
|
||||
// Only set the block to air on the server side so that we don't
|
||||
// tell the server to remove the rift block before it can use the
|
||||
// Rift Remover. Otherwise, it won't know to reduce durability.
|
||||
world.setBlockToAir(x, y, z);
|
||||
}
|
||||
if (world.isRemote)
|
||||
{
|
||||
// Tell the server about this
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
{
|
||||
stack.damageItem(1, player);
|
||||
}
|
||||
player.worldObj.playSoundAtEntity(player, mod_pocketDim.modid+":riftClose", 0.8f, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* allows items to add custom lines of information to the mouseover description
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
|
||||
{
|
||||
par3List.add("Use near exposed rift");
|
||||
par3List.add("to remove it and");
|
||||
par3List.add("any nearby rifts.");
|
||||
}
|
||||
}
|
||||
341
src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java
Normal file
341
src/main/java/StevenDimDoors/mod_pocketDim/mod_pocketDim.java
Normal file
@@ -0,0 +1,341 @@
|
||||
package StevenDimDoors.mod_pocketDim;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockDimWall;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockDimWallPerm;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockDoorGold;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockGoldDimDoor;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockLimbo;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.BlockRift;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.DimensionalDoor;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.TransTrapdoor;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.TransientDoor;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.UnstableDoor;
|
||||
import StevenDimDoors.mod_pocketDim.blocks.WarpDoor;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandCreateDungeonRift;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandCreatePocket;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandDeleteAllLinks;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandDeleteRifts;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandExportDungeon;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandResetDungeons;
|
||||
import StevenDimDoors.mod_pocketDim.commands.CommandTeleportPlayer;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.ChunkLoaderHelper;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemBlockDimWall;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemDimensionalDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemGoldDimDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemGoldDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemRiftBlade;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemRiftSignature;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemStabilizedRiftSignature;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemStableFabric;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemUnstableDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemWarpDoor;
|
||||
import StevenDimDoors.mod_pocketDim.items.ItemWorldThread;
|
||||
import StevenDimDoors.mod_pocketDim.items.itemRiftRemover;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.CommonTickHandler;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.LimboDecay;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.MonolithSpawner;
|
||||
import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoor;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityDimDoorGold;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityRift;
|
||||
import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
|
||||
import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo;
|
||||
import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket;
|
||||
import StevenDimDoors.mod_pocketDim.world.GatewayGenerator;
|
||||
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
|
||||
import StevenDimDoors.mod_pocketDim.world.PocketProvider;
|
||||
import StevenDimDoors.mod_pocketDimClient.ClientPacketHandler;
|
||||
import StevenDimDoors.mod_pocketDimClient.ClientTickHandler;
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.Mod.EventHandler;
|
||||
import cpw.mods.fml.common.Mod.Instance;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||
import cpw.mods.fml.common.network.NetworkMod;
|
||||
import cpw.mods.fml.common.network.NetworkMod.SidedPacketHandler;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.EntityEggInfo;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumToolMaterial;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChatMessageComponent;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
@Mod(modid = mod_pocketDim.modid, name = "Dimensional Doors", version = mod_pocketDim.version)
|
||||
|
||||
@NetworkMod(clientSideRequired = true, serverSideRequired = false, connectionHandler=ConnectionHandler.class,
|
||||
clientPacketHandlerSpec =
|
||||
@SidedPacketHandler(channels = {PacketConstants.CHANNEL_NAME}, packetHandler = ClientPacketHandler.class),
|
||||
serverPacketHandlerSpec =
|
||||
@SidedPacketHandler(channels = {PacketConstants.CHANNEL_NAME}, packetHandler = ServerPacketHandler.class))
|
||||
public class mod_pocketDim
|
||||
{
|
||||
public static final String version = "$VERSION$";
|
||||
public static final String modid = "dimdoors";
|
||||
|
||||
//need to clean up
|
||||
@SidedProxy(clientSide = "StevenDimDoors.mod_pocketDimClient.ClientProxy", serverSide = "StevenDimDoors.mod_pocketDim.CommonProxy")
|
||||
public static CommonProxy proxy;
|
||||
|
||||
@Instance("PocketDimensions")
|
||||
public static mod_pocketDim instance = new mod_pocketDim();
|
||||
|
||||
public static Block transientDoor;
|
||||
public static Block warpDoor;
|
||||
public static Block goldDoor;
|
||||
public static Block goldDimDoor;
|
||||
public static Block unstableDoor;
|
||||
public static Block blockLimbo;
|
||||
public static DimensionalDoor dimensionalDoor;
|
||||
public static Block blockDimWall;
|
||||
public static TransTrapdoor transTrapdoor;
|
||||
public static Block blockDimWallPerm;
|
||||
public static BlockRift blockRift;
|
||||
|
||||
public static Item itemGoldDimDoor;
|
||||
public static Item itemGoldDoor;
|
||||
public static Item itemWorldThread;
|
||||
|
||||
public static Item itemRiftBlade;
|
||||
public static Item itemDimDoor;
|
||||
public static Item itemExitDoor;
|
||||
public static Item itemRiftRemover;
|
||||
public static Item itemLinkSignature;
|
||||
public static Item itemStableFabric;
|
||||
public static Item itemChaosDoor;
|
||||
public static Item itemStabilizedLinkSignature;
|
||||
|
||||
public static BiomeGenBase limboBiome;
|
||||
public static BiomeGenBase pocketBiome;
|
||||
|
||||
public static boolean isPlayerWearingGoogles = false;
|
||||
|
||||
public static DDProperties properties;
|
||||
public static MonolithSpawner spawner; //Added this field temporarily. Will be refactored out later.
|
||||
public static GatewayGenerator riftGen;
|
||||
|
||||
public static CreativeTabs dimDoorsCreativeTab = new CreativeTabs("dimDoorsCreativeTab")
|
||||
{
|
||||
@Override
|
||||
public ItemStack getIconItemStack()
|
||||
{
|
||||
return new ItemStack(mod_pocketDim.itemDimDoor, 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslatedTabLabel()
|
||||
{
|
||||
return "Dimensional Doors";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPreInitialization(FMLPreInitializationEvent event)
|
||||
{
|
||||
instance = this;
|
||||
//This should be the FIRST thing that gets done.
|
||||
String path = event.getSuggestedConfigurationFile().getAbsolutePath().replace(modid, "DimDoors");
|
||||
|
||||
properties = DDProperties.initialize(new File(path));
|
||||
|
||||
//Now do other stuff
|
||||
MinecraftForge.EVENT_BUS.register(new EventHookContainer(properties));
|
||||
|
||||
riftGen = new GatewayGenerator(properties);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@EventHandler
|
||||
public void onInitialization(FMLInitializationEvent event)
|
||||
{
|
||||
CommonTickHandler commonTickHandler = new CommonTickHandler();
|
||||
TickRegistry.registerTickHandler(new ClientTickHandler(), Side.CLIENT);
|
||||
TickRegistry.registerTickHandler(commonTickHandler, Side.SERVER);
|
||||
|
||||
//MonolithSpawner should be initialized before any provider instances are created
|
||||
//Register the other regular tick receivers as well
|
||||
spawner = new MonolithSpawner(commonTickHandler, properties);
|
||||
new RiftRegenerator(commonTickHandler); //No need to store the reference
|
||||
LimboDecay decay = new LimboDecay(commonTickHandler, properties);
|
||||
|
||||
transientDoor = new TransientDoor(properties.TransientDoorID, Material.iron, properties).setHardness(1.0F) .setUnlocalizedName("transientDoor");
|
||||
goldDimDoor = new BlockGoldDimDoor(properties.GoldDimDoorID, Material.iron, properties).setHardness(1.0F) .setUnlocalizedName("dimDoorGold");
|
||||
|
||||
goldDoor = new BlockDoorGold(properties.GoldDoorID, Material.iron, properties).setHardness(0.1F).setUnlocalizedName("doorGold");
|
||||
blockDimWall = new BlockDimWall(properties.FabricBlockID, 0, Material.iron).setLightValue(1.0F).setHardness(0.1F).setUnlocalizedName("blockDimWall");
|
||||
blockDimWallPerm = (new BlockDimWallPerm(properties.PermaFabricBlockID, 0, Material.iron)).setLightValue(1.0F).setBlockUnbreakable().setResistance(6000000.0F).setUnlocalizedName("blockDimWallPerm");
|
||||
warpDoor = new WarpDoor(properties.WarpDoorID, Material.wood, properties).setHardness(1.0F) .setUnlocalizedName("dimDoorWarp");
|
||||
blockRift = (BlockRift) (new BlockRift(properties.RiftBlockID, 0, Material.air, properties).setHardness(1.0F) .setUnlocalizedName("rift"));
|
||||
blockLimbo = new BlockLimbo(properties.LimboBlockID, 15, Material.iron, properties.LimboDimensionID, decay).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F);
|
||||
unstableDoor = (new UnstableDoor(properties.UnstableDoorID, Material.iron, properties).setHardness(.2F).setUnlocalizedName("chaosDoor").setLightValue(.0F) );
|
||||
dimensionalDoor = (DimensionalDoor) (new DimensionalDoor(properties.DimensionalDoorID, Material.iron, properties).setHardness(1.0F).setResistance(2000.0F) .setUnlocalizedName("dimDoor"));
|
||||
transTrapdoor = (TransTrapdoor) (new TransTrapdoor(properties.TransTrapdoorID, Material.wood).setHardness(1.0F) .setUnlocalizedName("dimHatch"));
|
||||
|
||||
itemGoldDimDoor = (new ItemGoldDimDoor(properties.GoldDimDoorItemID, Material.iron)).setUnlocalizedName("itemGoldDimDoor");
|
||||
itemGoldDoor = (new ItemGoldDoor(properties.GoldDoorID, Material.wood)).setUnlocalizedName("itemGoldDoor");
|
||||
itemDimDoor = (new ItemDimensionalDoor(properties.DimensionalDoorItemID, Material.iron)).setUnlocalizedName("itemDimDoor");
|
||||
itemExitDoor = (new ItemWarpDoor(properties.WarpDoorItemID, Material.wood)).setUnlocalizedName("itemDimDoorWarp");
|
||||
itemLinkSignature = (new ItemRiftSignature(properties.RiftSignatureItemID)).setUnlocalizedName("itemLinkSignature");
|
||||
itemRiftRemover = (new itemRiftRemover(properties.RiftRemoverItemID, Material.wood)).setUnlocalizedName("itemRiftRemover");
|
||||
itemStableFabric = (new ItemStableFabric(properties.StableFabricItemID, 0)).setUnlocalizedName("itemStableFabric");
|
||||
itemChaosDoor = (new ItemUnstableDoor(properties.UnstableDoorItemID, Material.iron)).setUnlocalizedName("itemChaosDoor");
|
||||
itemRiftBlade = (new ItemRiftBlade(properties.RiftBladeItemID, EnumToolMaterial.GOLD, properties)).setUnlocalizedName("ItemRiftBlade");
|
||||
itemStabilizedLinkSignature = (new ItemStabilizedRiftSignature(properties.StabilizedRiftSignatureItemID)).setUnlocalizedName("itemStabilizedRiftSig");
|
||||
itemWorldThread = (new ItemWorldThread(properties.ItemWorldThreadID)).setUnlocalizedName("itemWorldThread");
|
||||
|
||||
|
||||
mod_pocketDim.limboBiome= (new BiomeGenLimbo(properties.LimboBiomeID));
|
||||
mod_pocketDim.pocketBiome= (new BiomeGenPocket(properties.PocketBiomeID));
|
||||
|
||||
GameRegistry.registerWorldGenerator(mod_pocketDim.riftGen);
|
||||
|
||||
GameRegistry.registerBlock(goldDoor, "Golden Door");
|
||||
GameRegistry.registerBlock(goldDimDoor, "Golden Dimensional Door");
|
||||
GameRegistry.registerBlock(unstableDoor, "Unstable Door");
|
||||
GameRegistry.registerBlock(warpDoor, "Warp Door");
|
||||
GameRegistry.registerBlock(blockRift, "Rift");
|
||||
GameRegistry.registerBlock(blockLimbo, "Unraveled Fabric");
|
||||
GameRegistry.registerBlock(dimensionalDoor, "Dimensional Door");
|
||||
GameRegistry.registerBlock(transTrapdoor,"Transdimensional Trapdoor");
|
||||
GameRegistry.registerBlock(blockDimWallPerm, "Fabric of RealityPerm");
|
||||
GameRegistry.registerBlock(transientDoor, "transientDoor");
|
||||
|
||||
GameRegistry.registerBlock(blockDimWall, ItemBlockDimWall.class, "Fabric of Reality");
|
||||
|
||||
DimensionManager.registerProviderType(properties.PocketProviderID, PocketProvider.class, false);
|
||||
DimensionManager.registerProviderType(properties.LimboProviderID, LimboProvider.class, false);
|
||||
DimensionManager.registerDimension(properties.LimboDimensionID, properties.LimboProviderID);
|
||||
|
||||
LanguageRegistry.addName(goldDoor, "Golden Door");
|
||||
LanguageRegistry.addName(goldDimDoor, "Golden Dimensional Door");
|
||||
LanguageRegistry.addName(transientDoor , "transientDoor");
|
||||
LanguageRegistry.addName(blockRift , "Rift");
|
||||
LanguageRegistry.addName(blockLimbo , "Unraveled Fabric");
|
||||
LanguageRegistry.addName(warpDoor , "Warp Door");
|
||||
LanguageRegistry.addName(unstableDoor , "Unstable Door");
|
||||
LanguageRegistry.addName(blockDimWall , "Fabric of Reality");
|
||||
LanguageRegistry.addName(blockDimWallPerm , "Eternal Fabric");
|
||||
LanguageRegistry.addName(dimensionalDoor, "Dimensional Door");
|
||||
LanguageRegistry.addName(transTrapdoor, "Transdimensional Trapdoor");
|
||||
|
||||
LanguageRegistry.addName(itemExitDoor, "Warp Door");
|
||||
LanguageRegistry.addName(itemLinkSignature , "Rift Signature");
|
||||
LanguageRegistry.addName(itemGoldDoor, "Golden Door");
|
||||
LanguageRegistry.addName(itemGoldDimDoor , "Golden Dimensional Door");
|
||||
LanguageRegistry.addName(itemStabilizedLinkSignature, "Stabilized Rift Signature");
|
||||
LanguageRegistry.addName(itemRiftRemover , "Rift Remover");
|
||||
LanguageRegistry.addName(itemStableFabric , "Stable Fabric");
|
||||
LanguageRegistry.addName(itemChaosDoor , "Unstable Door");
|
||||
LanguageRegistry.addName(itemDimDoor, "Dimensional Door");
|
||||
LanguageRegistry.addName(itemRiftBlade , "Rift Blade");
|
||||
LanguageRegistry.addName(itemWorldThread, "World Thread");
|
||||
|
||||
|
||||
/**
|
||||
* Add names for multiblock inventory item
|
||||
*/
|
||||
LanguageRegistry.addName(new ItemStack(blockDimWall, 1, 0), "Fabric of Reality");
|
||||
LanguageRegistry.addName(new ItemStack(blockDimWall, 1, 1), "Ancient Fabric");
|
||||
|
||||
|
||||
LanguageRegistry.instance().addStringLocalization("itemGroup.dimDoorsCustomTab", "en_US", "Dimensional Doors Items");
|
||||
|
||||
GameRegistry.registerTileEntity(TileEntityDimDoor.class, "TileEntityDimDoor");
|
||||
GameRegistry.registerTileEntity(TileEntityRift.class, "TileEntityRift");
|
||||
GameRegistry.registerTileEntity(TileEntityTransTrapdoor.class, "TileEntityDimHatch");
|
||||
GameRegistry.registerTileEntity(TileEntityDimDoorGold.class, "TileEntityDimDoorGold");
|
||||
|
||||
EntityRegistry.registerModEntity(MobMonolith.class, "Monolith", properties.MonolithEntityID, this, 70, 1, true);
|
||||
EntityList.IDtoClassMapping.put(properties.MonolithEntityID, MobMonolith.class);
|
||||
EntityList.entityEggs.put(properties.MonolithEntityID, new EntityEggInfo(properties.MonolithEntityID, 0, 0xffffff));
|
||||
LanguageRegistry.instance().addStringLocalization("entity.DimDoors.Obelisk.name", "Monolith");
|
||||
|
||||
|
||||
CraftingManager.registerRecipies();
|
||||
DungeonHelper.initialize();
|
||||
|
||||
proxy.loadTextures();
|
||||
proxy.registerRenderers();
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPostInitialization(FMLPostInitializationEvent event)
|
||||
{
|
||||
ForgeChunkManager.setForcedChunkLoadingCallback(instance, new ChunkLoaderHelper());
|
||||
//Register loot chests
|
||||
DDLoot.registerInfo();
|
||||
}
|
||||
@EventHandler
|
||||
public void onServerStopping(FMLServerStoppingEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
PocketManager.unload();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerStarting(FMLServerStartingEvent event)
|
||||
{
|
||||
|
||||
//TODO- load dims with forced chunks on server startup here
|
||||
|
||||
CommandResetDungeons.instance().register(event);
|
||||
CommandCreateDungeonRift.instance().register(event);
|
||||
CommandDeleteAllLinks.instance().register(event);
|
||||
//CommandDeleteDimensionData.instance().register(event);
|
||||
CommandDeleteRifts.instance().register(event);
|
||||
CommandExportDungeon.instance().register(event);
|
||||
//CommandPrintDimensionData.instance().register(event);
|
||||
//CommandPruneDimensions.instance().register(event);
|
||||
CommandCreatePocket.instance().register(event);
|
||||
CommandTeleportPlayer.instance().register(event);
|
||||
|
||||
try
|
||||
{
|
||||
ChunkLoaderHelper.loadChunkForcedWorlds(event);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.out.println("Loading chunkloaders failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendChat(EntityPlayer player, String message)
|
||||
{
|
||||
ChatMessageComponent cmp = new ChatMessageComponent();
|
||||
cmp.addText(message);
|
||||
player.sendChatToPlayer(cmp);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.BaseConfigurationProcessor;
|
||||
import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException;
|
||||
|
||||
public class BlacklistProcessor extends BaseConfigurationProcessor<List<Integer>>
|
||||
{
|
||||
|
||||
@Override
|
||||
public List<Integer> readFromStream(InputStream inputStream) throws ConfigurationProcessingException
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
List<Integer> data = this.createBlacklistFromJson(reader);
|
||||
reader.close();
|
||||
return data;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new ConfigurationProcessingException("Could not read blacklist");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Integer> createBlacklistFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
List<Integer> blacklist;
|
||||
blacklist = this.createIntListFromJson(reader);
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(OutputStream outputStream, List<Integer> data) throws ConfigurationProcessingException
|
||||
{
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
Gson gson = gsonBuilder.setPrettyPrinting().create();
|
||||
|
||||
try
|
||||
{
|
||||
outputStream.write(gson.toJson(data).getBytes("UTF-8"));
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// not sure if this is kosher, we need it to explode, but not by throwing the IO exception.
|
||||
throw new ConfigurationProcessingException("Incorrectly formatted save data");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<Integer> createIntListFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
List<Integer> list = new ArrayList<Integer>();
|
||||
reader.beginArray();
|
||||
|
||||
while(reader.peek()!= JsonToken.END_ARRAY)
|
||||
{
|
||||
list.add(reader.nextInt());
|
||||
}
|
||||
reader.endArray();
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
||||
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
||||
import StevenDimDoors.mod_pocketDim.core.NewDimData;
|
||||
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.DungeonData;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonPack;
|
||||
import StevenDimDoors.mod_pocketDim.dungeon.pack.DungeonType;
|
||||
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
||||
import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException;
|
||||
import StevenDimDoors.mod_pocketDim.util.FileFilters;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
public class DDSaveHandler
|
||||
{
|
||||
public static boolean loadAll()
|
||||
{
|
||||
// SenseiKiwi: Loading up our save data is not as simple as just reading files.
|
||||
// To properly restore dimensions, we need to make sure we always load
|
||||
// a dimension's parent and root before trying to load it. We'll use
|
||||
// topological sorting to determine the order in which to recreate the
|
||||
// dimension objects such that we respect those dependencies.
|
||||
// Links must be loaded after instantiating all the dimensions and must
|
||||
// be checked against our dimension blacklist.
|
||||
|
||||
// Don't surround this code with try-catch. Our mod should crash if an error
|
||||
// occurs at this level, since it could lead to some nasty problems.
|
||||
|
||||
String basePath = DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/";
|
||||
File dataDirectory = new File(basePath);
|
||||
|
||||
// Check if the folder exists. If it doesn't, just return.
|
||||
if (!dataDirectory.exists())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load the dimension blacklist
|
||||
File blacklistFile = new File(basePath+"blacklist.txt");
|
||||
|
||||
if(blacklistFile.exists())
|
||||
{
|
||||
BlacklistProcessor blacklistReader = new BlacklistProcessor();
|
||||
List<Integer> blacklist = readBlacklist(blacklistFile,blacklistReader);
|
||||
PocketManager.createAndRegisterBlacklist(blacklist);
|
||||
}
|
||||
|
||||
// List any dimension data files and read each dimension
|
||||
DimDataProcessor reader = new DimDataProcessor();
|
||||
List<PackedDimData> packedDims = new ArrayList<PackedDimData>();
|
||||
FileFilter dataFileFilter = new FileFilters.RegexFileFilter("dim_-?\\d+\\.txt");
|
||||
|
||||
File[] dataFiles = dataDirectory.listFiles(dataFileFilter);
|
||||
for (File dataFile : dataFiles)
|
||||
{
|
||||
PackedDimData packedDim = readDimension(dataFile, reader);
|
||||
packedDims.add(packedDim);
|
||||
}
|
||||
|
||||
List<PackedLinkData> linksToUnpack = new ArrayList<PackedLinkData>();
|
||||
//get the grand list of all links to unpack
|
||||
for(PackedDimData packedDim : packedDims)
|
||||
{
|
||||
linksToUnpack.addAll(packedDim.Links);
|
||||
}
|
||||
|
||||
|
||||
return unpackDimData(packedDims)&&unpackLinkData(linksToUnpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of packedDimData and rebuilds the DimData for it
|
||||
* @param packedDims
|
||||
* @return
|
||||
*/
|
||||
public static boolean unpackDimData(List<PackedDimData> packedDims)
|
||||
{
|
||||
List<PackedDimData> unpackedDims = new ArrayList<PackedDimData>();
|
||||
|
||||
|
||||
//Load roots
|
||||
for(PackedDimData packedDim : packedDims)
|
||||
{
|
||||
if(packedDim.ParentID==packedDim.ID)
|
||||
{
|
||||
PocketManager.registerPackedDimData(packedDim);
|
||||
unpackedDims.add(packedDim);
|
||||
}
|
||||
}
|
||||
packedDims.removeAll(unpackedDims);
|
||||
unpackedDims.clear();
|
||||
|
||||
//Load the pockets
|
||||
while(!packedDims.isEmpty())
|
||||
{
|
||||
for(PackedDimData packedDim : packedDims)
|
||||
{
|
||||
if(PocketManager.isRegisteredInternally(packedDim.ParentID))
|
||||
{
|
||||
PocketManager.registerPackedDimData(packedDim);
|
||||
unpackedDims.add(packedDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
//break here gracefully
|
||||
}
|
||||
}
|
||||
packedDims.removeAll(unpackedDims);
|
||||
unpackedDims.clear();
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean unpackLinkData(List<PackedLinkData> linksToUnpack)
|
||||
{
|
||||
Point3D fakePoint = new Point3D(-1,-1,-1);
|
||||
List<PackedLinkData> unpackedLinks = new ArrayList<PackedLinkData>();
|
||||
/**
|
||||
* sort through the list, unpacking links that do not have parents.
|
||||
*/
|
||||
//TODO- what we have a loop of links?
|
||||
for(PackedLinkData packedLink : linksToUnpack)
|
||||
{
|
||||
if(packedLink.parent.equals(fakePoint))
|
||||
{
|
||||
NewDimData data = PocketManager.getDimensionData(packedLink.source.getDimension());
|
||||
int linkType = packedLink.tail.linkType;
|
||||
|
||||
if((linkType < LinkTypes.ENUM_MIN || linkType > LinkTypes.ENUM_MAX) && linkType != LinkTypes.CLIENT_SIDE)
|
||||
{
|
||||
linkType = LinkTypes.NORMAL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
DimLink link = data.createLink(packedLink.source, linkType, packedLink.orientation);
|
||||
Point4D destination = packedLink.tail.destination;
|
||||
if(destination!=null)
|
||||
{
|
||||
PocketManager.getDimensionData(destination.getDimension()).setDestination(link, destination.getX(),destination.getY(),destination.getZ());
|
||||
}
|
||||
unpackedLinks.add(packedLink);
|
||||
}
|
||||
}
|
||||
linksToUnpack.removeAll(unpackedLinks);
|
||||
|
||||
//unpack remaining children
|
||||
while(!linksToUnpack.isEmpty())
|
||||
{
|
||||
for(PackedLinkData packedLink : linksToUnpack)
|
||||
{
|
||||
NewDimData data = PocketManager.getDimensionData(packedLink.source.getDimension());
|
||||
if(data.getLink(packedLink.parent)!=null)
|
||||
{
|
||||
data.createChildLink(packedLink.source.getX(), packedLink.source.getY(), packedLink.source.getZ(), data.getLink(packedLink.parent));
|
||||
}
|
||||
unpackedLinks.add(packedLink);
|
||||
}
|
||||
linksToUnpack.removeAll(unpackedLinks);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static PackedDimData readDimension(File dataFile, DimDataProcessor reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
return reader.readFromFile(dataFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Could not read dimension data from: " + dataFile.getAbsolutePath());
|
||||
System.err.println("The following error occurred:");
|
||||
printException(e, false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean saveAll(Iterable<? extends IPackable<PackedDimData>> dimensions, List<Integer> blacklist) throws IOException
|
||||
{
|
||||
// Create the data directory for our dimensions
|
||||
// Don't catch exceptions here. If we can't create this folder,
|
||||
// the mod should crash to let the user know early on.
|
||||
|
||||
String basePath = DimensionManager.getCurrentSaveRootDirectory() + "/DimensionalDoors/data/";
|
||||
File basePathFile = new File(basePath);
|
||||
Files.createParentDirs(basePathFile);
|
||||
basePathFile.mkdir();
|
||||
|
||||
BlacklistProcessor blacklistReader = new BlacklistProcessor();
|
||||
writeBlacklist(blacklist, blacklistReader,basePath);
|
||||
|
||||
FileFilter dataFileFilter = new FileFilters.RegexFileFilter("dim_-?\\d+\\.txt");
|
||||
|
||||
//TODO Deal with temp files correctly
|
||||
File[] dataFiles = basePathFile.listFiles(dataFileFilter);
|
||||
for (File dataFile : dataFiles)
|
||||
{
|
||||
dataFile.delete();
|
||||
}
|
||||
|
||||
|
||||
basePathFile = null;
|
||||
basePath += "dim_";
|
||||
|
||||
boolean succeeded = true;
|
||||
DimDataProcessor writer = new DimDataProcessor();
|
||||
for (IPackable<PackedDimData> dimension : dimensions)
|
||||
{
|
||||
succeeded &= writeDimension(dimension, writer, basePath);
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
private static boolean writeBlacklist(List<Integer> blacklist, BlacklistProcessor writer, String basePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
File tempFile = new File(basePath + "blacklist.tmp");
|
||||
File saveFile = new File(basePath + "blacklist.txt");
|
||||
writer.writeToFile(tempFile, blacklist);
|
||||
saveFile.delete();
|
||||
tempFile.renameTo(saveFile);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Could not save blacklist. The following error occurred:");
|
||||
printException(e, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
private static boolean writeDimension(IPackable<PackedDimData> dimension, DimDataProcessor writer, String basePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
File tempFile = new File(basePath + (dimension.name() + ".tmp"));
|
||||
File saveFile = new File(basePath + (dimension.name() + ".txt"));
|
||||
writer.writeToFile(tempFile, dimension.pack());
|
||||
saveFile.delete();
|
||||
tempFile.renameTo(saveFile);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Could not save data for dimension #" + dimension.name() + ". The following error occurred:");
|
||||
printException(e, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void printException(Exception e, boolean verbose)
|
||||
{
|
||||
if (e.getCause() == null)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println(e.getMessage());
|
||||
System.err.println("Caused by an underlying error:");
|
||||
if (verbose)
|
||||
{
|
||||
e.getCause().printStackTrace();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println(e.getCause().getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO - make this more robust
|
||||
public static DungeonData unpackDungeonData(PackedDungeonData packedDungeon)
|
||||
{
|
||||
for(DungeonData data : DungeonHelper.instance().getRegisteredDungeons())
|
||||
{
|
||||
if(data.schematicName().equals(packedDungeon.SchematicName))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Integer> readBlacklist(File blacklistFile, BlacklistProcessor reader)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
return reader.readFromFile(blacklistFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.util.BaseConfigurationProcessor;
|
||||
import StevenDimDoors.mod_pocketDim.util.ConfigurationProcessingException;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class DimDataProcessor extends BaseConfigurationProcessor<PackedDimData>
|
||||
{
|
||||
@Override
|
||||
public PackedDimData readFromStream(InputStream inputStream)
|
||||
throws ConfigurationProcessingException
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
PackedDimData data = this.createDImDataFromJson(reader);
|
||||
reader.close();
|
||||
return data;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new ConfigurationProcessingException("Could not read packedDimData");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(OutputStream outputStream, PackedDimData data)
|
||||
throws ConfigurationProcessingException
|
||||
{
|
||||
/** Print out dimData using the GSON built in serializer. I dont feel bad doing this because
|
||||
* 1- We can read it
|
||||
* 2- We are manually reading the data in.
|
||||
* 3- The error messages tell us exactly where its failing, so its easy to fix
|
||||
*/
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
Gson gson = gsonBuilder.setPrettyPrinting().create();
|
||||
|
||||
try
|
||||
{
|
||||
outputStream.write(gson.toJson(data).getBytes("UTF-8"));
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// not sure if this is kosher, we need it to explode, but not by throwing the IO exception.
|
||||
throw new ConfigurationProcessingException("Incorrectly formatted save data");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Nightmare method that takes a JsonReader pointed at a serialized instance of PackedDimData
|
||||
* @param reader
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public PackedDimData createDImDataFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
int ID;
|
||||
boolean IsDungeon;
|
||||
boolean IsFilled;
|
||||
int Depth;
|
||||
int PackDepth;
|
||||
int ParentID;
|
||||
int RootID;
|
||||
PackedDungeonData Dungeon = null;
|
||||
Point3D Origin;
|
||||
int Orientation;
|
||||
List<Integer> ChildIDs;
|
||||
List<PackedLinkData> Links;
|
||||
List<PackedLinkTail> Tails = new ArrayList<PackedLinkTail>();
|
||||
|
||||
reader.beginObject();
|
||||
|
||||
reader.nextName();
|
||||
if (reader.nextLong() != PackedDimData.SAVE_DATA_VERSION_ID)
|
||||
{
|
||||
throw new IOException("Save data version mismatch");
|
||||
}
|
||||
|
||||
reader.nextName();
|
||||
ID = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
IsDungeon = reader.nextBoolean();
|
||||
|
||||
reader.nextName();
|
||||
IsFilled = reader.nextBoolean();
|
||||
|
||||
reader.nextName();
|
||||
Depth = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
PackDepth = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
ParentID=reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
RootID= reader.nextInt();
|
||||
|
||||
if(reader.nextName().equals("DungeonData"))
|
||||
{
|
||||
Dungeon = createDungeonDataFromJson(reader);
|
||||
reader.nextName();
|
||||
}
|
||||
|
||||
Origin = createPointFromJson(reader);
|
||||
|
||||
reader.nextName();
|
||||
Orientation = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
ChildIDs = this.createIntListFromJson(reader);
|
||||
|
||||
reader.nextName();
|
||||
Links = this.createLinksListFromJson(reader);
|
||||
|
||||
return new PackedDimData(ID, Depth, PackDepth, ParentID, RootID, Orientation, IsDungeon, IsFilled, Dungeon, Origin, ChildIDs, Links, Tails);
|
||||
}
|
||||
|
||||
private Point3D createPointFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
reader.beginObject();
|
||||
|
||||
reader.nextName();
|
||||
int x = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
int y = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
int z = reader.nextInt();
|
||||
|
||||
reader.endObject();
|
||||
|
||||
return new Point3D(x,y,z);
|
||||
}
|
||||
|
||||
private Point4D createPoint4DFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
reader.beginObject();
|
||||
|
||||
reader.nextName();
|
||||
int x = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
int y = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
int z = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
int dimension = reader.nextInt();
|
||||
|
||||
reader.endObject();
|
||||
|
||||
return new Point4D(x,y,z,dimension);
|
||||
}
|
||||
|
||||
private List<Integer> createIntListFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
List<Integer> list = new ArrayList<Integer>();
|
||||
reader.beginArray();
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY)
|
||||
{
|
||||
list.add(reader.nextInt());
|
||||
|
||||
}
|
||||
reader.endArray();
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<PackedLinkData> createLinksListFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
List<PackedLinkData> list = new ArrayList<PackedLinkData>();
|
||||
|
||||
reader.beginArray();
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY)
|
||||
{
|
||||
list.add(createLinkDataFromJson(reader));
|
||||
}
|
||||
reader.endArray();
|
||||
return list;
|
||||
}
|
||||
|
||||
private PackedLinkData createLinkDataFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
Point4D source;
|
||||
Point3D parent;
|
||||
PackedLinkTail tail;
|
||||
int orientation;
|
||||
List<Point3D> children = new ArrayList<Point3D>();
|
||||
|
||||
reader.beginObject();
|
||||
|
||||
reader.nextName();
|
||||
source = this.createPoint4DFromJson(reader);
|
||||
|
||||
reader.nextName();
|
||||
parent = this.createPointFromJson(reader);
|
||||
|
||||
reader.nextName();
|
||||
tail = this.createLinkTailFromJson(reader);
|
||||
|
||||
reader.nextName();
|
||||
orientation = reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
reader.beginArray();
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY)
|
||||
{
|
||||
children.add(this.createPointFromJson(reader));
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
|
||||
return new PackedLinkData(source, parent, tail, orientation, children);
|
||||
}
|
||||
private PackedDungeonData createDungeonDataFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
int Weight;
|
||||
boolean IsOpen;
|
||||
boolean IsInternal;
|
||||
String SchematicPath;
|
||||
String SchematicName;
|
||||
String DungeonTypeName;
|
||||
String DungeonPackName;
|
||||
|
||||
reader.beginObject();
|
||||
@SuppressWarnings("unused")
|
||||
JsonToken test = reader.peek();
|
||||
|
||||
if(reader.peek() == JsonToken.END_OBJECT)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
reader.nextName();
|
||||
Weight=reader.nextInt();
|
||||
|
||||
reader.nextName();
|
||||
IsOpen=reader.nextBoolean();
|
||||
|
||||
reader.nextName();
|
||||
IsInternal=reader.nextBoolean();
|
||||
|
||||
reader.nextName();
|
||||
SchematicPath=reader.nextString();
|
||||
|
||||
reader.nextName();
|
||||
SchematicName=reader.nextString();
|
||||
|
||||
reader.nextName();
|
||||
DungeonTypeName=reader.nextString();
|
||||
|
||||
reader.nextName();
|
||||
DungeonPackName=reader.nextString();
|
||||
|
||||
reader.endObject();
|
||||
return new PackedDungeonData(Weight, IsOpen, IsInternal, SchematicPath, SchematicName, DungeonTypeName, DungeonPackName);
|
||||
}
|
||||
private PackedLinkTail createLinkTailFromJson(JsonReader reader) throws IOException
|
||||
{
|
||||
Point4D destination = null;
|
||||
int linkType;
|
||||
reader.beginObject();
|
||||
reader.nextName();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
JsonToken test = reader.peek();
|
||||
if (reader.peek() == JsonToken.BEGIN_OBJECT)
|
||||
{
|
||||
destination = this.createPoint4DFromJson(reader);
|
||||
reader.nextName();
|
||||
}
|
||||
|
||||
linkType = reader.nextInt();
|
||||
reader.endObject();
|
||||
|
||||
return new PackedLinkTail(destination, linkType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
public interface IPackable<T>
|
||||
{
|
||||
public String name();
|
||||
public T pack();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.DimData;
|
||||
import StevenDimDoors.mod_pocketDim.LinkData;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class OldSaveImporter
|
||||
{
|
||||
public static void importOldSave(File file) throws IOException, ClassNotFoundException
|
||||
{
|
||||
FileInputStream saveFile = new FileInputStream(file);
|
||||
ObjectSaveInputStream save = new ObjectSaveInputStream(saveFile);
|
||||
HashMap comboSave =((HashMap) save.readObject());
|
||||
save.close();
|
||||
|
||||
List<PackedLinkData> allPackedLinks = new ArrayList<PackedLinkData>();
|
||||
List<PackedDimData> newPackedDimData = new ArrayList<PackedDimData>();
|
||||
|
||||
HashMap<Integer, DimData> dimMap;
|
||||
|
||||
try
|
||||
{
|
||||
dimMap = (HashMap<Integer, DimData>) comboSave.get("dimList");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.out.println("Could not import old save data");
|
||||
return;
|
||||
}
|
||||
|
||||
for(DimData data : dimMap.values())
|
||||
{
|
||||
List<PackedLinkData> newPackedLinkData = new ArrayList<PackedLinkData>();
|
||||
List<Integer> childDims = new ArrayList<Integer>();
|
||||
|
||||
for(LinkData link : data.getLinksInDim())
|
||||
{
|
||||
Point4D source = new Point4D(link.locXCoord,link.locYCoord,link.locZCoord,link.locDimID);
|
||||
Point4D destintion = new Point4D(link.destXCoord,link.destYCoord,link.destZCoord,link.destDimID);
|
||||
PackedLinkTail tail = new PackedLinkTail(destintion, link.linkOrientation);
|
||||
List<Point3D> children = new ArrayList<Point3D>();
|
||||
|
||||
PackedLinkData newPackedLink = new PackedLinkData(source, new Point3D(-1,-1,-1), tail, link.linkOrientation,children);
|
||||
|
||||
newPackedLinkData.add(newPackedLink);
|
||||
allPackedLinks.add(newPackedLink);
|
||||
|
||||
}
|
||||
|
||||
PackedDimData dim = new PackedDimData(data.dimID, data.depth, data.depth, data.exitDimLink.locDimID, data.exitDimLink.locDimID, 0, data.dungeonGenerator!=null, data.hasBeenFilled, null, new Point3D(0,64,0), childDims, newPackedLinkData, null);
|
||||
newPackedDimData.add(dim);
|
||||
|
||||
DDSaveHandler.unpackDimData(newPackedDimData);
|
||||
DDSaveHandler.unpackLinkData(allPackedLinks);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
|
||||
public class PackedDimData
|
||||
{
|
||||
// These fields will be public since this is a simple data container
|
||||
public final static long SAVE_DATA_VERSION_ID = 982405775L;
|
||||
public final long SAVE_DATA_VERSION_ID_INSTANCE = SAVE_DATA_VERSION_ID;
|
||||
public final int ID;
|
||||
public final boolean IsDungeon;
|
||||
public final boolean IsFilled;
|
||||
public final int Depth;
|
||||
public final int PackDepth;
|
||||
public final int ParentID;
|
||||
public final int RootID;
|
||||
public final PackedDungeonData DungeonData;
|
||||
public final Point3D Origin;
|
||||
public final int Orientation;
|
||||
public final List<Integer> ChildIDs;
|
||||
public final List<PackedLinkData> Links;
|
||||
public final List<PackedLinkTail> Tails;
|
||||
|
||||
// FIXME Missing dungeon data, not sure how to include it
|
||||
|
||||
public PackedDimData(int id, int depth, int packDepth, int parentID, int rootID, int orientation,
|
||||
boolean isDungeon, boolean isFilled,PackedDungeonData dungeonData, Point3D origin, List<Integer> childIDs, List<PackedLinkData> links,
|
||||
List<PackedLinkTail> tails)
|
||||
{
|
||||
ID = id;
|
||||
Depth = depth;
|
||||
PackDepth = packDepth;
|
||||
ParentID = parentID;
|
||||
RootID = rootID;
|
||||
Orientation = orientation;
|
||||
IsDungeon = isDungeon;
|
||||
IsFilled = isFilled;
|
||||
DungeonData = dungeonData;
|
||||
Origin = origin;
|
||||
ChildIDs = childIDs;
|
||||
Links = links;
|
||||
Tails = tails;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
public class PackedDungeonData
|
||||
{
|
||||
public final int Weight;
|
||||
public final boolean IsOpen;
|
||||
public final boolean IsInternal;
|
||||
public final String SchematicPath;
|
||||
public final String SchematicName;
|
||||
public final String DungeonTypeName;
|
||||
public final String DungeonPackName;
|
||||
|
||||
public PackedDungeonData(int weight, boolean isOpen, boolean isInternal, String schematicPath, String schematicName, String dungeonTypeName, String dungeonPackName)
|
||||
{
|
||||
this.Weight= weight;
|
||||
this.IsOpen=isOpen;
|
||||
this.IsInternal=isInternal;
|
||||
this.SchematicName=schematicName;
|
||||
this.SchematicPath=schematicPath;
|
||||
this.DungeonTypeName=dungeonTypeName;
|
||||
this.DungeonPackName=dungeonPackName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class PackedLinkData
|
||||
{
|
||||
public final Point4D source;
|
||||
public final Point3D parent;
|
||||
public final PackedLinkTail tail;
|
||||
public final int orientation;
|
||||
public final List<Point3D> children;
|
||||
|
||||
public PackedLinkData(Point4D source, Point3D parent, PackedLinkTail tail, int orientation, List<Point3D> children)
|
||||
{
|
||||
this.source=source;
|
||||
this.parent=parent;
|
||||
this.tail=tail;
|
||||
this.orientation=orientation;
|
||||
this.children=children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package StevenDimDoors.mod_pocketDim.saving;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
||||
|
||||
public class PackedLinkTail
|
||||
{
|
||||
public final Point4D destination;
|
||||
public final int linkType;
|
||||
|
||||
public PackedLinkTail(Point4D destination, int linkType)
|
||||
{
|
||||
this.destination=destination;
|
||||
this.linkType=linkType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockComparator;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.BlockRedstoneRepeater;
|
||||
import net.minecraft.block.BlockStairs;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
|
||||
|
||||
public class BlockRotator
|
||||
{
|
||||
//This class is temporary. It's just a place in which to hold the old block rotation and transformation code
|
||||
//until we can rewrite it.
|
||||
|
||||
public final static int EAST_DOOR_METADATA = 0;
|
||||
private final static int BLOCK_ID_COUNT = 4096;
|
||||
|
||||
//Provides a fast lookup table for whether blocks have orientations
|
||||
private final static boolean[] hasOrientations = new boolean[BLOCK_ID_COUNT];
|
||||
|
||||
static
|
||||
{
|
||||
hasOrientations[Block.dispenser.blockID] = true;
|
||||
hasOrientations[Block.stairsStoneBrick.blockID] = true;
|
||||
hasOrientations[Block.lever.blockID] = true;
|
||||
hasOrientations[Block.stoneButton.blockID] = true;
|
||||
hasOrientations[Block.redstoneRepeaterIdle.blockID] = true;
|
||||
hasOrientations[Block.redstoneRepeaterActive.blockID] = true;
|
||||
hasOrientations[Block.tripWireSource.blockID] = true;
|
||||
hasOrientations[Block.torchWood.blockID] = true;
|
||||
hasOrientations[Block.torchRedstoneIdle.blockID] = true;
|
||||
hasOrientations[Block.torchRedstoneActive.blockID] = true;
|
||||
hasOrientations[Block.doorIron.blockID] = true;
|
||||
hasOrientations[Block.doorWood.blockID] = true;
|
||||
hasOrientations[Block.pistonBase.blockID] = true;
|
||||
hasOrientations[Block.pistonStickyBase.blockID] = true;
|
||||
hasOrientations[Block.pistonExtension.blockID] = true;
|
||||
hasOrientations[Block.redstoneComparatorIdle.blockID] = true;
|
||||
hasOrientations[Block.redstoneComparatorActive.blockID] = true;
|
||||
hasOrientations[Block.signPost.blockID] = true;
|
||||
hasOrientations[Block.signWall.blockID] = true;
|
||||
hasOrientations[Block.skull.blockID] = true;
|
||||
hasOrientations[Block.ladder.blockID] = true;
|
||||
hasOrientations[Block.vine.blockID] = true;
|
||||
hasOrientations[Block.anvil.blockID] = true;
|
||||
hasOrientations[Block.chest.blockID] = true;
|
||||
hasOrientations[Block.chestTrapped.blockID] = true;
|
||||
hasOrientations[Block.hopperBlock.blockID] = true;
|
||||
hasOrientations[Block.stairsNetherBrick.blockID] = true;
|
||||
hasOrientations[Block.stairsCobblestone.blockID] = true;
|
||||
hasOrientations[Block.stairsNetherQuartz.blockID] = true;
|
||||
hasOrientations[Block.stairsSandStone.blockID] = true;
|
||||
hasOrientations[Block.stairsBrick.blockID] = true;
|
||||
hasOrientations[Block.stairsWoodBirch.blockID] = true;
|
||||
hasOrientations[Block.stairsWoodOak.blockID] = true;
|
||||
hasOrientations[Block.stairsWoodJungle.blockID] = true;
|
||||
hasOrientations[Block.stairsWoodSpruce.blockID] = true;
|
||||
hasOrientations[Block.wood.blockID] = true;
|
||||
hasOrientations[Block.blockNetherQuartz.blockID] = true;
|
||||
hasOrientations[Block.railPowered.blockID] = true;
|
||||
hasOrientations[Block.railDetector.blockID] = true;
|
||||
hasOrientations[Block.railActivator.blockID] = true;
|
||||
hasOrientations[Block.rail.blockID] = true;
|
||||
|
||||
hasOrientations[mod_pocketDim.dimensionalDoor.blockID] = true;
|
||||
hasOrientations[mod_pocketDim.warpDoor.blockID] = true;
|
||||
|
||||
}
|
||||
|
||||
public static int transformMetadata(int metadata, int turns, int blockID)
|
||||
{
|
||||
//I changed rotations to reduce the monstrous code we had. It might be
|
||||
//slightly less efficient, but it's easier to maintain for now. ~SenseiKiwi
|
||||
|
||||
//Correct negative turns and get the minimum number of rotations needed
|
||||
turns += 1 << 16;
|
||||
turns %= 4;
|
||||
|
||||
if (hasOrientations[blockID])
|
||||
{
|
||||
while (turns > 0)
|
||||
{
|
||||
metadata = rotateMetadataBy90(metadata, blockID);
|
||||
turns--;
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private static int rotateMetadataBy90(int metadata, int blockID)
|
||||
{
|
||||
//TODO: Replace this horrible function with something prettier. We promise we will for the next version,
|
||||
//after switching to MC 1.6. PADRE, PLEASE FORGIVE OUR SINS.
|
||||
|
||||
if (blockID == Block.wood.blockID)
|
||||
{
|
||||
if (metadata >= 4 && metadata < 12)
|
||||
{
|
||||
metadata = (metadata % 8) + 4;
|
||||
}
|
||||
}
|
||||
else if (blockID == Block.blockNetherQuartz.blockID)
|
||||
{
|
||||
if (metadata == 3 || metadata == 4)
|
||||
{
|
||||
metadata = (metadata - 2) % 2 + 3;
|
||||
}
|
||||
}
|
||||
else if (blockID == Block.railPowered.blockID || blockID == Block.railDetector.blockID || blockID == Block.railActivator.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
//Powered Track/Detector Track/Activator Track (off)
|
||||
case 0:
|
||||
metadata = 1;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 0;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 3;
|
||||
break;
|
||||
|
||||
//Powered Track/Detector Track/Activator Track (on)
|
||||
case 8:
|
||||
metadata = 9;
|
||||
break;
|
||||
case 9:
|
||||
metadata = 8;
|
||||
break;
|
||||
case 10:
|
||||
metadata = 13;
|
||||
break;
|
||||
case 11:
|
||||
metadata = 12;
|
||||
break;
|
||||
case 12:
|
||||
metadata = 10;
|
||||
break;
|
||||
case 13:
|
||||
metadata = 11;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (blockID==Block.rail.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 0:
|
||||
metadata = 1;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 0;
|
||||
break;
|
||||
case 8:
|
||||
metadata = 9;
|
||||
break;
|
||||
case 9:
|
||||
metadata = 6;
|
||||
break;
|
||||
case 6:
|
||||
metadata = 7;
|
||||
break;
|
||||
case 7:
|
||||
metadata = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Block.blocksList[blockID] instanceof BlockStairs)
|
||||
{
|
||||
|
||||
switch (metadata)
|
||||
{
|
||||
case 0:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 3;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 1;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 0;
|
||||
break;
|
||||
case 7:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 6:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 7;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (blockID == Block.chest.blockID || blockID == Block.chestTrapped.blockID || blockID == Block.ladder.blockID || blockID == Block.hopperBlock.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 2:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else if (blockID==Block.vine.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
|
||||
case 1:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 8;
|
||||
break;
|
||||
case 8:
|
||||
metadata = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (blockID==Block.signWall.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
|
||||
case 3:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (blockID==Block.signPost.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 0:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 6;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 7;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 8;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 9;
|
||||
break;
|
||||
case 6:
|
||||
metadata = 10;
|
||||
break;
|
||||
case 7:
|
||||
metadata = 11;
|
||||
break;
|
||||
case 8:
|
||||
metadata = 12;
|
||||
break;
|
||||
case 9:
|
||||
metadata = 13;
|
||||
break;
|
||||
case 10:
|
||||
metadata = 14;
|
||||
break;
|
||||
case 11:
|
||||
metadata = 15;
|
||||
break;
|
||||
case 12:
|
||||
metadata = 0;
|
||||
break;
|
||||
case 13:
|
||||
metadata = 1;
|
||||
break;
|
||||
case 14:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 15:
|
||||
metadata = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(blockID== Block.lever.blockID||blockID== Block.stoneButton.blockID||blockID== Block.woodenButton.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 12:
|
||||
metadata = 9;
|
||||
break;
|
||||
case 11:
|
||||
metadata = 10;
|
||||
break;
|
||||
case 10:
|
||||
metadata = 12;
|
||||
break;
|
||||
case 9:
|
||||
metadata = 11;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 3;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonExtension.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 4:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 3;
|
||||
break;
|
||||
case 13:
|
||||
metadata = 11;
|
||||
break;
|
||||
case 12:
|
||||
metadata = 10;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 11:
|
||||
metadata = 12;
|
||||
break;
|
||||
case 10:
|
||||
metadata = 13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Block.blocksList[blockID] instanceof BlockRedstoneRepeater || Block.blocksList[blockID] instanceof BlockDoor || blockID== Block.tripWireSource.blockID || Block.blocksList[blockID] instanceof BlockComparator)
|
||||
{
|
||||
switch (metadata)
|
||||
{
|
||||
case 0:
|
||||
metadata = 1;
|
||||
break;
|
||||
case 1:
|
||||
metadata = 2;
|
||||
break;
|
||||
case 2:
|
||||
metadata = 3;
|
||||
break;
|
||||
case 3:
|
||||
metadata = 0;
|
||||
break;
|
||||
case 4:
|
||||
metadata = 5;
|
||||
break;
|
||||
case 5:
|
||||
metadata = 6;
|
||||
break;
|
||||
case 6:
|
||||
metadata = 7;
|
||||
break;
|
||||
case 7:
|
||||
metadata = 4;
|
||||
break;
|
||||
case 8:
|
||||
metadata = 9;
|
||||
break;
|
||||
case 9:
|
||||
metadata = 10;
|
||||
break;
|
||||
case 10:
|
||||
metadata = 11;
|
||||
break;
|
||||
case 11:
|
||||
metadata = 8;
|
||||
break;
|
||||
case 12:
|
||||
metadata = 13;
|
||||
break;
|
||||
case 13:
|
||||
metadata = 14;
|
||||
break;
|
||||
case 14:
|
||||
metadata = 15;
|
||||
break;
|
||||
case 15:
|
||||
metadata = 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public static void transformPoint(Point3D position, Point3D srcOrigin, int angle, Point3D destOrigin)
|
||||
{
|
||||
//This function receives a position (e.g. point in schematic space), translates it relative
|
||||
//to a source coordinate system (e.g. the point that will be the center of a schematic),
|
||||
//then rotates and translates it to obtain the corresponding point in a destination
|
||||
//coordinate system (e.g. the location of the entry rift in the pocket being generated).
|
||||
//The result is returned by overwriting the original position so that new object references
|
||||
//aren't needed. That way, repeated use of this function will not incur as much overhead.
|
||||
|
||||
//Position is only overwritten at the end, so it's okay to provide it as srcOrigin or destOrigin as well.
|
||||
|
||||
int tx = position.getX() - srcOrigin.getX();
|
||||
int ty = position.getY() - srcOrigin.getY();
|
||||
int tz = position.getZ() - srcOrigin.getZ();
|
||||
|
||||
//"int angle" specifies a rotation consistent with Minecraft's orientation system.
|
||||
//That means each increment of 1 in angle would be a 90-degree clockwise turn.
|
||||
//Given a starting direction A and a destination direction B, the rotation would be
|
||||
//calculated by (B - A).
|
||||
|
||||
//Adjust angle into the expected range
|
||||
if (angle < 0)
|
||||
{
|
||||
int correction = -(angle / 4);
|
||||
angle = angle + 4 * (correction + 1);
|
||||
}
|
||||
angle = angle % 4;
|
||||
|
||||
int rx;
|
||||
int rz;
|
||||
switch (angle)
|
||||
{
|
||||
case 0: //No rotation
|
||||
rx = tx;
|
||||
rz = tz;
|
||||
break;
|
||||
case 1: //90 degrees clockwise
|
||||
rx = -tz;
|
||||
rz = tx;
|
||||
break;
|
||||
case 2: //180 degrees
|
||||
rx = -tx;
|
||||
rz = -tz;
|
||||
break;
|
||||
case 3: //270 degrees clockwise
|
||||
rx = tz;
|
||||
rz = -tx;
|
||||
|
||||
break;
|
||||
default: //This should never happen
|
||||
throw new IllegalStateException("Invalid angle value. This should never happen!");
|
||||
}
|
||||
|
||||
position.setX( rx + destOrigin.getX() );
|
||||
position.setY( ty + destOrigin.getY() );
|
||||
position.setZ( rz + destOrigin.getZ() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
|
||||
public class CompactBoundsOperation extends WorldOperation
|
||||
{
|
||||
private int minX;
|
||||
private int minY;
|
||||
private int minZ;
|
||||
private int maxX;
|
||||
private int maxY;
|
||||
private int maxZ;
|
||||
|
||||
public CompactBoundsOperation()
|
||||
{
|
||||
super("CompactBoundsOperation");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
minX = Integer.MAX_VALUE;
|
||||
minY = Integer.MAX_VALUE;
|
||||
minZ = Integer.MAX_VALUE;
|
||||
maxX = x;
|
||||
maxY = y;
|
||||
maxZ = z;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||
{
|
||||
//This could be done more efficiently, but honestly, this is the simplest approach and it
|
||||
//makes it easy for us to verify that the code is correct.
|
||||
if (!world.isAirBlock(x, y, z))
|
||||
{
|
||||
maxX = x > maxX ? x : maxX;
|
||||
maxZ = z > maxZ ? z : maxZ;
|
||||
maxY = y > maxY ? y : maxY;
|
||||
|
||||
minX = x < minX ? x : minX;
|
||||
minZ = z < minZ ? z : minZ;
|
||||
minY = y < minY ? y : minY;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean finish()
|
||||
{
|
||||
if (minX == Integer.MAX_VALUE)
|
||||
{
|
||||
//The whole search space was empty!
|
||||
//Compact the space to a single block.
|
||||
minX = maxX;
|
||||
minY = maxY;
|
||||
minZ = maxZ;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Point3D getMaxCorner()
|
||||
{
|
||||
return new Point3D(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public Point3D getMinCorner()
|
||||
{
|
||||
return new Point3D(minX, minY, minZ);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CompoundFilter extends SchematicFilter {
|
||||
|
||||
private ArrayList<SchematicFilter> filters;
|
||||
|
||||
public CompoundFilter()
|
||||
{
|
||||
super("CompoundFilter");
|
||||
filters = new ArrayList<SchematicFilter>();
|
||||
}
|
||||
|
||||
public void addFilter(SchematicFilter filter)
|
||||
{
|
||||
filters.add(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (!filter.initialize(schematic, blocks, metadata))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !filters.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean finish()
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (!filter.finish())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||
{
|
||||
for (SchematicFilter filter : filters)
|
||||
{
|
||||
if (filter.applyToBlock(index, blocks, metadata))
|
||||
{
|
||||
return filter.terminates();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
public class InvalidSchematicException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -1011044077455149932L;
|
||||
|
||||
public InvalidSchematicException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidSchematicException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidSchematicException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
|
||||
public class ReplacementFilter extends SchematicFilter {
|
||||
|
||||
private short targetBlock;
|
||||
private byte targetMetadata;
|
||||
private boolean matchMetadata;
|
||||
private short replacementBlock;
|
||||
private byte replacementMetadata;
|
||||
private boolean changeMetadata;
|
||||
|
||||
public ReplacementFilter(short targetBlock, byte targetMetadata, short replacementBlock, byte replacementMetadata)
|
||||
{
|
||||
super("ReplacementFilter");
|
||||
this.targetBlock = targetBlock;
|
||||
this.targetMetadata = targetMetadata;
|
||||
this.matchMetadata = true;
|
||||
this.replacementBlock = replacementBlock;
|
||||
this.replacementMetadata = replacementMetadata;
|
||||
this.changeMetadata = true;
|
||||
}
|
||||
|
||||
public ReplacementFilter(short targetBlock, short replacementBlock, byte replacementMetadata)
|
||||
{
|
||||
super("ReplacementFilter");
|
||||
this.targetBlock = targetBlock;
|
||||
this.matchMetadata = false;
|
||||
this.replacementBlock = replacementBlock;
|
||||
this.replacementMetadata = replacementMetadata;
|
||||
this.changeMetadata = true;
|
||||
}
|
||||
|
||||
public ReplacementFilter(short targetBlock, byte targetMetadata, short replacementBlock)
|
||||
{
|
||||
super("ReplacementFilter");
|
||||
this.targetBlock = targetBlock;
|
||||
this.targetMetadata = targetMetadata;
|
||||
this.matchMetadata = true;
|
||||
this.replacementBlock = replacementBlock;
|
||||
this.changeMetadata = false;
|
||||
}
|
||||
|
||||
public ReplacementFilter(short targetBlock, short replacementBlock)
|
||||
{
|
||||
super("ReplacementFilter");
|
||||
this.targetBlock = targetBlock;
|
||||
this.matchMetadata = false;
|
||||
this.replacementBlock = replacementBlock;
|
||||
this.changeMetadata = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||
{
|
||||
if (blocks[index] == targetBlock)
|
||||
{
|
||||
if ((matchMetadata && metadata[index] == targetMetadata) || !matchMetadata)
|
||||
{
|
||||
blocks[index] = replacementBlock;
|
||||
if (changeMetadata)
|
||||
{
|
||||
metadata[index] = replacementMetadata;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean terminates()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,435 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
|
||||
/**
|
||||
* Represents an MC schematic and provides functions for loading, storing, and manipulating schematics.
|
||||
* This functionality has no dependencies to Dimensional Doors.
|
||||
*/
|
||||
public class Schematic {
|
||||
|
||||
protected short width;
|
||||
protected short height;
|
||||
protected short length;
|
||||
|
||||
protected short[] blocks;
|
||||
protected byte[] metadata;
|
||||
protected NBTTagList tileEntities;
|
||||
|
||||
protected Schematic(short width, short height, short length, short[] blocks, byte[] metadata, NBTTagList tileEntities)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.length = length;
|
||||
this.blocks = blocks;
|
||||
this.metadata = metadata;
|
||||
this.tileEntities = tileEntities;
|
||||
}
|
||||
|
||||
protected Schematic(Schematic source)
|
||||
{
|
||||
//Shallow copy constructor - critical for code reuse in derived classes since
|
||||
//source's fields will be inaccessible if the derived class is in another package.
|
||||
this.width = source.width;
|
||||
this.height = source.height;
|
||||
this.length = source.length;
|
||||
this.blocks = source.blocks;
|
||||
this.metadata = source.metadata;
|
||||
this.tileEntities = source.tileEntities;
|
||||
}
|
||||
|
||||
public int calculateIndex(int x, int y, int z)
|
||||
{
|
||||
if (x < 0 || x >= width)
|
||||
throw new IndexOutOfBoundsException("x must be non-negative and less than width");
|
||||
if (y < 0 || y >= height)
|
||||
throw new IndexOutOfBoundsException("y must be non-negative and less than height");
|
||||
if (z < 0 || z >= length)
|
||||
throw new IndexOutOfBoundsException("z must be non-negative and less than length");
|
||||
|
||||
return (y * width * length + z * width + x);
|
||||
}
|
||||
|
||||
public Point3D calculatePoint(int index)
|
||||
{
|
||||
int y = index / (width * length);
|
||||
index -= y * width * length;
|
||||
int z = index / width;
|
||||
index -= z * width;
|
||||
int x = index;
|
||||
|
||||
return new Point3D(x, y, z);
|
||||
}
|
||||
|
||||
public int calculateIndexBelow(int index)
|
||||
{
|
||||
return index - (width * length);
|
||||
}
|
||||
|
||||
public short getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public short getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public short getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
public short getBlockID(int x, int y, int z)
|
||||
{
|
||||
return blocks[calculateIndex(x, y, z)];
|
||||
}
|
||||
|
||||
public byte getBlockMetadata(int x, int y, int z)
|
||||
{
|
||||
return metadata[calculateIndex(x, y, z)];
|
||||
}
|
||||
|
||||
public NBTTagList getTileEntities()
|
||||
{
|
||||
return (NBTTagList) tileEntities.copy();
|
||||
}
|
||||
|
||||
public static Schematic readFromFile(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
return readFromFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public static Schematic readFromFile(File schematicFile) throws FileNotFoundException, InvalidSchematicException
|
||||
{
|
||||
// TODO: fix resource leaks here
|
||||
return readFromStream(new FileInputStream(schematicFile));
|
||||
}
|
||||
|
||||
public static Schematic readFromResource(String resourcePath) throws InvalidSchematicException
|
||||
{
|
||||
//We need an instance of a class in the mod to retrieve a resource
|
||||
Schematic empty = new Schematic((short) 0, (short) 0, (short) 0, null, null, null);
|
||||
InputStream schematicStream = empty.getClass().getResourceAsStream(resourcePath);
|
||||
return readFromStream(schematicStream);
|
||||
}
|
||||
|
||||
public static Schematic readFromStream(InputStream schematicStream) throws InvalidSchematicException
|
||||
{
|
||||
short width;
|
||||
short height;
|
||||
short length;
|
||||
int volume;
|
||||
int pairs;
|
||||
|
||||
byte[] metadata = null; //block metadata
|
||||
byte[] lowBits = null; //first 8 bits of the block IDs
|
||||
byte[] highBits = null; //additional 4 bits of the block IDs
|
||||
short[] blocks = null; //list of combined block IDs
|
||||
NBTTagList tileEntities = null; //storage for tile entities in NBT form
|
||||
NBTTagCompound schematicTag; //the NBT data extracted from the schematic file
|
||||
boolean hasExtendedBlockIDs; //indicates whether the schematic contains extended block IDs
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
schematicTag = CompressedStreamTools.readCompressed(schematicStream);
|
||||
schematicStream.close(); //readCompressed() probably closes the stream anyway, but close again to be sure.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidSchematicException("The schematic could not be decoded.");
|
||||
}
|
||||
|
||||
//load size of schematic to generate
|
||||
width = schematicTag.getShort("Width");
|
||||
height = schematicTag.getShort("Height");
|
||||
length = schematicTag.getShort("Length");
|
||||
volume = width * length * height;
|
||||
|
||||
if (width < 0)
|
||||
throw new InvalidSchematicException("The schematic cannot have a negative width.");
|
||||
if (height < 0)
|
||||
throw new InvalidSchematicException("The schematic cannot have a negative height.");
|
||||
if (length < 0)
|
||||
throw new InvalidSchematicException("The schematic cannot have a negative length.");
|
||||
|
||||
//load block info
|
||||
lowBits = schematicTag.getByteArray("Blocks");
|
||||
highBits = schematicTag.getByteArray("AddBlocks");
|
||||
metadata = schematicTag.getByteArray("Data");
|
||||
hasExtendedBlockIDs = (highBits.length != 0);
|
||||
|
||||
if (volume != lowBits.length)
|
||||
throw new InvalidSchematicException("The schematic has data for fewer blocks than its dimensions indicate.");
|
||||
if (volume != metadata.length)
|
||||
throw new InvalidSchematicException("The schematic has metadata for fewer blocks than its dimensions indicate.");
|
||||
if (volume > 2 * highBits.length && hasExtendedBlockIDs)
|
||||
throw new InvalidSchematicException("The schematic has extended block IDs for fewer blocks than its dimensions indicate.");
|
||||
|
||||
blocks = new short[volume];
|
||||
if (hasExtendedBlockIDs)
|
||||
{
|
||||
//Combine the split block IDs into a single value
|
||||
pairs = volume - (volume & 1);
|
||||
int index;
|
||||
for (index = 0; index < pairs; index += 2)
|
||||
{
|
||||
blocks[index] = (short) (((highBits[index >> 1] & 0x0F) << 8) + (lowBits[index] & 0xFF));
|
||||
blocks[index + 1] = (short) (((highBits[index >> 1] & 0xF0) << 4) + (lowBits[index + 1] & 0xFF));
|
||||
}
|
||||
if (index < volume)
|
||||
{
|
||||
blocks[index] = lowBits[index >> 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Copy the blockIDs
|
||||
for (int index = 0; index < volume; index++)
|
||||
{
|
||||
blocks[index] = (short) (lowBits[index] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
//Get the list of tile entities
|
||||
tileEntities = schematicTag.getTagList("TileEntities");
|
||||
|
||||
Schematic result = new Schematic(width, height, length, blocks, metadata, tileEntities);
|
||||
return result;
|
||||
}
|
||||
catch (InvalidSchematicException ex)
|
||||
{
|
||||
//Throw the exception again to pass it to the caller.
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidSchematicException("An unexpected error occurred while trying to decode the schematic.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length, boolean doCompactBounds)
|
||||
{
|
||||
if (doCompactBounds)
|
||||
{
|
||||
//Adjust the vertical bounds to reasonable values if necessary
|
||||
int worldHeight = world.getHeight();
|
||||
int fixedY = (y < 0) ? 0 : y;
|
||||
int fixedHeight = height + y - fixedY;
|
||||
|
||||
if (fixedHeight + fixedY >= worldHeight)
|
||||
{
|
||||
fixedHeight = worldHeight - fixedY;
|
||||
}
|
||||
|
||||
//Compact the area to be copied to remove empty borders
|
||||
CompactBoundsOperation compactor = new CompactBoundsOperation();
|
||||
compactor.apply(world, x, fixedY, z, width, fixedHeight, length);
|
||||
Point3D minCorner = compactor.getMinCorner();
|
||||
Point3D maxCorner = compactor.getMaxCorner();
|
||||
|
||||
short compactWidth = (short) (maxCorner.getX() - minCorner.getX() + 1);
|
||||
short compactHeight = (short) (maxCorner.getY() - minCorner.getY() + 1);
|
||||
short compactLength = (short) (maxCorner.getZ() - minCorner.getZ() + 1);
|
||||
|
||||
return copyFromWorld(world, minCorner.getX(), minCorner.getY(), minCorner.getZ(),
|
||||
compactWidth, compactHeight, compactLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
return copyFromWorld(world, x, y, z, width, height, length);
|
||||
}
|
||||
}
|
||||
|
||||
private static Schematic copyFromWorld(World world, int x, int y, int z, short width, short height, short length)
|
||||
{
|
||||
//Short and sweet ^_^
|
||||
WorldCopyOperation copier = new WorldCopyOperation();
|
||||
copier.apply(world, x, y, z, width, height, length);
|
||||
return new Schematic(width, height, length, copier.getBlockIDs(), copier.getMetadata(), copier.getTileEntities());
|
||||
}
|
||||
|
||||
private static boolean encodeBlockIDs(short[] blocks, byte[] lowBits, byte[] highBits)
|
||||
{
|
||||
int index;
|
||||
int length = blocks.length - (blocks.length & 1);
|
||||
boolean hasHighBits = false;
|
||||
for (index = 0; index < length; index += 2)
|
||||
{
|
||||
highBits[index >> 1] = (byte) (((blocks[index] >> 8) & 0x0F) + ((blocks[index + 1] >> 4) & 0xF0));
|
||||
hasHighBits |= (highBits[index >> 1] != 0);
|
||||
}
|
||||
if (index < blocks.length)
|
||||
{
|
||||
highBits[index >> 1] = (byte) ((blocks[index] >> 8) & 0x0F);
|
||||
hasHighBits |= (highBits[index >> 1] != 0);
|
||||
}
|
||||
for (index = 0; index < blocks.length; index++)
|
||||
{
|
||||
lowBits[index] = (byte) (blocks[index] & 0xFF);
|
||||
}
|
||||
return hasHighBits;
|
||||
}
|
||||
|
||||
public NBTTagCompound writeToNBT()
|
||||
{
|
||||
return writeToNBT(true);
|
||||
}
|
||||
|
||||
protected NBTTagCompound writeToNBT(boolean copyTileEntities)
|
||||
{
|
||||
return writeToNBT(width, height, length, blocks, metadata, tileEntities, copyTileEntities);
|
||||
}
|
||||
|
||||
protected static NBTTagCompound writeToNBT(short width, short height, short length, short[] blocks, byte[] metadata,
|
||||
NBTTagList tileEntities, boolean copyTileEntities)
|
||||
{
|
||||
//This is the main storage function. Schematics are really compressed NBT tags, so if we can generate
|
||||
//the tags, most of the work is done. All the other storage functions will rely on this one.
|
||||
|
||||
NBTTagCompound schematicTag = new NBTTagCompound("Schematic");
|
||||
|
||||
schematicTag.setShort("Width", width);
|
||||
schematicTag.setShort("Length", length);
|
||||
schematicTag.setShort("Height", height);
|
||||
|
||||
schematicTag.setTag("Entities", new NBTTagList());
|
||||
schematicTag.setString("Materials", "Alpha");
|
||||
|
||||
byte[] lowBits = new byte[blocks.length];
|
||||
byte[] highBits = new byte[(blocks.length >> 1) + (blocks.length & 1)];
|
||||
boolean hasExtendedIDs = encodeBlockIDs(blocks, lowBits, highBits);
|
||||
|
||||
schematicTag.setByteArray("Blocks", lowBits);
|
||||
schematicTag.setByteArray("Data", metadata);
|
||||
|
||||
if (hasExtendedIDs)
|
||||
{
|
||||
schematicTag.setByteArray("AddBlocks", highBits);
|
||||
}
|
||||
|
||||
if (copyTileEntities)
|
||||
{
|
||||
//Used when the result of this function will be passed outside this class.
|
||||
//Avoids exposing the private field to external modifications.
|
||||
schematicTag.setTag("TileEntities", tileEntities.copy());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Used when the result of this function is for internal use.
|
||||
//It's more efficient not to copy the tags unless it's needed.
|
||||
schematicTag.setTag("TileEntities", tileEntities);
|
||||
}
|
||||
return schematicTag;
|
||||
}
|
||||
|
||||
public void writeToFile(String schematicPath) throws IOException
|
||||
{
|
||||
writeToFile(new File(schematicPath));
|
||||
}
|
||||
|
||||
public void writeToFile(File schematicFile) throws IOException
|
||||
{
|
||||
FileOutputStream outputStream = new FileOutputStream(schematicFile);
|
||||
CompressedStreamTools.writeCompressed(writeToNBT(false), outputStream);
|
||||
//writeCompressed() probably closes the stream on its own - call close again just in case.
|
||||
//Closing twice will not throw an exception.
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
public boolean applyFilter(SchematicFilter filter)
|
||||
{
|
||||
return filter.apply(this, this.blocks, this.metadata);
|
||||
}
|
||||
|
||||
public void copyToWorld(World world, int x, int y, int z)
|
||||
{
|
||||
//This isn't implemented as a WorldOperation because it doesn't quite fit the structure of those operations.
|
||||
//It's not worth the trouble in this case.
|
||||
int index;
|
||||
int count;
|
||||
int dx, dy, dz;
|
||||
|
||||
//Copy blocks and metadata into the world
|
||||
index = 0;
|
||||
for (dy = 0; dy < height; dy++)
|
||||
{
|
||||
for (dz = 0; dz < length; dz++)
|
||||
{
|
||||
for (dx = 0; dx < width; dx++)
|
||||
{
|
||||
//In the future, we might want to make this more efficient by building whole chunks at a time
|
||||
setBlockDirectly(world, x + dx, y + dy, z + dz, blocks[index], metadata[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Copy tile entities into the world
|
||||
count = tileEntities.tagCount();
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
NBTTagCompound tileTag = (NBTTagCompound) tileEntities.tagAt(index);
|
||||
//Rewrite its location to be in world coordinates
|
||||
dx = tileTag.getInteger("x") + x;
|
||||
dy = tileTag.getInteger("y") + y;
|
||||
dz = tileTag.getInteger("z") + z;
|
||||
tileTag.setInteger("x", dx);
|
||||
tileTag.setInteger("y", dy);
|
||||
tileTag.setInteger("z", dz);
|
||||
//Load the tile entity and put it in the world
|
||||
world.setBlockTileEntity(dx, dy, dz, TileEntity.createAndLoadEntity(tileTag));
|
||||
}
|
||||
}
|
||||
|
||||
protected static void setBlockDirectly(World world, int x, int y, int z, int blockID, int metadata)
|
||||
{
|
||||
if (blockID != 0 && Block.blocksList[blockID] == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int cX = x >> 4;
|
||||
int cZ = z >> 4;
|
||||
int cY = y >> 4;
|
||||
Chunk chunk;
|
||||
|
||||
int localX = (x % 16) < 0 ? (x % 16) + 16 : (x % 16);
|
||||
int localZ = (z % 16) < 0 ? (z % 16) + 16 : (z % 16);
|
||||
ExtendedBlockStorage extBlockStorage;
|
||||
|
||||
try
|
||||
{
|
||||
chunk = world.getChunkFromChunkCoords(cX, cZ);
|
||||
extBlockStorage = chunk.getBlockStorageArray()[cY];
|
||||
if (extBlockStorage == null)
|
||||
{
|
||||
extBlockStorage = new ExtendedBlockStorage(cY << 4, !world.provider.hasNoSky);
|
||||
chunk.getBlockStorageArray()[cY] = extBlockStorage;
|
||||
}
|
||||
extBlockStorage.setExtBlockID(localX, y & 15, localZ, blockID);
|
||||
extBlockStorage.setExtBlockMetadata(localX, y & 15, localZ, metadata);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
public class SchematicFilter {
|
||||
|
||||
private String name;
|
||||
|
||||
protected SchematicFilter(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean apply(Schematic schematic, short[] blocks, byte[] metadata)
|
||||
{
|
||||
if (!initialize(schematic, blocks, metadata))
|
||||
return false;
|
||||
|
||||
for (int index = 0; index < blocks.length; index++)
|
||||
{
|
||||
if (applyToBlock(index, blocks, metadata) && terminates())
|
||||
return false;
|
||||
}
|
||||
|
||||
return finish();
|
||||
}
|
||||
|
||||
protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean applyToBlock(int index, short[] blocks, byte[] metadata)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean finish()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean terminates()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class WorldCopyOperation extends WorldOperation
|
||||
{
|
||||
private int originX;
|
||||
private int originY;
|
||||
private int originZ;
|
||||
private int index;
|
||||
private short[] blockIDs;
|
||||
private byte[] metadata;
|
||||
private NBTTagList tileEntities;
|
||||
|
||||
public WorldCopyOperation()
|
||||
{
|
||||
super("WorldCopyOperation");
|
||||
blockIDs = null;
|
||||
metadata = null;
|
||||
tileEntities = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
index = 0;
|
||||
originX = x;
|
||||
originY = y;
|
||||
originZ = z;
|
||||
blockIDs = new short[width * height * length];
|
||||
metadata = new byte[width * height * length];
|
||||
tileEntities = new NBTTagList();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||
{
|
||||
blockIDs[index] = (short) world.getBlockId(x, y, z);
|
||||
metadata[index] = (byte) world.getBlockMetadata(x, y, z);
|
||||
|
||||
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
|
||||
if (tileEntity != null)
|
||||
{
|
||||
//Extract tile entity data
|
||||
NBTTagCompound tileTag = new NBTTagCompound();
|
||||
tileEntity.writeToNBT(tileTag);
|
||||
//Translate the tile entity's position from the world's coordinate system
|
||||
//to the schematic's coordinate system.
|
||||
tileTag.setInteger("x", x - originX);
|
||||
tileTag.setInteger("y", y - originY);
|
||||
tileTag.setInteger("z", z - originZ);
|
||||
tileEntities.appendTag(tileTag);
|
||||
}
|
||||
index++; //This works assuming the loops in WorldOperation are done in YZX order
|
||||
return true;
|
||||
}
|
||||
|
||||
public short[] getBlockIDs()
|
||||
{
|
||||
return blockIDs;
|
||||
}
|
||||
|
||||
public byte[] getMetadata()
|
||||
{
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public NBTTagList getTileEntities()
|
||||
{
|
||||
return tileEntities;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.schematic;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class WorldOperation {
|
||||
|
||||
private String name;
|
||||
|
||||
public WorldOperation(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean applyToBlock(World world, int x, int y, int z);
|
||||
|
||||
protected boolean finish()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean apply(World world, Point3D minCorner, Point3D maxCorner)
|
||||
{
|
||||
int x = minCorner.getX();
|
||||
int y = minCorner.getY();
|
||||
int z = minCorner.getZ();
|
||||
int width = maxCorner.getX() - x + 1;
|
||||
int height = maxCorner.getY() - y + 1;
|
||||
int length = maxCorner.getZ() - z + 1;
|
||||
return apply(world, x, y, z, width, height, length);
|
||||
}
|
||||
|
||||
public boolean apply(World world, int x, int y, int z, int width, int height, int length)
|
||||
{
|
||||
if (!initialize(world, x, y, z, width, height, length))
|
||||
return false;
|
||||
|
||||
int cx, cy, cz;
|
||||
int limitX = x + width;
|
||||
int limitY = y + height;
|
||||
int limitZ = z + length;
|
||||
|
||||
//The order of these loops is important. Don't change it! It's used to avoid calculating
|
||||
//indeces in some schematic operations. The proper order is YZX.
|
||||
for (cy = y; cy < limitY; cy++)
|
||||
{
|
||||
for (cz = z; cz < limitZ; cz++)
|
||||
{
|
||||
for (cx = x; cx < limitX; cx++)
|
||||
{
|
||||
if (!applyToBlock(world, cx, cy, cz))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finish();
|
||||
}
|
||||
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
|
||||
import cpw.mods.fml.common.ITickHandler;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
|
||||
public class CommonTickHandler implements ITickHandler, IRegularTickSender
|
||||
{
|
||||
private static final String PROFILING_LABEL = "Dimensional Doors: Common Tick";
|
||||
|
||||
private int tickCount = 0;
|
||||
private ArrayList<RegularTickReceiverInfo> receivers;
|
||||
|
||||
|
||||
public CommonTickHandler()
|
||||
{
|
||||
this.receivers = new ArrayList<RegularTickReceiverInfo>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart)
|
||||
{
|
||||
RegularTickReceiverInfo info = new RegularTickReceiverInfo(receiver, interval, onTickStart);
|
||||
receivers.add(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
if (type.equals(EnumSet.of(TickType.SERVER)))
|
||||
{
|
||||
for (RegularTickReceiverInfo info : receivers)
|
||||
{
|
||||
if (info.OnTickStart && tickCount % info.Interval == 0)
|
||||
{
|
||||
info.RegularTickReceiver.notifyTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Stuck this in here because it's already rather hackish.
|
||||
//We should standardize this as an IRegularTickReceiver in the future. ~SenseiKiwi
|
||||
if (DDTeleporter.cooldown > 0)
|
||||
{
|
||||
DDTeleporter.cooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
for (RegularTickReceiverInfo info : receivers)
|
||||
{
|
||||
if (!info.OnTickStart && tickCount % info.Interval == 0)
|
||||
{
|
||||
info.RegularTickReceiver.notifyTick();
|
||||
}
|
||||
}
|
||||
tickCount++; //There is no need to reset the counter. Let it overflow.
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<TickType> ticks()
|
||||
{
|
||||
return EnumSet.of(TickType.SERVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return PROFILING_LABEL; //Used for profiling!
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package StevenDimDoors.mod_pocketDim.ticking;
|
||||
|
||||
|
||||
public interface IRegularTickReceiver {
|
||||
|
||||
/**
|
||||
* This method is called periodically to execute code based on ticks elapsed.
|
||||
*/
|
||||
public void notifyTick();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user