From 3c027330a4b92c2e353c2000464ff32b1da24089 Mon Sep 17 00:00:00 2001 From: Henry Mao Date: Mon, 4 Feb 2013 11:32:04 +0800 Subject: [PATCH] IC2 API Inclusion --- .gitignore | 1 + src/minecraft/ic2/api/BaseSeed.java | 56 +++ src/minecraft/ic2/api/CropCard.java | 475 ++++++++++++++++++ src/minecraft/ic2/api/Crops.java | 47 ++ src/minecraft/ic2/api/Direction.java | 107 ++++ src/minecraft/ic2/api/ElectricItem.java | 128 +++++ src/minecraft/ic2/api/ExplosionWhitelist.java | 46 ++ src/minecraft/ic2/api/IBoxable.java | 18 + src/minecraft/ic2/api/IC2Reactor.java | 28 ++ .../ic2/api/ICustomElectricItem.java | 64 +++ src/minecraft/ic2/api/IElectricItem.java | 52 ++ src/minecraft/ic2/api/IEnergyStorage.java | 52 ++ src/minecraft/ic2/api/IMetalArmor.java | 20 + src/minecraft/ic2/api/IPaintableBlock.java | 21 + src/minecraft/ic2/api/IReactor.java | 134 +++++ src/minecraft/ic2/api/IReactorChamber.java | 13 + src/minecraft/ic2/api/IReactorComponent.java | 97 ++++ src/minecraft/ic2/api/ITerraformingBP.java | 35 ++ src/minecraft/ic2/api/IWrenchable.java | 59 +++ src/minecraft/ic2/api/Ic2Recipes.java | 358 +++++++++++++ src/minecraft/ic2/api/Items.java | 401 +++++++++++++++ src/minecraft/ic2/api/TECrop.java | 161 ++++++ src/minecraft/ic2/api/energy/EnergyNet.java | 175 +++++++ .../ic2/api/energy/event/EnergyTileEvent.java | 17 + .../api/energy/event/EnergyTileLoadEvent.java | 24 + .../energy/event/EnergyTileSourceEvent.java | 33 ++ .../energy/event/EnergyTileUnloadEvent.java | 25 + .../ic2/api/energy/tile/IEnergyAcceptor.java | 22 + .../ic2/api/energy/tile/IEnergyConductor.java | 51 ++ .../ic2/api/energy/tile/IEnergyEmitter.java | 23 + .../ic2/api/energy/tile/IEnergySink.java | 41 ++ .../ic2/api/energy/tile/IEnergySource.java | 15 + .../ic2/api/energy/tile/IEnergyTile.java | 18 + src/minecraft/ic2/api/energy/usage.txt | 101 ++++ ...INetworkClientTileEntityEventListener.java | 17 + .../ic2/api/network/INetworkDataProvider.java | 18 + .../network/INetworkItemEventListener.java | 18 + .../INetworkTileEntityEventListener.java | 14 + .../api/network/INetworkUpdateListener.java | 14 + .../ic2/api/network/NetworkHelper.java | 243 +++++++++ 40 files changed, 3242 insertions(+) create mode 100644 src/minecraft/ic2/api/BaseSeed.java create mode 100644 src/minecraft/ic2/api/CropCard.java create mode 100644 src/minecraft/ic2/api/Crops.java create mode 100644 src/minecraft/ic2/api/Direction.java create mode 100644 src/minecraft/ic2/api/ElectricItem.java create mode 100644 src/minecraft/ic2/api/ExplosionWhitelist.java create mode 100644 src/minecraft/ic2/api/IBoxable.java create mode 100644 src/minecraft/ic2/api/IC2Reactor.java create mode 100644 src/minecraft/ic2/api/ICustomElectricItem.java create mode 100644 src/minecraft/ic2/api/IElectricItem.java create mode 100644 src/minecraft/ic2/api/IEnergyStorage.java create mode 100644 src/minecraft/ic2/api/IMetalArmor.java create mode 100644 src/minecraft/ic2/api/IPaintableBlock.java create mode 100644 src/minecraft/ic2/api/IReactor.java create mode 100644 src/minecraft/ic2/api/IReactorChamber.java create mode 100644 src/minecraft/ic2/api/IReactorComponent.java create mode 100644 src/minecraft/ic2/api/ITerraformingBP.java create mode 100644 src/minecraft/ic2/api/IWrenchable.java create mode 100644 src/minecraft/ic2/api/Ic2Recipes.java create mode 100644 src/minecraft/ic2/api/Items.java create mode 100644 src/minecraft/ic2/api/TECrop.java create mode 100644 src/minecraft/ic2/api/energy/EnergyNet.java create mode 100644 src/minecraft/ic2/api/energy/event/EnergyTileEvent.java create mode 100644 src/minecraft/ic2/api/energy/event/EnergyTileLoadEvent.java create mode 100644 src/minecraft/ic2/api/energy/event/EnergyTileSourceEvent.java create mode 100644 src/minecraft/ic2/api/energy/event/EnergyTileUnloadEvent.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergyAcceptor.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergyConductor.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergyEmitter.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergySink.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergySource.java create mode 100644 src/minecraft/ic2/api/energy/tile/IEnergyTile.java create mode 100644 src/minecraft/ic2/api/energy/usage.txt create mode 100644 src/minecraft/ic2/api/network/INetworkClientTileEntityEventListener.java create mode 100644 src/minecraft/ic2/api/network/INetworkDataProvider.java create mode 100644 src/minecraft/ic2/api/network/INetworkItemEventListener.java create mode 100644 src/minecraft/ic2/api/network/INetworkTileEntityEventListener.java create mode 100644 src/minecraft/ic2/api/network/INetworkUpdateListener.java create mode 100644 src/minecraft/ic2/api/network/NetworkHelper.java diff --git a/.gitignore b/.gitignore index 6a96edb22..a986b02ab 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ CHANGELOG !/src/minecraft/assemblyline/ !/src/minecraft/universalelectricity/ !/src/minecraft/dan200 +!/src/minecraft/ic2 !/resources/ !/models/ !info.txt diff --git a/src/minecraft/ic2/api/BaseSeed.java b/src/minecraft/ic2/api/BaseSeed.java new file mode 100644 index 000000000..6f4e57a54 --- /dev/null +++ b/src/minecraft/ic2/api/BaseSeed.java @@ -0,0 +1,56 @@ +package ic2.api; + +/** + * Base agriculture seed. Used to determine the state of a plant once it is planted from an item. + */ +public class BaseSeed { + /** + * Plant ID. + */ + public int id; + + /** + * Plant size. + */ + public int size; + + /** + * Plant growth stat. + */ + public int statGrowth; + + /** + * Plant gain stat. + */ + public int statGain; + + /** + * Plant resistance stat. + */ + public int statResistance; + + /** + * For internal usage only. + */ + public int stackSize; + + /** + * Create a BaseSeed object. + * + * @param id plant ID + * @param size plant size + * @param statGrowth plant growth stat + * @param statGain plant gain stat + * @param statResistance plant resistance stat + * @param stackSize for internal usage only + */ + public BaseSeed(int id, int size, int statGrowth, int statGain, int statResistance, int stackSize) { + super(); + this.id = id; + this.size = size; + this.statGrowth = statGrowth; + this.statGain = statGain; + this.statResistance = statResistance; + this.stackSize = stackSize; + } +} diff --git a/src/minecraft/ic2/api/CropCard.java b/src/minecraft/ic2/api/CropCard.java new file mode 100644 index 000000000..86aec1362 --- /dev/null +++ b/src/minecraft/ic2/api/CropCard.java @@ -0,0 +1,475 @@ +package ic2.api; + +import java.util.HashMap; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * Base agriculture crop. + * + * Any crop extending this can be registered using registerCrop to be added into the game. + */ +public abstract class CropCard +{ + /** + * Plant name. Will be displayed to the player. + * + * @return Plant name + */ + public abstract String name(); + + /** + * Your name here, will be shown in "Discovered by:" when analyzing seeds. + * + * @return Your name + */ + public String discoveredBy() {return "Alblaka";} + + /** + * Description of your plant. Keep it short, a few characters per line for up to two lines. + * Default is showing attributes of your plant, 2 per line. + * + * @param i line to get, starting from 0 + * @return The line + */ + public String desc(int i) + { + String[] att = attributes(); + if (att == null || att.length==0) return ""; + if (i == 0) + { + String s = att[0]; + if (att.length >= 2) + { + s+=", "+att[1]; + if (att.length >= 3) s+=","; + } + return s; + } + else + { + if (att.length < 3) return ""; + String s = att[2]; + if (att.length >= 4) s+=", "+att[3]; + return s; + } + } + + /** + * Tier of the plant. Ranges from 1 to 16, 0 is Weed. + * Valuable and powerful crops have higher tiers, useless and weak ones have lower tiers. + * + * @return Tier + */ + public abstract int tier(); + + /** + * Describe the plant through a set of stats, influencing breeding. + * Plants sharing stats and attributes will tend to cross-breed more often. + * + * Stats: + * - 0: Chemistry (Industrial uses based on chemical plant components) + * - 1: Consumable (Food, potion ingredients, stuff meant to be eaten or similarly used) + * - 2: Defensive (Plants with defense capabilities (damaging, explosive, chemical) or special abilities in general) + * - 3: Colorful (How colorful/aesthetically/beautiful is the plant, like dye-plants or plants without actual effects) + * - 4: Weed (Is this plant weed-like and rather unwanted/quick-spreading? Rare super-breed plants should have low values here) + * + * @param n index of the requested stat + * @return The requested value of the stats + */ + public abstract int stat(int n); + + /** + * Additional attributes of the plant, also influencing breeding. + * Plants sharing stats and attributes will tend to cross-breed more often. + * + * @return Attributes as an array of strings + */ + public abstract String[] attributes(); + + /** + * Sprite index the crop is meant to be rendered with. + * + * @param crop reference to TECrop + * @return 0-255, representing the sprite index on the crop's spritesheet. + */ + public abstract int getSpriteIndex(TECrop crop); + + /** + * Get the crop's spritesheet. + * Per default crops_0.png of ic2-sprites + * @return Texture file path + */ + public String getTextureFile() { + return "/ic2/sprites/crops_0.png"; + } + + /** + * Amount of growth points needed to increase the plant's size. + * Default is 200 * tier. + */ + public int growthDuration(TECrop crop) + { + return tier()*200; + } + + /** + * Check whether the plant can grow further. + * + * Consider: + * - Humidity, nutrients and air quality + * - Current size + * - Light level + * - Special biomes or conditions, accessible through crop.worldObj + * + * This method will be called upon empty upgraded crops to check whether a neighboring plant can cross onto it! Don't check if the size is greater than 0 and if the ID is real. + * + * @param crop reference to TECrop + * @return Whether the crop can grow + */ + public abstract boolean canGrow(TECrop crop); + + /** + * Calculate the influence for the plant to grow based on humidity, nutrients and air. + * Normal behavior is rating the three stats "normal", with each of them ranging from 0-30. + * Basic rule: Assume everything returns 10. All together must equal 30. Add the factors to your likings, for example (humidity*0.7)+(nutrients*0.9)+(air*1.4) + * + * Default is humidity + nutrients + air (no factors). + * + * @param crop reference to TECrop + * @param humidity ground humidity, influenced by hydration + * @param nutrients nutrient quality in ground, based on fertilizers + * @param air air quality, influences by open gardens and less crops surrounding this one + * @return 0-30 + */ + public int weightInfluences(TECrop crop, float humidity, float nutrients, float air) + { + return (int) (humidity+nutrients+air); + } + + /** + * Used to determine whether the plant can crossbreed with another crop. + * Default is allow crossbreeding if the size is greater or equal than 3. + * + * @param crop crop to crossbreed with + */ + public boolean canCross(TECrop crop) + { + return crop.size >= 3; + } + + + /** + * Called when the plant is rightclicked by a player. + * Default action is harvesting. + * + * @param crop reference to TECrop + * @param player player rightclicking the crop + * @return Whether the plant has changed + */ + public boolean rightclick(TECrop crop, EntityPlayer player) + { + return crop.harvest(true); + } + + /** + * Check whether the crop can be harvested. + * + * @param crop reference to TECrop + * @return Whether the crop can be harvested in its current state. + */ + public abstract boolean canBeHarvested(TECrop crop); + + /** + * Base chance for dropping the plant's gains, specify values greater than 1 for multiple drops. + * Default is 0.95^tier. + * + * @return Chance to drop the gains + */ + public float dropGainChance() + { + float base = 1F; + for (int i = 0; i < tier(); i++) {base*=0.95;} + return base; + } + + /** + * Item obtained from harvesting the plant. + * + * @param crop reference to TECrop + * @return Item obtained + */ + public abstract ItemStack getGain(TECrop crop); + + /** + * Get the size of the plant after harvesting. + * Default is 1. + * + * @param crop reference to TECrop + * @return Plant size after harvesting + */ + public byte getSizeAfterHarvest(TECrop crop) {return 1;} + + + /** + * Called when the plant is leftclicked by a player. + * Default action is picking the plant. + * + * @param crop reference to TECrop + * @param player player leftclicked the crop + * @return Whether the plant has changed + */ + public boolean leftclick(TECrop crop, EntityPlayer player) + { + return crop.pick(true); + } + + /** + * Base chance for dropping seeds when the plant is picked. + * Default is 0.5*0.8^tier with a bigger chance for sizes greater than 2 and absolutely no chance for size 0. + * + * @param crop reference to TECrop + * @return Chance to drop the seeds + */ + public float dropSeedChance(TECrop crop) + { + if (crop.size == 1) return 0; + float base = 0.5F; + if (crop.size == 2) base/=2F; + for (int i = 0; i < tier(); i++) {base*=0.8;} + return base; + } + + /** + * Obtain seeds dropped when the plant is picked. + * Multiple drops of the returned ItemStack can occur. + * Default action is generating a seed from this crop. + * + * @param crop reference to TECrop + * @return Seeds + */ + public ItemStack getSeeds(TECrop crop) + { + return crop.generateSeeds(crop.id, crop.statGrowth, crop.statGain, crop.statResistance, crop.scanLevel); + } + + /** + * Called when a neighbor block to the crop has changed. + * + * @param crop reference to TECrop + */ + public void onNeighbourChange(TECrop crop){} + + /** + * Check if the crop should emit redstone. + * + * @return Whether the crop should emit redstone + */ + public boolean emitRedstone(TECrop crop){return false;} + + /** + * Called when the crop is destroyed. + * + * @param crop reference to TECrop + */ + public void onBlockDestroyed(TECrop crop){} + + /** + * Get the light value emitted by the plant. + * + * @param crop reference to TECrop + * @return Light value emitted + */ + public int getEmittedLight(TECrop crop) {return 0;} + + /** + * Default is true if the entity is an EntityLiving in jumping or sprinting state. + * + * @param crop reference to TECrop + * @param entity entity colliding + * @return Whether trampling calculation should happen, return false if the plant is no longer valid. + */ + public boolean onEntityCollision(TECrop crop, Entity entity) + { + if (entity instanceof EntityLiving) + { + return ((EntityLiving)entity).isSprinting(); + } + return false; + } + + + /** + * Called every time the crop ticks. + * Should be called every 256 ticks or around 13 seconds. + * + * @param crop reference to TECrop + */ + public void tick(TECrop crop) {} + + /** + * Check whether this plant spreads weed to surrounding tiles. + * Default is true if the plant has a high growth stat (or is weeds) and size greater or equal than 2. + * + * @param crop reference to TECrop + * @return Whether the plant spreads weed + */ + public boolean isWeed(TECrop crop) + { + return crop.size>=2 && (crop.id==0 || crop.statGrowth>=24); + } + + + /** + * Get this plant's ID. + * + * @return ID of this CropCard or -1 if it's not registered + */ + public final int getId() + { + for (int i = 0; i < cropCardList.length; i++) + { + if (this == cropCardList[i]) + { + return i; + } + } + return -1; + } + + private static final CropCard[] cropCardList = new CropCard[256]; + + /** + * Get the size of the plant list. + * + * @return Plant list size + */ + public static int cropCardListLength() {return cropCardList.length;} + + /** + * Return the CropCard assigned to the given ID. + * If the ID is out of bounds, weed should be returned. If the ID is not registered, weed should be returned and a console print will notify. + * + * @param id plant ID + * @return Plant class + */ + public static final CropCard getCrop(int id) + { + if (id < 0 || id >= cropCardList.length) + {// Out of bounds + return cropCardList[0]; + } + if (cropCardList[id]==null) + {// Out of bounds + System.out.println("[IndustrialCraft] Something tried to access non-existant cropID #"+id+"!!!"); + return cropCardList[0]; + } + + return cropCardList[id]; + } + + /** + * Check whether the specified plant ID is already assigned. + * @param id ID to be checked + * @return true if the the given id is inbounds and the registered slot is not null + */ + public static final boolean idExists(int id) + { + return !(id < 0 || id >= cropCardList.length || cropCardList[id]==null); + } + + /** + * Auto-assign an ID to a plant and register it. + * Usage of this method is not recommended! Other plants could take your IDs and cause your plants to turn into other plants. + * + * @param crop plant to register + * @return The ID assigned to the plant + */ + public static final short registerCrop(CropCard crop) + { + for (short x = 0; x < cropCardList.length; x++) + {// Iterate through list + if (cropCardList[x]==null) + {// Found empty slot, add crop here + cropCardList[x]=crop; + nameReference.addLocal("item.cropSeed"+x+".name", crop.name()+" Seeds"); + return x; + } + } + //No free slot avaible + return -1; + } + + /** + * Attempt to register a plant to an ID. + * If the ID is taken, the crop will not be registered and a console print will notify the user. + * + * @param crop plant to register + * @param i ID to register the plant to + * @return Whether the crop was registered + */ + public static final boolean registerCrop(CropCard crop, int i) + { + if (i < 0 || i >= cropCardList.length) + {// Out of bounds + return false; + } + if (cropCardList[i]==null) + { + cropCardList[i]=crop; + nameReference.addLocal("item.cropSeed"+i+".name", crop.name()+" Seeds"); + return true; + } + System.out.println("[IndustrialCraft] Cannot add crop:"+crop.name()+" on ID #"+i+", slot already occupied by crop:"+cropCardList[i].name()); + return false; + } + + /** + * For internal usage only. + */ + public static TECrop nameReference; + + private static HashMap baseseeds = new HashMap(); + + /** + * Registers a base seed, an item used to plant a crop. + * + * @param stack item + * @param id plant ID + * @param size initial size + * @param growth initial growth stat + * @param gain initial gain stat + * @param resistance initial resistance stat + * @return True if successful + */ + public static boolean registerBaseSeed(ItemStack stack, int id, int size, int growth, int gain, int resistance) + { + for (ItemStack key : baseseeds.keySet()) + if (key.itemID==stack.itemID && key.getItemDamage()==stack.getItemDamage()) return false; + + baseseeds.put(stack, new BaseSeed(id, size, growth, gain, resistance, stack.stackSize)); + return true; + } + + /** + * Finds a base seed from the given item. + * + * @return Base seed or null if none found + */ + public static BaseSeed getBaseSeed(ItemStack stack) + { + if (stack == null) return null; + for (ItemStack key : baseseeds.keySet()) + { + if (key.itemID == stack.itemID && + (key.getItemDamage() == -1 || key.getItemDamage() == stack.getItemDamage())) + { + return baseseeds.get(key); + } + } + return null; + } +} diff --git a/src/minecraft/ic2/api/Crops.java b/src/minecraft/ic2/api/Crops.java new file mode 100644 index 000000000..7002d612f --- /dev/null +++ b/src/minecraft/ic2/api/Crops.java @@ -0,0 +1,47 @@ +package ic2.api; + +import java.util.HashMap; + +import net.minecraft.world.biome.BiomeGenBase; + +/** + * General management of the crop system. All crop management methods will be moved here in the 2.00 update. + */ +public class Crops { + private static final HashMap humidityBiomeBonus = new HashMap(); + private static final HashMap nutrientBiomeBonus = new HashMap(); + + /** + * Add a crop humidity and nutrient biome bonus. + * + * 0 indicates no bonus and negative values indicate a penalty. + * + * @param biome Biome to apply the bonus in + * @param humidityBonus Humidity stat bonus + * @param nutrientsBonus Nutrient stat bonus + */ + public static void addBiomeBonus(BiomeGenBase biome, int humidityBonus, int nutrientsBonus) { + humidityBiomeBonus.put(biome, humidityBonus); + nutrientBiomeBonus.put(biome, nutrientsBonus); + } + + /** + * Get the humidity bonus for a biome. + * + * @param biome biome to check + * @return Humidity bonus or 0 if none + */ + public static int getHumidityBiomeBonus(BiomeGenBase biome) { + return humidityBiomeBonus.containsKey(biome) ? humidityBiomeBonus.get(biome) : 0; + } + + /** + * Get the nutrient bonus for a biome. + * + * @param biome biome to check + * @return Nutrient bonus or 0 if none + */ + public static int getNutrientBiomeBonus(BiomeGenBase biome) { + return nutrientBiomeBonus.containsKey(biome) ? nutrientBiomeBonus.get(biome) : 0; + } +} diff --git a/src/minecraft/ic2/api/Direction.java b/src/minecraft/ic2/api/Direction.java new file mode 100644 index 000000000..751375ab7 --- /dev/null +++ b/src/minecraft/ic2/api/Direction.java @@ -0,0 +1,107 @@ +package ic2.api; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +/** + * Represents the 6 possible directions along the axis of a block. + */ +public enum Direction { + /** + * -X + */ + XN(0), + /** + * +X + */ + XP(1), + + /** + * -Y + */ + YN(2), //MC-Code starts with 0 here + /** + * +Y + */ + YP(3), // 1... + + /** + * -Z + */ + ZN(4), + /** + * +Z + */ + ZP(5); + + Direction(int dir) { + this.dir = dir; + } + + /*public CoordinateTuple ApplyToCoordinates(CoordinateTuple coordinates) { + CoordinateTuple ret = new CoordinateTuple(coordinates); + + ret.coords[dir/2] += GetSign(); + + return ret; + }*/ + + /** + * Get the tile entity next to a tile entity following this direction. + * + * @param tileEntity tile entity to check + * @return Adjacent tile entity or null if none exists + */ + public TileEntity applyToTileEntity(TileEntity tileEntity) { + int coords[] = { tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord }; + + coords[dir/2] += getSign(); + + if (tileEntity.worldObj != null && tileEntity.worldObj.blockExists(coords[0], coords[1], coords[2])) { + return tileEntity.worldObj.getBlockTileEntity(coords[0], coords[1], coords[2]); + } else { + return null; + } + } + + /** + * Get the inverse of this direction (XN -> XP, XP -> XN, etc.) + * + * @return Inverse direction + */ + public Direction getInverse() { + int inverseDir = dir - getSign(); + + for (Direction direction : directions) { + if (direction.dir == inverseDir) return direction; + } + + return this; + } + + /** + * Convert this direction to a Minecraft side value. + * + * @return Minecraft side value + */ + public int toSideValue() { + return (dir + 4) % 6; + } + + /** + * Determine direction sign (N for negative or P for positive). + * + * @return -1 if the direction is negative, +1 if the direction is positive + */ + private int getSign() { + return (dir % 2) * 2 - 1; + } + + public ForgeDirection toForgeDirection() { + return ForgeDirection.getOrientation(toSideValue()); + } + + private int dir; + private static final Direction[] directions = Direction.values(); +} + diff --git a/src/minecraft/ic2/api/ElectricItem.java b/src/minecraft/ic2/api/ElectricItem.java new file mode 100644 index 000000000..7d560a7c0 --- /dev/null +++ b/src/minecraft/ic2/api/ElectricItem.java @@ -0,0 +1,128 @@ +package ic2.api; + +import java.lang.reflect.Method; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * Allows for charging, discharging and using electric items (IElectricItem). + * + * The charge or remaining capacity of an item can be determined by calling charge/discharge with + * ignoreTransferLimit and simulate set to true. + */ +public final class ElectricItem { + /** + * Charge an item with a specified amount of energy + * + * @param itemStack electric item's stack + * @param amount amount of energy to charge in EU + * @param tier tier of the charging device, has to be at least as high as the item to charge + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually change the item, just determine the return value + * @return Energy transferred into the electric item + */ + public static int charge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) { + try { + if (ElectricItem_charge == null) ElectricItem_charge = Class.forName(getPackage() + ".core.item.ElectricItem").getMethod("charge", ItemStack.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE, Boolean.TYPE); + + return (Integer) ElectricItem_charge.invoke(null, itemStack, amount, tier, ignoreTransferLimit, simulate); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Discharge an item by a specified amount of energy + * + * @param itemStack electric item's stack + * @param amount amount of energy to charge in EU + * @param tier tier of the discharging device, has to be at least as high as the item to discharge + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually discharge the item, just determine the return value + * @return Energy retrieved from the electric item + */ + public static int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) { + try { + if (ElectricItem_discharge == null) ElectricItem_discharge = Class.forName(getPackage() + ".core.item.ElectricItem").getMethod("discharge", ItemStack.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE, Boolean.TYPE); + + return (Integer) ElectricItem_discharge.invoke(null, itemStack, amount, tier, ignoreTransferLimit, simulate); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Determine if the specified electric item has at least a specific amount of EU. + * This is supposed to be used in the item code during operation, for example if you want to implement your own electric item. + * BatPacks are not taken into account. + * + * @param itemStack electric item's stack + * @param amount minimum amount of energy required + * @return true if there's enough energy + */ + public static boolean canUse(ItemStack itemStack, int amount) { + try { + if (ElectricItem_canUse == null) ElectricItem_canUse = Class.forName(getPackage() + ".core.item.ElectricItem").getMethod("canUse", ItemStack.class, Integer.TYPE); + + return (Boolean) ElectricItem_canUse.invoke(null, itemStack, amount); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Try to retrieve a specific amount of energy from an Item, and if applicable, a BatPack. + * This is supposed to be used in the item code during operation, for example if you want to implement your own electric item. + * + * @param itemStack electric item's stack + * @param amount amount of energy to discharge in EU + * @param player player holding the item + * @return true if the operation succeeded + */ + public static boolean use(ItemStack itemStack, int amount, EntityPlayer player) { + try { + if (ElectricItem_use == null) ElectricItem_use = Class.forName(getPackage() + ".core.item.ElectricItem").getMethod("use", ItemStack.class, Integer.TYPE, EntityPlayer.class); + + return (Boolean) ElectricItem_use.invoke(null, itemStack, amount, player); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Charge an item from the BatPack a player is wearing. + * This is supposed to be used in the item code during operation, for example if you want to implement your own electric item. + * use() already contains this functionality. + * + * @param itemStack electric item's stack + * @param player player holding the item + */ + public static void chargeFromArmor(ItemStack itemStack, EntityPlayer player) { + try { + if (ElectricItem_chargeFromArmor == null) ElectricItem_chargeFromArmor = Class.forName(getPackage() + ".core.item.ElectricItem").getMethod("chargeFromArmor", ItemStack.class, EntityPlayer.class); + + ElectricItem_chargeFromArmor.invoke(null, itemStack, player); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = ElectricItem.class.getPackage(); + if (pkg != null) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else return "ic2"; + } + + private static Method ElectricItem_charge; + private static Method ElectricItem_discharge; + private static Method ElectricItem_canUse; + private static Method ElectricItem_use; + private static Method ElectricItem_chargeFromArmor; +} + diff --git a/src/minecraft/ic2/api/ExplosionWhitelist.java b/src/minecraft/ic2/api/ExplosionWhitelist.java new file mode 100644 index 000000000..2206dcd6e --- /dev/null +++ b/src/minecraft/ic2/api/ExplosionWhitelist.java @@ -0,0 +1,46 @@ +package ic2.api; + +import java.util.*; + +import net.minecraft.block.Block; + +/** + * Blocks on this whitelist will not resist an explosion but won't be destroyed. + * + * The explosion code by default ignores blocks which absorb more than 1000 explosion power to + * prevent abusing personal safes, Trade-O-Mats and other blocks to serve as a cheap and + * invulnerable reactor chambers. Said blocks will not shield the explosion and won't get + * destroyed. + */ +public final class ExplosionWhitelist { + /** + * Add a block to the whitelist. + * + * @param block block to add + */ + public static void addWhitelistedBlock(Block block) { + whitelist.add(block); + } + + /** + * Remove a block from the whitelist. + * + * @param block block to remove + */ + public static void removeWhitelistedBlock(Block block) { + whitelist.remove(block); + } + + /** + * Check if a block is on the whitelist. + * + * @param block block to check if whitelisted + * @return Whether the block is whitelisted + */ + public static boolean isBlockWhitelisted(Block block) { + return whitelist.contains(block); + } + + private static Set whitelist = new HashSet(); +} + diff --git a/src/minecraft/ic2/api/IBoxable.java b/src/minecraft/ic2/api/IBoxable.java new file mode 100644 index 000000000..4b6f12cf1 --- /dev/null +++ b/src/minecraft/ic2/api/IBoxable.java @@ -0,0 +1,18 @@ +package ic2.api; + +import net.minecraft.item.ItemStack; + +/** + * Provides custom toolbox storage behavior for items. + * + * The normal condition for storing an item in a toolbox is having a maximum stack size of 1. + */ +public interface IBoxable { + /** + * Determine whether an item can be stored in a toolbox or not. + * + * @param itemstack item to be stored + * @return Whether to store the item in the toolbox or not + */ + public abstract boolean canBeStoredInToolbox(ItemStack itemstack); +} diff --git a/src/minecraft/ic2/api/IC2Reactor.java b/src/minecraft/ic2/api/IC2Reactor.java new file mode 100644 index 000000000..cacd72500 --- /dev/null +++ b/src/minecraft/ic2/api/IC2Reactor.java @@ -0,0 +1,28 @@ +package ic2.api; + +import java.lang.reflect.Field; + +public class IC2Reactor { + private static Field energyGeneratorNuclear; + + public static int getEUOutput() { + try { + if (energyGeneratorNuclear == null) energyGeneratorNuclear = Class.forName(getPackage() + ".core.IC2").getDeclaredField("energyGeneratorNuclear"); + + return energyGeneratorNuclear.getInt(null); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = IC2Reactor.class.getPackage(); + if (pkg != null) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else return "ic2"; + } +} diff --git a/src/minecraft/ic2/api/ICustomElectricItem.java b/src/minecraft/ic2/api/ICustomElectricItem.java new file mode 100644 index 000000000..bf48b2a04 --- /dev/null +++ b/src/minecraft/ic2/api/ICustomElectricItem.java @@ -0,0 +1,64 @@ +package ic2.api; + +import net.minecraft.item.ItemStack; + +/** + * Provides the ability to store energy on the implementing item. + * + * This interface is a special version of IElectricItem which delegates the implementation of + * charge(), discharge() and canUse() to the implementing Item. + * + * The default implementation (when not using ICustomElectricItem) does the following: + * - store and retrieve the charge + * - handle charging, taking amount, tier, transfer limit and simulate into account + * - replace item IDs if appropriate (getChargedItemId() and getEmptyItemId()) + * - update and manage the damage value for the visual charge indicator + * + * @note ICustomElectricItem must not call the ElectricItem methods charge, discharge or canUse + */ +public interface ICustomElectricItem extends IElectricItem { + /** + * Charge an item with a specified amount of energy + * + * @param itemStack electric item's stack + * @param amount amount of energy to charge in EU + * @param tier tier of the charging device, has to be at least as high as the item to charge + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually change the item, just determine the return value + * @return Energy transferred into the electric item + */ + public int charge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate); + + /** + * Discharge an item by a specified amount of energy + * + * @param itemStack electric item's stack + * @param amount amount of energy to charge in EU + * @param tier tier of the discharging device, has to be at least as high as the item to discharge + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually discharge the item, just determine the return value + * @return Energy retrieved from the electric item + */ + public int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate); + + /** + * Determine if the specified electric item has at least a specific amount of EU. + * This is supposed to be used in the item code during operation, for example if you want to implement your own electric item. + * BatPacks are not taken into account. + * + * @param itemStack electric item's stack + * @param amount minimum amount of energy required + * @return true if there's enough energy + */ + public boolean canUse(ItemStack itemStack, int amount); + + /** + * Determine whether to show the charge tool tip with NEI or other means. + * + * Return false if IC2's handler is incompatible, you want to implement your own or you don't + * want to display the charge at all. + * + * @return true to show the tool tip (x/y EU) + */ + public boolean canShowChargeToolTip(ItemStack itemStack); +} diff --git a/src/minecraft/ic2/api/IElectricItem.java b/src/minecraft/ic2/api/IElectricItem.java new file mode 100644 index 000000000..21142fa85 --- /dev/null +++ b/src/minecraft/ic2/api/IElectricItem.java @@ -0,0 +1,52 @@ +package ic2.api; + +/** + * Provides the ability to store energy on the implementing item. + * + * The item should have a maximum damage of 13. + */ +public interface IElectricItem { + /** + * Determine if the item can be used in a machine or as an armor part to supply energy. + * + * @return Whether the item can supply energy + */ + boolean canProvideEnergy(); + + /** + * Get the item ID to use for a charge energy greater than 0. + * + * @return Item ID to use + */ + int getChargedItemId(); + + /** + * Get the item ID to use for a charge energy of 0. + * + * @return Item ID to use + */ + int getEmptyItemId(); + + /** + * Get the item's maximum charge energy in EU. + * + * @return Maximum charge energy + */ + int getMaxCharge(); + + /** + * Get the item's tier, lower tiers can't send energy to higher ones. + * Batteries are Tier 1, Energy Crystals are Tier 2, Lapotron Crystals are Tier 3. + * + * @return Item's tier + */ + int getTier(); + + /** + * Get the item's transfer limit in EU per transfer operation. + * + * @return Transfer limit + */ + int getTransferLimit(); +} + diff --git a/src/minecraft/ic2/api/IEnergyStorage.java b/src/minecraft/ic2/api/IEnergyStorage.java new file mode 100644 index 000000000..fc275f733 --- /dev/null +++ b/src/minecraft/ic2/api/IEnergyStorage.java @@ -0,0 +1,52 @@ +package ic2.api; + +/** + * Interface implemented by the tile entity of energy storage blocks. + */ +public interface IEnergyStorage { + /** + * Get the amount of energy currently stored in the block. + * + * @return Energy stored in the block + */ + public int getStored(); + + /** + * Set the amount of energy currently stored in the block. + * + * @param energy stored energy + */ + public void setStored(int energy); + + /** + * Add the specified amount of energy. + * + * Use negative values to decrease. + * + * @param amount of energy to add + * @return Energy stored in the block after adding the specified amount + */ + public int addEnergy(int amount); + + /** + * Get the maximum amount of energy the block can store. + * + * @return Maximum energy stored + */ + public int getCapacity(); + + /** + * Get the block's energy output. + * + * @return Energy output in EU/t + */ + public int getOutput(); + + /** + * Get whether this block can have its energy used by an adjacent teleporter. + * + * @param side side the teleporter is draining energy from + * @return Whether the block is teleporter compatible + */ + public boolean isTeleporterCompatible(Direction side); +} diff --git a/src/minecraft/ic2/api/IMetalArmor.java b/src/minecraft/ic2/api/IMetalArmor.java new file mode 100644 index 000000000..3b5112b27 --- /dev/null +++ b/src/minecraft/ic2/api/IMetalArmor.java @@ -0,0 +1,20 @@ +package ic2.api; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * Armor items implementing this can be considered metal armor. + * + * Currently used for determining which boots can be used to slide up a magnetic pole. + */ +public interface IMetalArmor { + /** + * Determine if the given armor piece is metal armor. + * + * @param itemstack Armor piece as worn by the player + * @param player The player + * @return Whether the armor piece is metal armor + */ + public boolean isMetalArmor(ItemStack itemstack, EntityPlayer player); +} diff --git a/src/minecraft/ic2/api/IPaintableBlock.java b/src/minecraft/ic2/api/IPaintableBlock.java new file mode 100644 index 000000000..6ba19d39f --- /dev/null +++ b/src/minecraft/ic2/api/IPaintableBlock.java @@ -0,0 +1,21 @@ +package ic2.api; + +import net.minecraft.world.World; + +/** + * Allows a block to be painted by a Painter. + */ +public interface IPaintableBlock +{ + /** + * Color the block. + * + * @param world block's world + * @param x block X position + * @param y block Y position + * @param z block Z position + * @param color painter color, same as dye metadata values + * @return Whether the block was painted and the painter should be damaged + */ + public boolean colorBlock(World world, int x, int y, int z, int color); +} diff --git a/src/minecraft/ic2/api/IReactor.java b/src/minecraft/ic2/api/IReactor.java new file mode 100644 index 000000000..56d402d32 --- /dev/null +++ b/src/minecraft/ic2/api/IReactor.java @@ -0,0 +1,134 @@ +package ic2.api; + +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +/** + * Interface implemented by the tile entity of nuclear reactors. + */ +public interface IReactor { + /** + * Get the reactor's position in the world. + * + * @return Position of the reactor + */ + public ChunkCoordinates getPosition(); + + /** + * Get the reactor's corresponding world. + * + * @return The reactor's world + */ + public World getWorld(); + + /** + * Get the reactor's heat. + * + * @return The reactor's heat + */ + public int getHeat(); + + /** + * Set the reactor's heat. + * + * @param heat reactor heat + */ + public void setHeat(int heat); + + /** + * Increase the reactor's heat. + * + * Use negative values to decrease. + * + * @param amount amount of heat to add + * @return The reactor's heat after adding the specified amount + */ + public int addHeat(int amount); + + /** + * Get the reactor's maximum heat before exploding. + * + * @return Maximum heat value + */ + public int getMaxHeat(); + + /** + * Set the reactor's stored maxHeat variable. + * Used by plating to increase the reactors MaxHeat capacity. + * Needs to be called during each cycle process. + */ + public void setMaxHeat(int newMaxHeat); + + /** + * Get's the reactor's HEM (Heat Effect Modifier) + * Basic value is 1.0F. + * Reducing the value causes a weakening/reduction of the heat-based sideeffects of reactors + * (F.e. water evaporation, melting, damaging entitys, etc) + * + * @return HEM + */ + public float getHeatEffectModifier(); + + /** + * Set's the reactor's HEM + * Needs to be called during each cycle process. + */ + public void setHeatEffectModifier(float newHEM); + + /** + * Get the reactor's energy output. + * + * @return Energy output, not multiplied by the base EU/t value + */ + public int getOutput(); + + /** + * Add's the given amount of energy to the Reactor's output. + * + * @return Energy output after adding the value, not multiplied by the base EU/t value + */ + public int addOutput(int energy); + + /** + * Replaced by IC2Reactor.getEUOutput() - stays at the universal output value of 1 for compatibility + */ + @Deprecated + public int getPulsePower(); + + /** + * Get the item at the specified grid coordinates. + * + * @param x X position of the item + * @param y Y position of the item + * @return The item or null if there is no item + */ + public ItemStack getItemAt(int x, int y); + + /** + * Set the item at the specified grid coordinates. + * + * @param x X position of the item + * @param y Y position of the item + * @param item The item to set. + */ + public void setItemAt(int x, int y, ItemStack item); + + /** + * Explode the reactor. + */ + public void explode(); + + /** + * Get the reactor's tick rate (game ticks per reactor tick). + * + * @return Tick rate + */ + public int getTickRate(); + + /** + * Get whether the reactor is active and supposed to produce energy + * @return Whether the reactor is active + */ + public boolean produceEnergy(); +} diff --git a/src/minecraft/ic2/api/IReactorChamber.java b/src/minecraft/ic2/api/IReactorChamber.java new file mode 100644 index 000000000..fad40c275 --- /dev/null +++ b/src/minecraft/ic2/api/IReactorChamber.java @@ -0,0 +1,13 @@ +package ic2.api; + +/** + * Interface implemented by the reactor chamber tile entity. + */ +public interface IReactorChamber { + /** + * Get the chamber's reactor. + * + * @return The reactor + */ + public IReactor getReactor(); +} diff --git a/src/minecraft/ic2/api/IReactorComponent.java b/src/minecraft/ic2/api/IReactorComponent.java new file mode 100644 index 000000000..4a7135e8f --- /dev/null +++ b/src/minecraft/ic2/api/IReactorComponent.java @@ -0,0 +1,97 @@ +package ic2.api; + +import net.minecraft.item.ItemStack; + +/** + * Design custom Reactor components by implementing this Interface + * Items implementing the interface will not be ejected from Reactors in their clean-up + * and can/will be interacted with by other elements, f.e. Uranium Cells. + * + * All IC2 ReactorComponents implement and use this Interface + * + */ +public interface IReactorComponent +{ + /** + * Called by reactor upon iterating through it's inventory (every cycle). + * Perform all necessary calculation/interaction here + * + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @param x X-coordinate of the stack in the grid + * @param y Y-coordinate of the stack in the grid + */ + public void processChamber(IReactor reactor, ItemStack yourStack, int x, int y); + + /** + * Can be called by Uranium-Components who attempt to generate energy by pulsing to other components. + * Uranium-Uranium interaction (f.e.) uses this method. + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of called ItemStack + * @param pulsingStack Reference to the specific instance of pulsing ItemStack + * @param youX X-coordinate of your stack in the grid + * @param youY Y-coordinate of your stack in the grid + * @param pulseX X-coordinate of pulsing stack in the grid + * @param pulseY Y-coordinate of pulsing stack in the grid + * @return true if this component reacts to the pulse (and pulse is therefore meant to produce heat) + */ + public boolean acceptUraniumPulse(IReactor reactor, ItemStack yourStack, ItemStack pulsingStack, int youX, int youY, int pulseX, int pulseY); + + /** + * Called by components to determine whether your component can be heated. + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @param x X-coordinate of the stack in the grid + * @param y Y-coordinate of the stack in the grid + * @return true if your component can take heat + */ + public boolean canStoreHeat(IReactor reactor, ItemStack yourStack, int x, int y); + + /** + * Called by heat-switches to determine how much heat to distribute into which direction. + * Please return the maximum capacity of your heat-containing component here. + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @param x X-coordinate of the stack in the grid + * @param y Y-coordinate of the stack in the grid + * @return Maximum heat + */ + public int getMaxHeat(IReactor reactor, ItemStack yourStack, int x, int y); + + /** + * Called by heat-switches to determine how much heat to distribute into which direction. + * Please return the current amount of heat stored in this component + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @param x X-coordinate of the stack in the grid + * @param y Y-coordinate of the stack in the grid + * @return Current Heat + */ + public int getCurrentHeat(IReactor reactor, ItemStack yourStack, int x, int y); + + /** + * Called by components to distribute heat to your component. + * Perform heating-calculations and increase your heat (dmg) level accordingly. + * This method will as well be called to REDUCE heat, by providing a negative amount. + * + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @param x X-coordinate of the stack in the grid + * @param y Y-coordinate of the stack in the grid + * @param heat Amount of heat to be added (may be negative to subtract heat) + * @return 0 if the 'order' was accepted, return >0 to indicate the 'remaining' heat which couldn't be absorbed (and vice versa for <0) + */ + public int alterHeat(IReactor reactor, ItemStack yourStack, int x, int y, int heat); + + /** + * Called upon reactor explosion + * Alter the explosion size. + * Returning a float 0 < f < 1 will be counted as multiplier. + * Anything else will be counted as a flat addition (in case of <0 = reduction). + * + * @param reactor Reference to the Reactor + * @param yourStack Reference to the specific instance of iterated ItemStack + * @return your explosion modifier + */ + public float influenceExplosion(IReactor reactor, ItemStack yourStack); +} diff --git a/src/minecraft/ic2/api/ITerraformingBP.java b/src/minecraft/ic2/api/ITerraformingBP.java new file mode 100644 index 000000000..378164a60 --- /dev/null +++ b/src/minecraft/ic2/api/ITerraformingBP.java @@ -0,0 +1,35 @@ +package ic2.api; + +import net.minecraft.world.World; + +/** + * Allows an item to act as a terraformer blueprint. + */ +public interface ITerraformingBP +{ + /** + * Get the energy consumption per operation of the blueprint. + * + * @return Energy consumption in EU + */ + public abstract int getConsume(); + + /** + * Get the maximum range of the blueprint. + * Should be a divisor of 5. + * + * @return Maximum range in blocks + */ + public abstract int getRange(); + + /** + * Perform the terraforming operation. + * + * @param world world to terraform + * @param x X position to terraform + * @param z Z position to terraform + * @param yCoord Y position of the terraformer + * @return Whether the operation was successful and the terraformer should consume energy. + */ + public abstract boolean terraform(World world, int x, int z, int yCoord); +} diff --git a/src/minecraft/ic2/api/IWrenchable.java b/src/minecraft/ic2/api/IWrenchable.java new file mode 100644 index 000000000..7357423a1 --- /dev/null +++ b/src/minecraft/ic2/api/IWrenchable.java @@ -0,0 +1,59 @@ +package ic2.api; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * Allows a tile entity to make use of the wrench's removal and rotation functions. + */ +public interface IWrenchable { + /** + * Determine if the wrench can be used to set the block's facing. + * Called before wrenchCanRemove(). + * + * @param entityPlayer player using the wrench + * @param side block's side the wrench was clicked on + * @return Whether the wrenching was done and the wrench should be damaged + */ + boolean wrenchCanSetFacing(EntityPlayer entityPlayer, int side); + + /** + * Get the block's facing. + * + * @return Block facing + */ + short getFacing(); + + /** + * Set the block's facing + * + * @param facing facing to set the block to + */ + void setFacing(short facing); + + /** + * Determine if the wrench can be used to remove the block. + * Called if wrenchSetFacing fails. + * + * @param entityPlayer player using the wrench + * @return Whether the wrenching was done and the wrench should be damaged + */ + boolean wrenchCanRemove(EntityPlayer entityPlayer); + + /** + * Determine the probability to drop the block as it is. + * The first entry in getBlockDropped will be replaced by blockid:meta if the drop is successful. + * + * @return Probability from 0 to 1 + */ + float getWrenchDropRate(); + + /** + * Determine the item the block will drop when the wrenching is successful. + * + * @param entityPlayer player using the wrench + * @return Item to drop + */ + ItemStack getWrenchDrop(EntityPlayer entityPlayer); +} + diff --git a/src/minecraft/ic2/api/Ic2Recipes.java b/src/minecraft/ic2/api/Ic2Recipes.java new file mode 100644 index 000000000..31ac16bcb --- /dev/null +++ b/src/minecraft/ic2/api/Ic2Recipes.java @@ -0,0 +1,358 @@ +package ic2.api; + +import java.lang.reflect.Array; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +/** + * Provides access to Compressor, Extractor and Macerator recipes, as well as charge-aware recipes + * and the Recycler blacklist. + * + * The recipes are only valid after IC2 has been loaded and are metadata and stack size sensitive, + * for example you can create a recipe to compress 3 wooden planks into 2 sticks. + */ +public final class Ic2Recipes { + /** + * Add a charge-aware shaped crafting recipe. + */ + public static void addCraftingRecipe(ItemStack result, Object... args) { + try { + Class.forName(getPackage() + ".core.AdvRecipe").getMethod("addAndRegister", ItemStack.class, Array.newInstance(Object.class, 0).getClass()).invoke(null, result, args); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Add a charge-aware shapeless crafting recipe. + */ + public static void addShapelessCraftingRecipe(ItemStack result, Object... args) { + try { + Class.forName(getPackage() + ".core.AdvShapelessRecipe").getMethod("addAndRegister", ItemStack.class, Array.newInstance(Object.class, 0).getClass()).invoke(null, result, args); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Retrieve the registered Compressor recipes. + * + * @return Recipe list as a list of map entries, the key is the input and the value is the output + */ + public static List > getCompressorRecipes() { + if (TileEntityCompressor_recipes == null) { + try { + TileEntityCompressor_recipes = (List >) Class.forName(getPackage() + ".core.block.machine.tileentity.TileEntityCompressor").getField("recipes").get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return TileEntityCompressor_recipes; + } + + /** + * Add a Compressor recipe. + * + * @param input Input + * @param output Output + */ + public static void addCompressorRecipe(ItemStack input, ItemStack output) { + getCompressorRecipes().add(new AbstractMap.SimpleEntry(input, output)); + } + + + /** + * Get the Compressor output for an input item. + * + * @param input input item + * @param adjustInput remove the processing requirements from input + * @return Output item as an independent stack + */ + public static ItemStack getCompressorOutputFor(ItemStack input, boolean adjustInput) { + return getOutputFor(input, adjustInput, getCompressorRecipes()); + } + + /** + * Retrieve the registered Extractor recipes. + * + * @return Recipe list as a list of map entries, the key is the input and the value is the output + */ + public static List > getExtractorRecipes() { + if (TileEntityExtractor_recipes == null) { + try { + TileEntityExtractor_recipes = (List >) Class.forName(getPackage() + ".core.block.machine.tileentity.TileEntityExtractor").getField("recipes").get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return TileEntityExtractor_recipes; + } + + /** + * Add a Extractor recipe. + * + * @param input Input + * @param output Output + */ + public static void addExtractorRecipe(ItemStack input, ItemStack output) { + getExtractorRecipes().add(new AbstractMap.SimpleEntry(input, output)); + } + + + /** + * Get the Extractor output for an input item. + * + * @param input input item + * @param adjustInput remove the processing requirements from input + * @return Output item as an independent stack + */ + public static ItemStack getExtractorOutputFor(ItemStack input, boolean adjustInput) { + return getOutputFor(input, adjustInput, getExtractorRecipes()); + } + + /** + * Retrieve the registered Macerator recipes. + * + * @return Recipe list as a list of map entries, the key is the input and the value is the output + */ + public static List > getMaceratorRecipes() { + if (TileEntityMacerator_recipes == null) { + try { + TileEntityMacerator_recipes = (List >) Class.forName(getPackage() + ".core.block.machine.tileentity.TileEntityMacerator").getField("recipes").get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return TileEntityMacerator_recipes; + } + + /** + * Add a Macerator recipe. + * + * @param input Input + * @param output Output + */ + public static void addMaceratorRecipe(ItemStack input, ItemStack output) { + getMaceratorRecipes().add(new AbstractMap.SimpleEntry(input, output)); + } + + + /** + * Get the Macerator output for an input item. + * + * @param input input item + * @param adjustInput remove the processing requirements from input + * @return Output item as an independent stack + */ + public static ItemStack getMaceratorOutputFor(ItemStack input, boolean adjustInput) { + return getOutputFor(input, adjustInput, getMaceratorRecipes()); + } + + + private static ItemStack getOutputFor(ItemStack input, boolean adjustInput, List > recipeList) { + assert input != null; + + for (Map.Entry entry: recipeList) { + if (entry.getKey().isItemEqual(input) && input.stackSize >= entry.getKey().stackSize) { + if (adjustInput) input.stackSize -= entry.getKey().stackSize; + + return entry.getValue().copy(); + } + } + + return null; + } + + + /** + * Retrieve the registered Recycler blacklist items. + * + * @return Blacklist + */ + public static List getRecyclerBlacklist() { + if (TileEntityRecycler_blacklist == null) { + try { + TileEntityRecycler_blacklist = (List) Class.forName(getPackage() + ".core.block.machine.tileentity.TileEntityRecycler").getField("blacklist").get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return TileEntityRecycler_blacklist; + } + + /** + * Add an item stack to the Recycler blacklist. + * + * @param newBlacklistedItem item stack to add + */ + public static void addRecyclerBlacklistItem(ItemStack newBlacklistedItem) { + getRecyclerBlacklist().add(newBlacklistedItem); + } + + /** + * Add an item to the Recycler blacklist. + * + * @param newBlacklistedItem item to add + */ + public static void addRecyclerBlacklistItem(Item newBlacklistedItem) { + addRecyclerBlacklistItem(new ItemStack(newBlacklistedItem, 1, -1)); + } + + /** + * Add a block to the Recycler blacklist. + * + * @param newBlacklistedBlock block to add + */ + public static void addRecyclerBlacklistItem(Block newBlacklistedBlock) { + addRecyclerBlacklistItem(new ItemStack(newBlacklistedBlock, 1, -1)); + } + + + /** + * Determine if an item is in the Recycler blacklist. + * + * @param itemStack item to check + * @return Whether the item is blacklisted or not + */ + public static boolean isRecyclerInputBlacklisted(ItemStack itemStack) { + for (ItemStack blackItem: getRecyclerBlacklist()) { + if (itemStack.isItemEqual(blackItem)) return true; + } + + return false; + } + + /** + * Retrieve the registered Scrap Box drops. + * + * @return Drops as a list of item stack and float (chance) pairs + */ + public static List> getScrapboxDrops() { + try { + return (List>) Class.forName(getPackage() + ".core.item.ItemScrapbox").getMethod("getDropList").invoke(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* + * Reference scrap box chance values: + * + * 0.1: Diamond + * 0.5: Cake, Gold Helmet, Iron Ore, Gold Ore + * 1.0: Wooden tools, Soul Sand, Sign, Leather, Feather, Bone + * 1.5: Apple, Bread + * 2.0: Netherrack, Rotten Flesh + * 3.0: Grass, Gravel + * 4.0: Stick + * 5.0: Dirt, Wooden Hoe + */ + + /** + * Add an item stack to the Scrap Box drops. + * + * @param dropItem item stack to add + * @param chance chance for the item to drop, see the code comments for reference values + */ + public static void addScrapboxDrop(ItemStack dropItem, float chance) { + try { + Class.forName(getPackage() + ".core.item.ItemScrapbox").getMethod("addDrop", ItemStack.class, float.class).invoke(null, dropItem, chance); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Add an item to the Scrap Box drops. + * + * @param dropItem item to add + * @param chance chance for the item to drop, see the code comments for reference values + */ + public static void addScrapboxDrop(Item dropItem, float chance) { + addScrapboxDrop(new ItemStack(dropItem, 1), chance); + } + + /** + * Add a block to the Scrap Box drops. + * + * @param dropItem item to add + * @param chance chance for the item to drop, see the code comments for reference values + */ + public static void addScrapboxDrop(Block dropItem, float chance) { + addScrapboxDrop(new ItemStack(dropItem), chance); + } + + /** + * Retrieve the registered Mass Fabricator amplifiers. + * + * @return Amplifiers as a list of item stack and integer (amplifier value) pairs + */ + public static List > getMatterAmplifiers() { + if (TileEntityMatter_amplifiers == null) { + try { + TileEntityMatter_amplifiers = (List >) Class.forName(getPackage() + ".core.block.machine.tileentity.TileEntityMatter").getField("amplifiers").get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return TileEntityMatter_amplifiers; + } + + /** + * Add an item stack to the Mass Fabricator amplifiers. + * + * @param amplifierItem item stack to add + * @param value amplifier value for the item, scrap is 5000 + */ + public static void addMatterAmplifier(ItemStack amplifierItem, int value) { + getMatterAmplifiers().add(new AbstractMap.SimpleEntry(amplifierItem, value)); + } + + /** + * Add an item to the Mass Fabricator amplifiers. + * + * @param amplifierItem item to add + * @param value amplifier value for the item, scrap is 5000 + */ + public static void addMatterAmplifier(Item amplifierItem, int value) { + addMatterAmplifier(new ItemStack(amplifierItem, 1, -1), value); + } + + /** + * Add a block to the Mass Fabricator amplifiers. + * + * @param amplifierItem item to add + * @param value amplifier value for the item, scrap is 5000 + */ + public static void addMatterAmplifier(Block amplifierItem, int value) { + addMatterAmplifier(new ItemStack(amplifierItem, 1, -1), value); + } + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = Ic2Recipes.class.getPackage(); + if (pkg != null) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else return "ic2"; + } + + private static List > TileEntityCompressor_recipes; + private static List > TileEntityExtractor_recipes; + private static List > TileEntityMacerator_recipes; + private static List TileEntityRecycler_blacklist; + private static List > TileEntityMatter_amplifiers; +} + diff --git a/src/minecraft/ic2/api/Items.java b/src/minecraft/ic2/api/Items.java new file mode 100644 index 000000000..0579f3150 --- /dev/null +++ b/src/minecraft/ic2/api/Items.java @@ -0,0 +1,401 @@ +package ic2.api; + +import net.minecraft.item.ItemStack; + +/** + * Provides access to IC2 blocks and items. + * + * Some items can be acquired through the ore dictionary which is the recommended way. + * The items are initialized while IC2 is being loaded - try to use ModsLoaded() or load your mod after IC2. + * Some blocks/items can be disabled by a config setting, so it's recommended to check if they're null first. + * + * Getting the associated Block/Item for an ItemStack x: + * Blocks: Block.blocksList[x.itemID] + * Items: x.getItem() + */ +public final class Items { + /** + * Get an ItemStack for a specific item name, example: Items.getItem("resin") + * See the list below for item names. + * Make sure to copy() the ItemStack if you want to modify it. + * + * @param name item name + * @return The item or null if the item does not exist or an error occurred + */ + public static ItemStack getItem(String name) { + try { + if (Ic2Items == null) Ic2Items = Class.forName(getPackage() + ".core.Ic2Items"); + + Object ret = Ic2Items.getField(name).get(null); + + if (ret instanceof ItemStack) { + return (ItemStack) ret; + } else { + return null; + } + } catch (Exception e) { + System.out.println("IC2 API: Call getItem failed for "+name); + + return null; + } + } + + /* Possible values: + + ----- blocks ----- + + ores + copperOre Copper Ore block, currently not meta sensitive, meta in ItemStack set to 0, ore dictionary: oreCopper, null with enableWorldGenOreCopper=false + tinOre Tin Ore block, currently not meta sensitive, meta in ItemStack set to 0, ore dictionary: oreTin, null with enableWorldGenOreTin=false + uraniumOre Tin Ore block, currently not meta sensitive, meta in ItemStack set to 0, ore dictionary: oreUranium, null with enableWorldGenOreUranium=false + + rubber related + Rubber wood block, meta reflects the state, meta in ItemStack set to 0, ore dictionary: woodRubber (with meta 0), null with enableWorldGenTreeRubber=false + dropped (as an item) -> metadata 0 + block, no resin spot -> metadata 0 or 1 + block, wet resin spot -> metadata 2-5 (according to the side) + block, dry resin spot -> metadata 8-11 (wet state + 6) + + rubberWood + rubberLeaves Rubber Leaves block, currently not meta sensitive, meta in ItemStack set to 0, null with enableWorldGenTreeRubber=false + rubberSapling Rubber Sapling block, currently not meta sensitive, meta in ItemStack set to 0, null with enableWorldGenTreeRubber=false + resinSheet Resin Sheet block, currently not meta sensitive + rubberTrampoline Rubber Trampoline block, meta reflects internal state, meta in ItemStack set to 0 + + building/storage + ironFence Iron Fence block, currently not meta sensitive + + reinforcedStone Reinforced Stone block, currently not meta sensitive + reinforcedGlass Reinforced Glass block, currently not meta sensitive + reinforcedDoorBlock Reinforced Door block, meta reflects the state (see vanilla doors), meta in ItemStack set to 0 + + constructionFoam Construction Foam block, currently not meta sensitive + constructionFoamWall Construction Foam Wall block, meta = color, implements IPaintableBlock + scaffold Scaffold block, meta reflects internal physical model data + + bronzeBlock Bronze block, meta sensitive + copperBlock Copper block, meta sensitive + tinBlock Tin block, meta sensitive + uraniumBlock Uranium block, meta sensitive + + cables (when placed as a block, inventory items are different TE implements IEnergyConductor) + copperCableBlock Copper Cable block, meta sensitive + insulatedCopperCableBlock Insulated Copper Cable block, meta sensitive + + goldCableBlock Gold Cable block, meta sensitive + insulatedGoldCableBlock Insulated Gold Cable block, meta sensitive + doubleInsulatedGoldCableBlock Double Insulated Gold Cable block, meta sensitive + + ironCableBlock Iron Cable block, meta sensitive + insulatedIronCableBlock Insulated Iron Cable block, meta sensitive + doubleInsulatedIronCableBlock Double Insulated Iron Cable block, meta sensitive + trippleInsulatedIronCableBlock Tripple Insulated Iron Cable block, meta sensitive + + glassFiberCableBlock Glass Fiber Cable block, meta sensitive + + tinCableBlock Tin Cable block, meta sensitive + + detectorCableBlock Detector Cable block, meta sensitive + splitterCableBlock Splitter Cable block, meta sensitive + + generators + related (TE implements IEnergySource ex. reactorChamber) + generator Generator block, meta sensitive + geothermalGenerator Geothermal Generator block, meta sensitive + waterMill Water Mill block, meta sensitive + solarPanel Solar Panel block, meta sensitive + windMill Wind Mill block, meta sensitive + nuclearReactor Nuclear Reactor block, meta sensitive + reactorChamber Reactor Chamber block, currently not meta sensitive + + energy storages (TE implements IEnergySource and IEnergyConductor) + batBox BatBox block, meta sensitive + mfeUnit MFE Unit block, meta sensitive + mfsUnit MFS Unit block, meta sensitive + + transformers (TE implements IEnergySource and IEnergyConductor) + lvTransformer LV Transformer block, meta sensitive + mvTransformer MV Transformer block, meta sensitive + hvTransformer HV Transformer block, meta sensitive + + machines + related (TE implements IEnergySink ex. machine, miningPipe, miningPipeTip) + machine Machine block, meta sensitive + advancedMachine Advanced Machine block, meta sensitive + + ironFurnace Iron Furnace block, meta sensitive + electroFurnace Electro Furnace block, meta sensitive + macerator Macerator block, meta sensitive + extractor Extractor block, meta sensitive + compressor Compressor block, meta sensitive + canner Canner block, meta sensitive + miner Miner block, meta sensitive + pump Pump block, meta sensitive + magnetizer Magnetizer block, meta sensitive + electrolyzer Electrolyzer block, meta sensitive + recycler Recycler block, meta sensitive + inductionFurnace Induction Furnace block, meta sensitive + massFabricator Mass Fabricator block, meta sensitive + terraformer Terraformer block, meta sensitive + teleporter Teleporter block, meta sensitive + teslaCoil Tesla Coil block, meta sensitive + luminator Passive (dark) Luminator block, meta = facing + activeLuminator Active (bright) Luminator block, meta = facing + + miningPipe Mining Pipe block, currently not meta sensitive, meta in ItemStack set to 0 + miningPipeTip Mining Pipe Tip block, currently not meta sensitive, meta in ItemStack set to 0 + + personal blocks + personalSafe Personal Safe block, meta sensitive + tradeOMat Trade-O-Mat block, meta sensitive + energyOMat Energy-O-Mat block, meta sensitive + + explosives + industrialTnt Industrial TNT block, currently not meta sensitive + nuke Nuke block, currently not meta sensitive + dynamiteStick Dynamite Stick block, meta = placement, meta in ItemStack set to 0 + dynamiteStickWithRemote Dynamite Stick with Remote block, meta = placement, meta in ItemStack set to 0 + + Agriculture Stuff + crop Crop Block, empty, not meta sensitive + + + ----- items ----- + + rubber + related + resin Resin item, currently not meta sensitive + rubber Rubber item, currently not meta sensitive, ore dictionary: itemRubber + + ore drops + uraniumDrop Uranium Drop item, currently not meta sensitive, ore dictionary: itemDropUranium + + dusts + bronzeDust Bronze Dust item, currently not meta sensitive + clayDust Clay Dust item, currently not meta sensitive + coalDust Coal Dust item, currently not meta sensitive + copperDust Copper Dust item, currently not meta sensitive + goldDust Gold Dust item, currently not meta sensitive + ironDust Iron Dust item, currently not meta sensitive + silverDust Silver Dust item, currently not meta sensitive + smallIronDust Small Iron Dust item, currently not meta sensitive + tinDust Tin Dust item, currently not meta sensitive + hydratedCoalDust Hydrated Coal Dust item, currently not meta sensitive + + ingots + refinedIronIngot Refined Iron Ingot item, currently not meta sensitive, ore dictionary: ingotRefinedIron + copperIngot Copper Ingot item, currently not meta sensitive, ore dictionary: ingotCopper + tinIngot Tin Ingot item, currently not meta sensitive, ore dictionary: ingotTin + bronzeIngot Bronze Ingot item, currently not meta sensitive, ore dictionary: ingotBronze + mixedMetalIngot Mixed Metal Ingot item, currently not meta sensitive + uraniumIngot Uranium Ingot item, currently not meta sensitive, ore dictionary: ingotUranium + + tools/weapons (without electric tools) + treetap Treetap item, meta = damage value + wrench Wrench item, meta = damage value + cutter Insulation Cutter item, meta = damage value + constructionFoamSprayer Construction Foam Sprayer item, meta = charges (as of v1.45) + + bronzePickaxe Bronze Pickaxe item, meta = damage value + bronzeAxe Bronze Axe item, meta = damage value + bronzeSword Bronze Sword item, meta = damage value + bronzeShovel Bronze Shovel item, meta = damage value + bronzeHoe Bronze Hoe item, meta = damage value + + el. tools/devices/weapons + miningDrill Mining Drill item, meta = visual charge indicator, implements IElectricItem + diamondDrill Diamond Tipped Mining Drill item, meta = visual charge indicator, implements IElectricItem + chainsaw Chainsaw item, meta = visual charge indicator, implements IElectricItem + electricWrench Electric Wrench item, meta = visual charge indicator, implements IElectricItem + electricTreetap Electric Treetap item, meta = visual charge indicator, implements IElectricItem + miningLaser Mining Laser item, meta = visual charge indicator, implements IElectricItem + + ecMeter EC-Mater item, currently not meta sensitive + odScanner Ore Density Scanner item, meta = damage value for charge level, implements IElectricItem + ovScanner Ore Value Scanner item, meta = visual charge indicator, implements IElectricItem + + frequencyTransmitter Frequency Transmitter item, currently not meta sensitive + + nanoSaber Idle Nano Saber item, meta = visual charge indicator, implements IElectricItem + enabledNanoSaber Enabled Nano Saber item, meta = visual charge indicator, implements IElectricItem + + armor/wearable + rubberBoots Rubber Boots item, meta = damage value + + bronzeHelmet Bronze Helmet Armor item, meta = damage value + bronzeChestplate Bronze Chestplate Armor item, meta = damage value + bronzeLeggings Bronze Leggings Armor item, meta = damage value + bronzeBoots Bronze Boots Armor item, meta = damage value + + compositeArmor Composite Armor item, meta = damage value for charge level + + nanoHelmet Nano Helmet Armor item, meta = visual charge indicator, implements IElectricItem + nanoBodyarmor Nano Bodyarmor item, meta = visual charge indicator, implements IElectricItem + nanoLeggings Nano Leggings Armor item, meta = visual charge indicator, implements IElectricItem + nanoBoots Nano Boots Armor item, meta = visual charge indicator, implements IElectricItem + + quantumHelmet Quantum Helmet Armor item, meta = visual charge indicator, implements IElectricItem + quantumBodyarmor Quantum Bodyarmor item, meta = visual charge indicator, implements IElectricItem + quantumLeggings Quantum Leggings Armor item, meta = visual charge indicator, implements IElectricItem + quantumBoots Quantum Boots Armor item, meta = visual charge indicator, implements IElectricItem + + jetpack Jetpack item, meta = damage value for fuel level + electricJetpack Electric Jetpack item, meta = visual charge indicator, implements IElectricItem + + batPack BatPack item, meta = visual charge indicator, implements IElectricItem, can provide energy + lapPack LapPack item, meta = visual charge indicator, implements IElectricItem, can provide energy + + cfPack CF Pack item, meta = charges (as of v1.45) + + solarHelmet Solar Helmet item, currently not meta sensitive + staticBoots Static Boots item, currently not meta sensitive + + batteries + reBattery Empty RE Battery item, currently not meta sensitive, implements IElectricItem + chargedReBattery RE Battery item, meta = visual charge indicator, implements IElectricItem, can provide energy + energyCrystal Energy Crystal item, meta = visual charge indicator, implements IElectricItem, can provide energy + lapotronCrystal Lapotron Crystal item, meta = visual charge indicator, implements IElectricItem, can provide energy + suBattery SU Battery item, currently not meta sensitive + + cables + copperCableItem Copper Cable item, meta sensitive + insulatedCopperCableItem Insulated Copper Cable item, meta sensitive + + goldCableItem Gold Cable item, meta sensitive + insulatedGoldCableItem Insulated Gold Cable item, meta sensitive + doubleInsulatedGoldCableItem Double Insulated Gold Cable item, meta sensitive + + ironCableItem Iron Cable item, meta sensitive + insulatedIronCableItem Insulated Iron Cable item, meta sensitive + doubleInsulatedIronCableItem Double Insulated Iron Cable item, meta sensitive + trippleInsulatedIronCableItem Tripple Insulated Iron Cable item, meta sensitive + + glassFiberCableItem Glass Fiber Cable item, meta sensitive + + tinCableItem Tin Cable item, meta sensitive + + detectorCableItem Detector Cable item, meta sensitive + splitterCableItem Splitter Cable item, meta sensitive + + cells/containers (without reactor components) + cell Empty Cell item, currently not meta sensitive + lavaCell Lava Cell item, currently not meta sensitive + hydratedCoalCell Hydrated Coal Cell item, currently not meta sensitive + bioCell Bio Cell item, currently not meta sensitive + coalfuelCell Coalfuel Cell item, currently not meta sensitive + biofuelCell Biofuel Cell item, currently not meta sensitive + waterCell Water Cell item, currently not meta sensitive + electrolyzedWaterCell Electrolyzed Water Cell item, currently not meta sensitive + + fuelCan Empty Fuel Can item, currently not meta sensitive + filledFuelCan Fuel Can item, meta = fuel value (as of v1.45) + + tinCan Empty Tin Can item, currently not meta sensitive + filledTinCan Filled Tin Can item, currently not meta sensitive + + reactor components + uraniumCell Uranium Cell item, meta = damage value + coolingCell Cooling Cell item, meta = damage value + + depletedIsotopeCell Depleted Isotope Cell item, meta = damage value + reEnrichedUraniumCell Re-Enriched Uranium Cell item, currently not meta sensitive + nearDepletedUraniumCell Near-Depleted Uranium Cell item, currently not meta sensitive + + integratedReactorPlating Integrated Reactor Plating item, meta = damage value + integratedHeatDisperser Integrated Heat Disperser item, meta = damage value + + terraformer blueprints + terraformerBlueprint Empty Terraformer Blueprint item, currently not meta sensitive + cultivationTerraformerBlueprint Cultivation Terraformer Blueprint item, currently not meta sensitive + irrigationTerraformerBlueprint Irrigation Terraformer Blueprint item, currently not meta sensitive + chillingTerraformerBlueprint Chilling Terraformer Blueprint item, currently not meta sensitive + desertificationTerraformerBlueprint Desertification Terraformer Blueprint item, currently not meta sensitive + flatificatorTerraformerBlueprint Flatificator Terraformer Blueprint item, currently not meta sensitive + mushroomTerraformerBlueprint Mushroom Terraformer Blueprint item, currently not meta sensitive + + diamond chain + coalBall Coal Ball item, currently not meta sensitive + compressedCoalBall Compressed Coal Ball item, currently not meta sensitive + coalChunk Coal Chunk item, currently not meta sensitive + industrialDiamond Industrial Diamond item, currently not meta sensitive, DEPRECATED + + recycler chain + scrap Scrap item, currently not meta sensitive + scrapBox Scrap Box item, currently not meta sensitive + + fuel production chain + hydratedCoalClump Hydrated Coal Clump item, currently not meta sensitive + plantBall Plant Ball item, currently not meta sensitive + compressedPlantBall Compressed Plant Ball item, currently not meta sensitive + + painting + painter Painter item, currently not meta sensitive + + blackPainter Black Painter item, meta = damage value + redPainter Red Painter item, meta = damage value + greenPainter Green Painter item, meta = damage value + brownPainter Brown Painter item, meta = damage value + bluePainter Blue Painter item, meta = damage value + purplePainter Purple Painter item, meta = damage value + cyanPainter Cyan Painter item, meta = damage value + lightGreyPainter Light Grey Painter item, meta = damage value + darkGreyPainter Dark Grey Painter item, meta = damage value + pinkPainter Pink Painter item, meta = damage value + limePainter Lime Painter item, meta = damage value + yellowPainter Yellow Painter item, meta = damage value + cloudPainter Cloud Painter item, meta = damage value + magentaPainter Magenta Painter item, meta = damage value + orangePainter Orange Painter item, meta = damage value + whitePainter White Painter item, meta = damage value + + explosives + related + dynamite Throwable Dynamite item, currently not meta sensitive + stickyDynamite Throwable Sticky Dynamite item, currently not meta sensitive + + remote Dynamite Remote item, currently not meta sensitive + + misc intermediate recipe ingredients + electronicCircuit Electronic Circuit item, currently not meta sensitive + advancedCircuit Advanced Circuit item, currently not meta sensitive + + advancedAlloy Advanced Alloy item, currently not meta sensitive + + carbonFiber Raw Carbon Fiber item, currently not meta sensitive + carbonMesh Raw Carbon Mesh item, currently not meta sensitive + carbonPlate Carbon Plate item, currently not meta sensitive + + matter UU-Matter item, currently not meta sensitive + iridiumOre Iridium Ore item, currently not meta sensitive + iridiumPlate Iridium Plate item, currently not meta sensitive + + upgrade modules + overclockerUpgrade overclocker upgrade item, meta sensitive + transformerUpgrade transformer upgrade item, meta sensitive + energyStorageUpgrade energy storage upgrade item, meta sensitive + + misc + coin Coin item, currently not meta sensitive + reinforcedDoor Reinforced Door item, currently not meta sensitive + constructionFoamPellet Construction Foam Pellet item, currently not meta sensitive + cropSeed Crop seeds, stuff stored in NBT, don't use for crafting recipes! + cropnalyzer Cropnalyzer handheld device + fertilizer Basic IC2Item, used to provide nutrients toCropBlocks + hydratingCell Cell used to hydrate Crops, meta = Content, 0 = Full, 9999 = Near empty + electricHoe Electric Hoe, meta = charge level + solarHelmet Solar Helmet item, currently not meta sensitive + terraWart Terra Wart item, cures potion effects + weedEx Weed-EX can, meta = uses left + + */ + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = Items.class.getPackage(); + if (pkg != null) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else return "ic2"; + } + + private static Class Ic2Items; +} + diff --git a/src/minecraft/ic2/api/TECrop.java b/src/minecraft/ic2/api/TECrop.java new file mode 100644 index 000000000..d8b957b81 --- /dev/null +++ b/src/minecraft/ic2/api/TECrop.java @@ -0,0 +1,161 @@ +package ic2.api; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; + +/** + * Provides access to a crop tile entity. Contains all methods and fields you can access from your CropCard. + */ +public abstract class TECrop extends TileEntity +{ + /** + * ID of the plant currently on the crop. + * -1 if there is no plant currently on the crop. + */ + public short id = -1; + + /** + * Current size of the plant. + * 1 is the starting size and the maximum size varies from plant to plant. + */ + public byte size = 0; + + /** + * Growth ability of a plant. + * Higher values give faster growth. + */ + public byte statGrowth = 0; + /** + * Chances and amount of gain and seeds from harvested crops. + * Higher values give more drops. + */ + public byte statGain = 0; + /** + * Ability for the plant to resist trampling. + * Higher values give more resistance against trampling. + */ + public byte statResistance = 0; + + /** + * Scan level, increases each time a seed goes through analysis. + */ + public byte scanLevel = 0; + + /** + * Custom data stored along a TECrop. + */ + public short[] custumData = new short[16]; + + /** + * Crop nutrients. + * Ranges from 0 (empty) to 100 (full). + */ + public int nutrientStorage = 0; + /** + * Crop hydration. + * Values are: + * - 0 for nothing + * - 1-10 for water hydration + * - 11-100 for distilled water (hydration cell) hydration + */ + public int waterStorage = 0; + /** + * Remaining duration of WeedEX + * PRevents weed from growing and protects against (unimplemented) insects or similar stuff + */ + public int exStorage = 0; + + /** + * Crop humidity. + * Ranges from 0 (dry) to 10 (humid). + * Updates every couple of seconds or when an update is requested. + * + * @see #updateState() + */ + public abstract byte getHumidity(); + + /** + * Get the crop's nutrient level. + * Ranges from 0 (empty) to 10 (full). + * Updates every couple of seconds or when an update is requested. + * + * @see #updateState() + */ + public abstract byte getNutrients(); + + /** + * Get the crop's air quality. + * Ranges from 0 (cluttered) to 10 (fresh). + * Updates every couple of seconds or when an update is requested. + * + * @see #updateState() + * + * @return Crop air quality + */ + public abstract byte getAirQuality(); + + /** + * Get the crop's light level. + * + * @return Crop light level + */ + public int getLightLevel() + { + return worldObj.getBlockLightValue(xCoord, yCoord, zCoord); + } + + + /** + * Pick the crop, removing and giving seeds for the plant. + * + * @param manual whether it was done by hand (not automated) + * @return true if successfully picked + */ + public abstract boolean pick(boolean manual); + + /** + * Harvest the crop, turning it into gain and resetting its size. + * + * @param manual whether it one by hand (not automated) + * @return true if successfully harvested + */ + public abstract boolean harvest(boolean manual); + + /** + * Fully clears the crop without dropping anything. + */ + public abstract void reset(); + + /** + * Request a texture and lighting update. + */ + public abstract void updateState(); + + /** + * Check if a block is under the farmland containing the crop. + * Searches up to 2 blocks below the farmland or an air space, whichever appears first. + * + * @param block block to search + * @return Whether the block was found + */ + public abstract boolean isBlockBelow(Block block); + + /** + * Generate plant seeds with the given parameters. + * + * @param plant plant ID + * @param growth plant growth stat + * @param gain plant gain stat + * @param resis plant resistance stat + * @param scan plant scan level + * @return Plant seed item + */ + public abstract ItemStack generateSeeds(short plant, byte growth, byte gain, byte resis, byte scan); + + /** + * For internal usage only. + */ + public abstract void addLocal(String s1, String s2); + +} diff --git a/src/minecraft/ic2/api/energy/EnergyNet.java b/src/minecraft/ic2/api/energy/EnergyNet.java new file mode 100644 index 000000000..724aa9bc9 --- /dev/null +++ b/src/minecraft/ic2/api/energy/EnergyNet.java @@ -0,0 +1,175 @@ +package ic2.api.energy; + +import java.lang.reflect.Method; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import ic2.api.energy.tile.IEnergySource; + +/** + * Provides access to the energy network. + */ +public final class EnergyNet { + /** + * Gets the EnergyNet instance for the specified world. + * + * @param world world + * @return EnergyNet instance for the world + */ + public static EnergyNet getForWorld(World world) { + try { + if (EnergyNet_getForWorld == null) EnergyNet_getForWorld = Class.forName(getPackage() + ".core.EnergyNet").getMethod("getForWorld", World.class); + + return new EnergyNet(EnergyNet_getForWorld.invoke(null, world)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private EnergyNet(Object energyNetInstance) { + this.energyNetInstance = energyNetInstance; + } + + /** + * Add a tile entity to the energy network. + * The tile entity has to be valid and initialized. + * + * @param addedTileEntity tile entity to add + * + * @deprecated use EnergyTileLoadEvent instead + */ + @Deprecated + public void addTileEntity(TileEntity addedTileEntity) { + try { + if (EnergyNet_addTileEntity == null) EnergyNet_addTileEntity = Class.forName(getPackage() + ".core.EnergyNet").getMethod("addTileEntity", TileEntity.class); + + EnergyNet_addTileEntity.invoke(energyNetInstance, addedTileEntity); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Removes a tile entity from the energy network. + * The tile entity has to be still valid. + * + * @param removedTileEntity tile entity to remove + * + * @deprecated use EnergyTileUnloadEvent instead + */ + @Deprecated + public void removeTileEntity(TileEntity removedTileEntity) { + try { + if (EnergyNet_removeTileEntity == null) EnergyNet_removeTileEntity = Class.forName(getPackage() + ".core.EnergyNet").getMethod("removeTileEntity", TileEntity.class); + + EnergyNet_removeTileEntity.invoke(energyNetInstance, removedTileEntity); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Emit energy from an energy source to the energy network. + * + * @param energySource energy source to emit energy from + * @param amount amount of energy to emit in EU + * @return Leftover (unused) power + * + * @deprecated use EnergyTileSourceEvent instead + */ + @Deprecated + public int emitEnergyFrom(IEnergySource energySource, int amount) { + try { + if (EnergyNet_emitEnergyFrom == null) EnergyNet_emitEnergyFrom = Class.forName(getPackage() + ".core.EnergyNet").getMethod("emitEnergyFrom", IEnergySource.class, Integer.TYPE); + + return ((Integer) EnergyNet_emitEnergyFrom.invoke(energyNetInstance, energySource, amount)).intValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get the amount of energy currently being conducted by a conductor. + * Call this twice with a delay to get the average conducted power by doing (call2 - call1) / 2. + * + * @param tileEntity conductor + * + * @deprecated use getTotalEnergyEmitted and getTotalEnergySunken instead + */ + @Deprecated + public long getTotalEnergyConducted(TileEntity tileEntity) { + try { + if (EnergyNet_getTotalEnergyConducted == null) EnergyNet_getTotalEnergyConducted = Class.forName(getPackage() + ".core.EnergyNet").getMethod("getTotalEnergyConducted", TileEntity.class); + + return ((Long) EnergyNet_getTotalEnergyConducted.invoke(energyNetInstance, tileEntity)).longValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * determine how much energy has been emitted by the EnergyEmitter specified + * + * @note call this twice with x ticks delay to get the avg. emitted power p = (call2 - call1) / x EU/tick + * + * @param tileEntity energy emitter + */ + public long getTotalEnergyEmitted(TileEntity tileEntity) { + try { + if (EnergyNet_getTotalEnergyEmitted == null) EnergyNet_getTotalEnergyEmitted = Class.forName(getPackage() + ".core.EnergyNet").getMethod("getTotalEnergyEmitted", TileEntity.class); + + return ((Long) EnergyNet_getTotalEnergyEmitted.invoke(energyNetInstance, tileEntity)).longValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * determine how much energy has been sunken by the EnergySink specified + * + * @note call this twice with x ticks delay to get the avg. sunken power p = (call2 - call1) / x EU/tick + * + * @param tileEntity energy emitter + */ + public long getTotalEnergySunken(TileEntity tileEntity) { + try { + if (EnergyNet_getTotalEnergySunken == null) EnergyNet_getTotalEnergySunken = Class.forName(getPackage() + ".core.EnergyNet").getMethod("getTotalEnergySunken", TileEntity.class); + + return ((Long) EnergyNet_getTotalEnergySunken.invoke(energyNetInstance, tileEntity)).longValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = EnergyNet.class.getPackage(); + + if (pkg != null) { + String packageName = pkg.getName(); + + return packageName.substring(0, packageName.length() - ".api.energy".length()); + } + + return "ic2"; + } + + /** + * Instance of the energy network. + */ + Object energyNetInstance; + + private static Method EnergyNet_getForWorld; + private static Method EnergyNet_addTileEntity; + private static Method EnergyNet_removeTileEntity; + private static Method EnergyNet_emitEnergyFrom; + private static Method EnergyNet_getTotalEnergyConducted; + private static Method EnergyNet_getTotalEnergyEmitted; + private static Method EnergyNet_getTotalEnergySunken; +} + diff --git a/src/minecraft/ic2/api/energy/event/EnergyTileEvent.java b/src/minecraft/ic2/api/energy/event/EnergyTileEvent.java new file mode 100644 index 000000000..c8faea4f9 --- /dev/null +++ b/src/minecraft/ic2/api/energy/event/EnergyTileEvent.java @@ -0,0 +1,17 @@ +package ic2.api.energy.event; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.event.world.WorldEvent; + +import ic2.api.energy.tile.IEnergyTile; + +public class EnergyTileEvent extends WorldEvent { + public final IEnergyTile energyTile; + + public EnergyTileEvent(IEnergyTile energyTile) { + super(((TileEntity) energyTile).worldObj); + + this.energyTile = energyTile; + } +} + diff --git a/src/minecraft/ic2/api/energy/event/EnergyTileLoadEvent.java b/src/minecraft/ic2/api/energy/event/EnergyTileLoadEvent.java new file mode 100644 index 000000000..b80d45b30 --- /dev/null +++ b/src/minecraft/ic2/api/energy/event/EnergyTileLoadEvent.java @@ -0,0 +1,24 @@ +package ic2.api.energy.event; + +import ic2.api.energy.tile.IEnergyTile; + +/** + * Event announcing new energy tiles. + * + * This event notifies subscribers of loaded energy tiles, e.g. after getting + * loaded through the chunk they are in or after being placed down by the + * player or another deployer mechanism. + * + * Every energy tile which wants to get connected to the IC2 Energy Network has + * to either post this event or alternatively call EnergyNet.addTileEntity(). + * + * You may use this event to build a static representation of energy tiles for + * your own energy grid implementation if you need to. It's not required if you + * always lookup energy paths on demand. + */ +public class EnergyTileLoadEvent extends EnergyTileEvent { + public EnergyTileLoadEvent(IEnergyTile energyTile) { + super(energyTile); + } +} + diff --git a/src/minecraft/ic2/api/energy/event/EnergyTileSourceEvent.java b/src/minecraft/ic2/api/energy/event/EnergyTileSourceEvent.java new file mode 100644 index 000000000..80c230c31 --- /dev/null +++ b/src/minecraft/ic2/api/energy/event/EnergyTileSourceEvent.java @@ -0,0 +1,33 @@ +package ic2.api.energy.event; + +import ic2.api.energy.tile.IEnergySource; + +/** + * Event announcing an energy source operation. + * + * This event notifies subscribers of energy sources trying to push energy into + * an energy grid. + * + * The amount field indicates the maximum amount of energy left to be + * distributed. You have to substract the amount of energy you accepted from + * 'amount'. + * + * The IEnergySource posting this event has to check 'amount' to see how much + * energy has not been used up and adjust its output buffer accordingly + * (usually buffer -= 'initial amount' - 'amount after posting the event') + */ +public class EnergyTileSourceEvent extends EnergyTileEvent { + /** + * Amount of energy provided by the energy source. + * + * amount needs to be adjusted to show the remaining unused energy. + */ + public int amount; + + public EnergyTileSourceEvent(IEnergySource energySource, int amount) { + super(energySource); + + this.amount = amount; + } +} + diff --git a/src/minecraft/ic2/api/energy/event/EnergyTileUnloadEvent.java b/src/minecraft/ic2/api/energy/event/EnergyTileUnloadEvent.java new file mode 100644 index 000000000..5e0463752 --- /dev/null +++ b/src/minecraft/ic2/api/energy/event/EnergyTileUnloadEvent.java @@ -0,0 +1,25 @@ +package ic2.api.energy.event; + +import ic2.api.energy.tile.IEnergyTile; + +/** + * Event announcing terminated energy tiles. + * + * This event notifies subscribers of unloaded energy tiles, e.g. after getting + * unloaded through the chunk they are in or after being destroyed by the + * player or another block pick/destruction mechanism. + * + * Every energy tile which wants to get disconnected from the IC2 Energy + * Network has to either post this event or alternatively call + * EnergyNet.removeTileEntity(). + * + * You may use this event to build a static representation of energy tiles for + * your own energy grid implementation if you need to. It's not required if you + * always lookup energy paths on demand. + */ +public class EnergyTileUnloadEvent extends EnergyTileEvent { + public EnergyTileUnloadEvent(IEnergyTile energyTile) { + super(energyTile); + } +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergyAcceptor.java b/src/minecraft/ic2/api/energy/tile/IEnergyAcceptor.java new file mode 100644 index 000000000..c4bb85bcd --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergyAcceptor.java @@ -0,0 +1,22 @@ +package ic2.api.energy.tile; + +import net.minecraft.tileentity.TileEntity; + +import ic2.api.Direction; + +/** + * For internal usage only. + * + * @see IEnergySink + * @see IEnergyConductor + */ +public interface IEnergyAcceptor extends IEnergyTile { + /** + * Determine if this acceptor can accept current from an adjacent emitter in a direction. + * + * @param emitter energy emitter + * @param direction direction the energy is being received from + */ + boolean acceptsEnergyFrom(TileEntity emitter, Direction direction); +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergyConductor.java b/src/minecraft/ic2/api/energy/tile/IEnergyConductor.java new file mode 100644 index 000000000..2bfc8b6cf --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergyConductor.java @@ -0,0 +1,51 @@ +package ic2.api.energy.tile; + +/** + * Tile entities which conduct energy pulses without buffering (mostly cables) have to implement this + * interface. + */ +public interface IEnergyConductor extends IEnergyAcceptor, IEnergyEmitter { + /** + * Energy loss for the conductor in EU per block. + * + * @return Energy loss + */ + double getConductionLoss(); + + /** + * Amount of energy the insulation will handle before shocking nearby players and mobs. + * + * @return Insulation energy absorption in EU + */ + int getInsulationEnergyAbsorption(); + + /** + * Amount of energy the insulation will handle before it is destroyed. + * Ensure that this value is greater than the insulation energy absorption + 64. + * + * @return Insulation-destroying energy in EU + */ + int getInsulationBreakdownEnergy(); + + /** + * Amount of energy the conductor will handle before it melts. + * + * @return Conductor-destroying energy in EU + */ + int getConductorBreakdownEnergy(); + + /** + * Remove the conductor's insulation if the insulation breakdown energy was exceeded. + * + * @see #getInsulationBreakdownEnergy() + */ + void removeInsulation(); + + /** + * Remove the conductor if the conductor breakdown energy was exceeded. + * + * @see #getConductorBreakdownEnergy() + */ + void removeConductor(); +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergyEmitter.java b/src/minecraft/ic2/api/energy/tile/IEnergyEmitter.java new file mode 100644 index 000000000..367349f85 --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergyEmitter.java @@ -0,0 +1,23 @@ +package ic2.api.energy.tile; + +import net.minecraft.tileentity.TileEntity; + +import ic2.api.Direction; + +/** + * For internal usage only. + * + * @see IEnergySource + * @see IEnergyConductor + */ +public interface IEnergyEmitter extends IEnergyTile { + /** + * Determine if this emitter can emit energy to an adjacent receiver. + * + * @param receiver receiver + * @param direction direction the receiver is from the emitter + * @return Whether energy should be emitted + */ + boolean emitsEnergyTo(TileEntity receiver, Direction direction); +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergySink.java b/src/minecraft/ic2/api/energy/tile/IEnergySink.java new file mode 100644 index 000000000..19013c1b1 --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergySink.java @@ -0,0 +1,41 @@ +package ic2.api.energy.tile; + +import ic2.api.Direction; + +/** + * Allows a tile entity (mostly a machine) to receive energy. + */ +public interface IEnergySink extends IEnergyAcceptor { + /** + * Determine how much energy the sink accepts. + * + * This value is unrelated to getMaxSafeInput(). + * + * Make sure that injectEnergy() does accepts energy if demandsEnergy() returns anything > 0. + * + * @return max accepted input in eu + */ + int demandsEnergy(); + + /** + * Transfer energy to the sink. + * + * @param directionFrom direction from which the energy comes from + * @param amount energy to be transferred + * @return Energy not consumed (leftover) + */ + int injectEnergy(Direction directionFrom, int amount); + + /** + * Determine the amount of eu which can be safely injected into the specific energy sink without exploding. + * + * Typical values are 32 for LV, 128 for MV, 512 for HV and 2048 for EV. A value of Integer.MAX_VALUE indicates no + * limit. + * + * This value is unrelated to demandsEnergy(). + * + * @return max safe input in eu + */ + int getMaxSafeInput(); +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergySource.java b/src/minecraft/ic2/api/energy/tile/IEnergySource.java new file mode 100644 index 000000000..d00864881 --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergySource.java @@ -0,0 +1,15 @@ +package ic2.api.energy.tile; + +/** + * Allows a tile entity (mostly a generator) to emit energy. + */ +public interface IEnergySource extends IEnergyEmitter { + /** + * Maximum energy output provided by the source. + * If unsure, use Integer.MAX_VALUE. + * + * @return Maximum energy output + */ + int getMaxEnergyOutput(); +} + diff --git a/src/minecraft/ic2/api/energy/tile/IEnergyTile.java b/src/minecraft/ic2/api/energy/tile/IEnergyTile.java new file mode 100644 index 000000000..182e10d56 --- /dev/null +++ b/src/minecraft/ic2/api/energy/tile/IEnergyTile.java @@ -0,0 +1,18 @@ +package ic2.api.energy.tile; + +/** + * For internal usage only. + * + * @see IEnergySink + * @see IEnergySource + * @see IEnergyConductor + */ +public interface IEnergyTile { + /** + * Determine if this tile entity has been added to the energy network + * + * @return Whether the tile entity has been added + */ + boolean isAddedToEnergyNet(); +} + diff --git a/src/minecraft/ic2/api/energy/usage.txt b/src/minecraft/ic2/api/energy/usage.txt new file mode 100644 index 000000000..b01b3c0b5 --- /dev/null +++ b/src/minecraft/ic2/api/energy/usage.txt @@ -0,0 +1,101 @@ +----------------------------------------------------- +-- How to implement your own energy network blocks -- +----------------------------------------------------- + +There are currently three different types of energy network blocks: +- energy sources, e.g. generators or the output side of a storage block/transformer +- energy sinks, e.g. machines or the input side of a storage block/transformer +- conductors, e.g. cables + +Note that storage blocks or transformers are both sources and sinks. + +All those blocks have to have a tile entity which has to implement the interface corresponding to +its function and also post events to the Forge event bus. + +The energy generation, distribution and consumption is strictly limited to the simulating (server) +side, use the proper side checks before posting the related events. One possibility is to check for +FMLCommonHandler.instance().getEffectiveSide().isClient() being false. + +The energy network works by sources pushing energy into the grid through EnergyTileSourceEvent, +conductors will carry the energy to sinks which will then receive it through injectEnergy(). + +-- EnergyTileLoadEvent -- + +For all energy network tiles (sources, sinks, conductors) you have to post an EnergyTileLoadEvent. + +The event has to be posted as soon as the implementing tile entity is fully loaded, usually after +loading the chunk which contains it or after the user placing the block. + +The energy net implementation will use the event to add it to its energy grid map, taking it into +account for further energy transfers. + +You can detect the loading by either using the 1st iteration of updateEntity() or by waiting for +the next world tick after TileEntity.validate(). The 2nd approach is obviously more sophisticated +and requires to use some tick queuing mechanism. + +The event can by posted as following: + MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); + +-- EnergyTileUnloadEvent -- + +Another event every energy tile has to post is the EnergyTileUnloadEvent. + +The event has to be posted as soon as the implementing tile entity is being unloaded, either by +unloading the containing chunk or by destroying the block containing it. + +It's possible to detect the unloading by triggering on both the beginning of +TileEntity.invalidate() and the beginning of TileEntity.onChunkUnload(). + +It is important that the tile entity is still properly linked to the world while posting the unload +event, otherwise the energy net can't find all affected connections. + +-- energy source -- + +An energy source has to post the following events: + - EnergyTileLoadEvent on load + - EnergyTileUnloadEvent on unload + - EnergyTileSourceEvent whenever it wants to send energy + +Additionally the interface IEnergySource has to be implemented. + +The EnergyTileSourceEvent contains a field amount, which should be evaluated after having posted +the event. The value determines how much energy couldn't be delivered somewhere. + +-- energy sink -- + +An energy sink has to post the following events: + - EnergyTileLoadEvent on load + - EnergyTileUnloadEvent on unload + +Additionally the interface IEnergySink has to be implemented. + +The method demandsEnergy() will be called fairly often and should be implemented with performance +in mind. It's usually recommended to always fill some small internal buffer regardless of other +conditions, e.g. even if an enabling redstone signal is off. + +-- energy conductor -- + +An energy conductor has to post the following events: + - EnergyTileLoadEvent on load + - EnergyTileUnloadEvent on unload + +Additionally the interface IEnergyConductor has to be implemented. + + +-------------------------------------------------- +-- How to implement/add your own energy network -- +-------------------------------------------------- + +If you want to create an alternative way of distributing energy, e.g. to have different +distribution rules or to use energy networks provided by other mods, you can register to the energy +tile events and use the interfaces to handle the energy distribution yourself. It's no longer +required to use conversion blocks. + +IC2's EnergyNet itself is built on top of the api events and interfaces, providing their default +use case. + +Note that is you have a pull-type energy network which lets the sinks retrieve energy from the +sources instead of IC2's method of pushing energy from the sources to the sinks, you'll currently +have to monitor the energy sinks regularly for their energy demand and start/stop pulling energy +accordingly. The load and unload events will tell you when to start/stop monitoring demandsEnergy. + diff --git a/src/minecraft/ic2/api/network/INetworkClientTileEntityEventListener.java b/src/minecraft/ic2/api/network/INetworkClientTileEntityEventListener.java new file mode 100644 index 000000000..ed3ea38fe --- /dev/null +++ b/src/minecraft/ic2/api/network/INetworkClientTileEntityEventListener.java @@ -0,0 +1,17 @@ +package ic2.api.network; + +import net.minecraft.entity.player.EntityPlayer; + +/** + * Allows a tile entity to receive network events received from clients. + */ +public interface INetworkClientTileEntityEventListener { + /** + * Called when a network event is received. + * + * @param player client which sent the event + * @param event event ID + */ + void onNetworkEvent(EntityPlayer player, int event); +} + diff --git a/src/minecraft/ic2/api/network/INetworkDataProvider.java b/src/minecraft/ic2/api/network/INetworkDataProvider.java new file mode 100644 index 000000000..c3f283e5f --- /dev/null +++ b/src/minecraft/ic2/api/network/INetworkDataProvider.java @@ -0,0 +1,18 @@ +package ic2.api.network; + +import java.util.List; + +/** + * Tile entities which want to synchronized specific fields between client and server have to implement this. + * + * The fields don't update themselves, a field update must be sent every time a synchronized field changes. + */ +public interface INetworkDataProvider { + /** + * Get the list of synchronized fields. + * + * @return Names of the synchronized fields + */ + List getNetworkedFields(); +} + diff --git a/src/minecraft/ic2/api/network/INetworkItemEventListener.java b/src/minecraft/ic2/api/network/INetworkItemEventListener.java new file mode 100644 index 000000000..02ce470da --- /dev/null +++ b/src/minecraft/ic2/api/network/INetworkItemEventListener.java @@ -0,0 +1,18 @@ +package ic2.api.network; + +import net.minecraft.entity.player.EntityPlayer; + +/** + * Allows an item to receive network events received from the server. + */ +public interface INetworkItemEventListener { + /** + * Called when a network event is received. + * + * @param metaData item metadata + * @param player player containing the item + * @param event event ID + */ + void onNetworkEvent(int metaData, EntityPlayer player, int event); +} + diff --git a/src/minecraft/ic2/api/network/INetworkTileEntityEventListener.java b/src/minecraft/ic2/api/network/INetworkTileEntityEventListener.java new file mode 100644 index 000000000..fbb4753c5 --- /dev/null +++ b/src/minecraft/ic2/api/network/INetworkTileEntityEventListener.java @@ -0,0 +1,14 @@ +package ic2.api.network; + +/** + * Allows a tile entity to receive network events received from the server. + */ +public interface INetworkTileEntityEventListener { + /** + * Called when a network event is received. + * + * @param event Event ID + */ + void onNetworkEvent(int event); +} + diff --git a/src/minecraft/ic2/api/network/INetworkUpdateListener.java b/src/minecraft/ic2/api/network/INetworkUpdateListener.java new file mode 100644 index 000000000..09414ae38 --- /dev/null +++ b/src/minecraft/ic2/api/network/INetworkUpdateListener.java @@ -0,0 +1,14 @@ +package ic2.api.network; + +/** + * Allows a tile entity to receive field sync updates received from the server. + */ +public interface INetworkUpdateListener { + /** + * Called when a field is synchronized. + * + * @param field field synchronized + */ + void onNetworkUpdate(String field); +} + diff --git a/src/minecraft/ic2/api/network/NetworkHelper.java b/src/minecraft/ic2/api/network/NetworkHelper.java new file mode 100644 index 000000000..0981dafbe --- /dev/null +++ b/src/minecraft/ic2/api/network/NetworkHelper.java @@ -0,0 +1,243 @@ +package ic2.api.network; + +import java.lang.reflect.Method; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +/** + * Provides methods to initiate events and synchronize tile entity fields in SMP. + * + * The methods are transparent between singleplayer and multiplayer - if a method is called in + * singleplayer, the associated callback will be locally executed. The implementation is different + * between the client and server versions of IC2. + * + * You'll usually want to use the server->client methods defined here to synchronize information + * which is needed by the clients outside the GUI, such as rendering the block, playing sounds or + * producing effects. Anything which is only visible inside the GUI should be synchronized through + * the Container class associated to the GUI in Container.updateProgressBar(). + */ +public final class NetworkHelper { + // server -> client + + + /** + * Schedule a TileEntity's field to be updated to the clients in range. + * + * The updater will query the field's value during the next update, updates happen usually + * every 2 ticks. If low latency is important use initiateTileEntityEvent instead. + * + * IC2's network updates have to get triggered every time, it doesn't continuously poll/send + * the field value. Just call updateTileEntityField after every change to a field which needs + * network synchronization. + * + * The following field data types are currently supported: + * - int, int[], short, short[], byte, byte[], long, long[] + * - float, float[], double, double[] + * - boolean, boolean[] + * - String, String[] + * - ItemStack + * - NBTBase (includes NBTTagCompound) + * - Block, Item, Achievement, Potion, Enchantment + * - ChunkCoordinates, ChunkCoordIntPair + * - TileEntity (does not sync the actual tile entity, instead looks up the tile entity by its position in the client world) + * - World (does not sync the actual world, instead looks up the world by its dimension ID) + * + * Once the update has been processed by the client, it'll call onNetworkUpdate on the client- + * side TileEntity if it implements INetworkUpdateListener. + * + * If this method is being executed on the client (i.e. Singleplayer), it'll just call + * INetworkUpdateListener.onNetworkUpdate (if implemented by the te). + * + * @param te TileEntity to update + * @param field Name of the field to update + */ + public static void updateTileEntityField(TileEntity te, String field) { + try { + if (NetworkManager_updateTileEntityField == null) NetworkManager_updateTileEntityField = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("updateTileEntityField", TileEntity.class, String.class); + if (instance == null) instance = getInstance(); + + NetworkManager_updateTileEntityField.invoke(instance, te, field); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Immediately send an event for the specified TileEntity to the clients in range. + * + * If this method is being executed on the client (i.e. Singleplayer), it'll just call + * INetworkTileEntityEventListener.onNetworkEvent (if implemented by the te). + * + * @param te TileEntity to notify, should implement INetworkTileEntityEventListener + * @param event Arbitrary integer to represent the event, choosing the values is up to you + * @param limitRange Limit the notification range to (currently) 20 blocks instead of the + * tracking distance if true + */ + public static void initiateTileEntityEvent(TileEntity te, int event, boolean limitRange) { + try { + if (NetworkManager_initiateTileEntityEvent == null) NetworkManager_initiateTileEntityEvent = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("initiateTileEntityEvent", TileEntity.class, Integer.TYPE, Boolean.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_initiateTileEntityEvent.invoke(instance, te, event, limitRange); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Immediately send an event for the specified Item to the clients in range. + * + * The item should implement INetworkItemEventListener to receive the event. + * + * If this method is being executed on the client (i.e. Singleplayer), it'll just call + * INetworkItemEventListener.onNetworkEvent (if implemented by the item). + * + * @param player EntityPlayer holding the item + * @param itemStack ItemStack containing the item + * @param event Arbitrary integer to represent the event, choosing the values is up to you + * @param limitRange Limit the notification range to (currently) 20 blocks instead of the + * tracking distance if true + */ + public static void initiateItemEvent(EntityPlayer player, ItemStack itemStack, int event, boolean limitRange) { + try { + if (NetworkManager_initiateItemEvent == null) NetworkManager_initiateItemEvent = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("initiateItemEvent", EntityPlayer.class, ItemStack.class, Integer.TYPE, Boolean.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_initiateItemEvent.invoke(instance, player, itemStack, event, limitRange); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Schedule a block update (re-render) on the clients in range. + * + * If this method is being executed on the client (i.e. Singleplayer), it'll just trigger the + * block update locally. + * + * @param world World containing the block + * @param x The block's x coordinate + * @param y The block's y coordinate + * @param z The block's z coordinate + */ + public static void announceBlockUpdate(World world, int x, int y, int z) { + try { + if (NetworkManager_announceBlockUpdate == null) NetworkManager_announceBlockUpdate = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("announceBlockUpdate", World.class, Integer.TYPE, Integer.TYPE, Integer.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_announceBlockUpdate.invoke(instance, world, x, y, z); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + // client -> server + + + /** + * Ask the server to send the values of the fields specified. + * + * See updateTileEntityField for the supported field types. + * + * The implementation is currently limited to TileEntitys as data providers. The tile entity + * has to be fully initialized when executing this method (i.e. valid worldObj+coords). + * + * This method doesn't do anything if executed on the server. + * + * @param dataProvider Object implementing the INetworkDataProvider interface + */ + public static void requestInitialData(INetworkDataProvider dataProvider) { + try { + if (NetworkManager_requestInitialData == null) NetworkManager_requestInitialData = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("requestInitialData", INetworkDataProvider.class); + if (instance == null) instance = getInstance(); + + NetworkManager_requestInitialData.invoke(instance, dataProvider); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Immediately send an event for the specified TileEntity to the server. + * + * This method doesn't do anything if executed on the server. + * + * @param te TileEntity to notify, should implement INetworkClientTileEntityEventListener + * @param event Arbitrary integer to represent the event, choosing the values is up to you + */ + public static void initiateClientTileEntityEvent(TileEntity te, int event) { + try { + if (NetworkManager_initiateClientTileEntityEvent == null) NetworkManager_initiateClientTileEntityEvent = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("initiateClientTileEntityEvent", TileEntity.class, Integer.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_initiateClientTileEntityEvent.invoke(instance, te, event); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Immediately send an event for the specified Item to the clients in range. + * + * The item should implement INetworkItemEventListener to receive the event. + * + * This method doesn't do anything if executed on the server. + * + * @param itemStack ItemStack containing the item + * @param event Arbitrary integer to represent the event, choosing the values is up to you + */ + public static void initiateClientItemEvent(ItemStack itemStack, int event) { + try { + if (NetworkManager_initiateClientItemEvent == null) NetworkManager_initiateClientItemEvent = Class.forName(getPackage() + ".core.network.NetworkManager").getMethod("initiateClientItemEvent", ItemStack.class, Integer.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_initiateClientItemEvent.invoke(instance, itemStack, event); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get the base IC2 package name, used internally. + * + * @return IC2 package name, if unable to be determined defaults to ic2 + */ + private static String getPackage() { + Package pkg = NetworkHelper.class.getPackage(); + + if (pkg != null) { + String packageName = pkg.getName(); + + return packageName.substring(0, packageName.length() - ".api.network".length()); + } + + return "ic2"; + } + + /** + * Get the NetworkManager instance, used internally. + * + * @return NetworkManager instance + */ + private static Object getInstance() { + try { + return Class.forName(getPackage() + ".core.IC2").getDeclaredField("network").get(null); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + private static Object instance; + private static Method NetworkManager_updateTileEntityField; + private static Method NetworkManager_initiateTileEntityEvent; + private static Method NetworkManager_initiateItemEvent; + private static Method NetworkManager_announceBlockUpdate; + private static Method NetworkManager_requestInitialData; + private static Method NetworkManager_initiateClientTileEntityEvent; + private static Method NetworkManager_initiateClientItemEvent; +} +