From 4cd39ad1fa5caecdb074f6c498b1b2d07566800d Mon Sep 17 00:00:00 2001 From: Aidan Brady Date: Wed, 17 Oct 2012 15:55:29 -0400 Subject: [PATCH] Added logo and API to project for Jenkins. --- logo.png | Bin 0 -> 11600 bytes mcmod.info | 17 + .../api/blueprints/BlockSignature.java | 77 +++ .../api/blueprints/BlueprintManager.java | 34 ++ .../buildcraft/api/blueprints/BptBlock.java | 266 ++++++++++ .../api/blueprints/BptBlockUtils.java | 87 ++++ .../api/blueprints/BptSlotInfo.java | 58 +++ .../api/blueprints/IBptContext.java | 53 ++ .../api/blueprints/ItemSignature.java | 47 ++ .../buildcraft/api/bptblocks/BptBlockBed.java | 88 ++++ .../api/bptblocks/BptBlockCustomStack.java | 35 ++ .../api/bptblocks/BptBlockDelegate.java | 67 +++ .../api/bptblocks/BptBlockDirt.java | 43 ++ .../api/bptblocks/BptBlockDoor.java | 72 +++ .../api/bptblocks/BptBlockIgnore.java | 46 ++ .../api/bptblocks/BptBlockIgnoreMeta.java | 35 ++ .../api/bptblocks/BptBlockInventory.java | 27 + .../api/bptblocks/BptBlockLever.java | 39 ++ .../api/bptblocks/BptBlockLiquid.java | 64 +++ .../api/bptblocks/BptBlockPiston.java | 28 ++ .../api/bptblocks/BptBlockPumpkin.java | 54 ++ .../bptblocks/BptBlockRedstoneRepeater.java | 51 ++ .../bptblocks/BptBlockRotateInventory.java | 26 + .../api/bptblocks/BptBlockRotateMeta.java | 85 ++++ .../api/bptblocks/BptBlockSign.java | 66 +++ .../api/bptblocks/BptBlockStairs.java | 54 ++ .../api/bptblocks/BptBlockWallSide.java | 53 ++ .../buildcraft/api/core/BuildCraftAPI.java | 56 +++ .../buildcraft/api/core/IAreaProvider.java | 35 ++ src/common/buildcraft/api/core/IBox.java | 30 ++ src/common/buildcraft/api/core/LaserKind.java | 14 + .../buildcraft/api/core/Orientations.java | 80 +++ src/common/buildcraft/api/core/Position.java | 141 ++++++ .../buildcraft/api/core/SafeTimeTracker.java | 44 ++ .../buildcraft/api/filler/FillerManager.java | 7 + .../buildcraft/api/filler/IFillerPattern.java | 21 + .../api/filler/IFillerRegistry.java | 15 + .../api/fuels/IronEngineCoolant.java | 33 ++ .../buildcraft/api/fuels/IronEngineFuel.java | 47 ++ src/common/buildcraft/api/gates/Action.java | 44 ++ .../buildcraft/api/gates/ActionManager.java | 85 ++++ src/common/buildcraft/api/gates/IAction.java | 11 + .../buildcraft/api/gates/IActionProvider.java | 24 + .../buildcraft/api/gates/IActionReceptor.java | 17 + .../api/gates/IOverrideDefaultTriggers.java | 24 + src/common/buildcraft/api/gates/ITrigger.java | 41 ++ .../api/gates/ITriggerParameter.java | 18 + .../api/gates/ITriggerProvider.java | 32 ++ src/common/buildcraft/api/gates/Trigger.java | 84 ++++ .../api/gates/TriggerParameter.java | 69 +++ .../api/inventory/ISecuredInventory.java | 20 + .../api/inventory/ISelectiveInventory.java | 17 + .../api/inventory/ISpecialInventory.java | 26 + .../buildcraft/api/liquids/ILiquid.java | 20 + .../buildcraft/api/liquids/ILiquidTank.java | 27 + .../api/liquids/ITankContainer.java | 46 ++ .../buildcraft/api/liquids/LiquidData.java | 45 ++ .../api/liquids/LiquidDictionary.java | 57 +++ .../buildcraft/api/liquids/LiquidManager.java | 64 +++ .../buildcraft/api/liquids/LiquidStack.java | 109 ++++ .../buildcraft/api/liquids/LiquidTank.java | 100 ++++ .../buildcraft/api/power/IPowerProvider.java | 41 ++ .../buildcraft/api/power/IPowerReceptor.java | 23 + .../buildcraft/api/power/PowerFramework.java | 56 +++ .../buildcraft/api/power/PowerProvider.java | 162 ++++++ .../api/recipes/AssemblyRecipe.java | 46 ++ .../api/recipes/RefineryRecipe.java | 79 +++ .../buildcraft/api/tools/IToolPipette.java | 34 ++ .../buildcraft/api/tools/IToolWrench.java | 35 ++ .../api/transport/IExtractionHandler.java | 19 + .../transport/IPassiveItemContribution.java | 20 + .../buildcraft/api/transport/IPipe.java | 45 ++ .../api/transport/IPipeConnection.java | 17 + .../buildcraft/api/transport/IPipeEntry.java | 25 + .../buildcraft/api/transport/IPipeTile.java | 17 + .../buildcraft/api/transport/IPipedItem.java | 100 ++++ .../buildcraft/api/transport/PipeManager.java | 45 ++ .../dan200/computer/api/IComputerAccess.java | 131 +++++ .../dan200/computer/api/IPeripheral.java | 103 ++++ .../dan200/turtle/api/ITurtleAccess.java | 144 ++++++ .../turtle/api/ITurtleCommandHandler.java | 20 + .../dan200/turtle/api/ITurtlePeripheral.java | 22 + .../dan200/turtle/api/ITurtleUpgrade.java | 97 ++++ src/common/dan200/turtle/api/TurtleAPI.java | 73 +++ src/common/dan200/turtle/api/TurtleSide.java | 18 + .../dan200/turtle/api/TurtleUpgradeType.java | 22 + src/common/dan200/turtle/api/TurtleVerb.java | 21 + src/common/ic2/api/BaseSeed.java | 56 +++ src/common/ic2/api/CropCard.java | 475 ++++++++++++++++++ src/common/ic2/api/Crops.java | 47 ++ src/common/ic2/api/Direction.java | 106 ++++ src/common/ic2/api/ElectricItem.java | 128 +++++ src/common/ic2/api/EnergyNet.java | 119 +++++ src/common/ic2/api/ExplosionWhitelist.java | 46 ++ src/common/ic2/api/IBoxable.java | 18 + src/common/ic2/api/IElectricItem.java | 52 ++ src/common/ic2/api/IEnergyAcceptor.java | 20 + src/common/ic2/api/IEnergyConductor.java | 51 ++ src/common/ic2/api/IEnergyEmitter.java | 21 + src/common/ic2/api/IEnergySink.java | 23 + src/common/ic2/api/IEnergySource.java | 15 + src/common/ic2/api/IEnergyStorage.java | 27 + src/common/ic2/api/IEnergyTile.java | 18 + src/common/ic2/api/IMetalArmor.java | 20 + ...INetworkClientTileEntityEventListener.java | 17 + src/common/ic2/api/INetworkDataProvider.java | 18 + .../ic2/api/INetworkItemEventListener.java | 18 + .../api/INetworkTileEntityEventListener.java | 14 + .../ic2/api/INetworkUpdateListener.java | 14 + src/common/ic2/api/IPaintableBlock.java | 21 + src/common/ic2/api/IReactor.java | 134 +++++ src/common/ic2/api/IReactorChamber.java | 13 + src/common/ic2/api/IReactorComponent.java | 97 ++++ src/common/ic2/api/ITerraformingBP.java | 35 ++ src/common/ic2/api/IWrenchable.java | 50 ++ src/common/ic2/api/Ic2Recipes.java | 358 +++++++++++++ src/common/ic2/api/Items.java | 401 +++++++++++++++ src/common/ic2/api/NetworkHelper.java | 236 +++++++++ src/common/ic2/api/TECrop.java | 161 ++++++ .../railcraft/common/api/carts/CartBase.java | 118 +++++ .../railcraft/common/api/carts/CartTools.java | 372 ++++++++++++++ .../api/carts/ICartRenderInterface.java | 24 + .../common/api/carts/IEnergyTransfer.java | 82 +++ .../common/api/carts/IItemTransfer.java | 65 +++ .../common/api/carts/ILinkableCart.java | 77 +++ .../common/api/carts/ILinkageManager.java | 102 ++++ .../common/api/carts/ILiquidTransfer.java | 53 ++ .../railcraft/common/api/carts/IMinecart.java | 52 ++ .../common/api/carts/TransferCartBase.java | 252 ++++++++++ .../common/api/carts/bore/IBoreHead.java | 37 ++ .../common/api/carts/bore/IMineable.java | 36 ++ .../common/api/core/INetworkedObject.java | 16 + .../common/api/core/IPostConnection.java | 27 + .../common/api/core/WorldCoordinate.java | 78 +++ .../api/core/items/BallastRegistry.java | 93 ++++ .../common/api/core/items/EnumItemType.java | 47 ++ .../common/api/core/items/ICrowbar.java | 14 + .../common/api/core/items/IMinecartItem.java | 39 ++ .../common/api/core/items/ITrackItem.java | 46 ++ .../common/api/core/items/ItemRegistry.java | 93 ++++ .../IBlastFurnaceCraftingManager.java | 25 + .../api/crafting/IBlastFurnaceRecipe.java | 21 + .../crafting/ICokeOvenCraftingManager.java | 26 + .../common/api/crafting/ICokeOvenRecipe.java | 20 + .../crafting/IRockCrusherCraftingManager.java | 35 ++ .../api/crafting/IRockCrusherRecipe.java | 37 ++ .../IRollingMachineCraftingManager.java | 23 + .../crafting/RailcraftCraftingManager.java | 16 + .../common/api/signals/EnumSignalAspect.java | 155 ++++++ .../common/api/signals/IBlockSignal.java | 47 ++ .../common/api/signals/ISignalController.java | 45 ++ .../common/api/signals/ISignalReceiver.java | 43 ++ .../common/api/signals/SignalTools.java | 159 ++++++ .../common/api/tracks/ITrackCustomPlaced.java | 29 ++ .../common/api/tracks/ITrackCustomShape.java | 24 + .../common/api/tracks/ITrackEmitter.java | 22 + .../common/api/tracks/ITrackInstance.java | 123 +++++ .../common/api/tracks/ITrackLockdown.java | 18 + .../common/api/tracks/ITrackPowered.java | 24 + .../common/api/tracks/ITrackReversable.java | 17 + .../common/api/tracks/ITrackSwitch.java | 21 + .../common/api/tracks/ITrackTile.java | 13 + .../common/api/tracks/RailTools.java | 175 +++++++ .../common/api/tracks/TrackInstanceBase.java | 385 ++++++++++++++ .../common/api/tracks/TrackRegistry.java | 62 +++ .../common/api/tracks/TrackSpec.java | 86 ++++ .../universalelectricity/BasicComponents.java | 60 +++ src/common/universalelectricity/Ticker.java | 49 ++ src/common/universalelectricity/UEConfig.java | 56 +++ .../UniversalElectricity.java | 90 ++++ .../electricity/ElectricInfo.java | 217 ++++++++ .../electricity/ElectricityManager.java | 362 +++++++++++++ .../electricity/ElectricityNetwork.java | 118 +++++ .../electricity/ElectricityTransferData.java | 42 ++ .../implement/IConductor.java | 56 +++ .../implement/IConnector.java | 18 + .../implement/IDisableable.java | 21 + .../implement/IElectricityProducer.java | 17 + .../implement/IElectricityReceiver.java | 39 ++ .../implement/IElectricityStorage.java | 24 + .../implement/IItemElectric.java | 16 + .../implement/IRedstoneProvider.java | 13 + .../implement/IRedstoneReceptor.java | 21 + .../implement/IRotatable.java | 28 ++ .../universalelectricity/implement/ITier.java | 21 + .../implement/IVoltage.java | 11 + .../implement/UEDamageSource.java | 65 +++ .../network/ConnectionHandler.java | 88 ++++ .../network/IPacketReceiver.java | 15 + .../network/ISimpleConnectionHandler.java | 12 + .../network/PacketManager.java | 264 ++++++++++ .../network/UECommand.java | 49 ++ .../universalelectricity/ore/OreGenBase.java | 94 ++++ .../ore/OreGenReplace.java | 128 +++++ .../ore/OreGenReplaceStone.java | 18 + .../ore/OreGenerator.java | 68 +++ .../prefab/AdvancedTile.java | 57 +++ .../prefab/BlockConductor.java | 50 ++ .../prefab/BlockMachine.java | 221 ++++++++ .../prefab/CommonProxy.java | 25 + .../prefab/ItemElectric.java | 219 ++++++++ .../prefab/TileEntityConductor.java | 175 +++++++ .../prefab/TileEntityDisableable.java | 45 ++ .../prefab/TileEntityElectricityReceiver.java | 35 ++ .../universalelectricity/prefab/Vector2.java | 106 ++++ .../universalelectricity/prefab/Vector3.java | 421 ++++++++++++++++ .../prefab/chunk/ChunkEventCaller.java | 105 ++++ .../prefab/chunk/IChunkLoadHandler.java | 21 + .../prefab/potion/CustomPotion.java | 36 ++ .../prefab/potion/CustomPotionEffect.java | 39 ++ .../recipe/CraftingRecipe.java | 25 + .../recipe/IRecipeHandler.java | 24 + .../recipe/RecipeManager.java | 386 ++++++++++++++ .../recipe/SmeltingRecipe.java | 25 + 214 files changed, 14788 insertions(+) create mode 100644 logo.png create mode 100755 mcmod.info create mode 100644 src/common/buildcraft/api/blueprints/BlockSignature.java create mode 100644 src/common/buildcraft/api/blueprints/BlueprintManager.java create mode 100644 src/common/buildcraft/api/blueprints/BptBlock.java create mode 100644 src/common/buildcraft/api/blueprints/BptBlockUtils.java create mode 100644 src/common/buildcraft/api/blueprints/BptSlotInfo.java create mode 100644 src/common/buildcraft/api/blueprints/IBptContext.java create mode 100644 src/common/buildcraft/api/blueprints/ItemSignature.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockBed.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockCustomStack.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockDelegate.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockDirt.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockDoor.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockIgnore.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockIgnoreMeta.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockInventory.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockLever.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockLiquid.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockPiston.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockPumpkin.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockRedstoneRepeater.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockRotateInventory.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockRotateMeta.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockSign.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockStairs.java create mode 100644 src/common/buildcraft/api/bptblocks/BptBlockWallSide.java create mode 100644 src/common/buildcraft/api/core/BuildCraftAPI.java create mode 100644 src/common/buildcraft/api/core/IAreaProvider.java create mode 100644 src/common/buildcraft/api/core/IBox.java create mode 100644 src/common/buildcraft/api/core/LaserKind.java create mode 100644 src/common/buildcraft/api/core/Orientations.java create mode 100644 src/common/buildcraft/api/core/Position.java create mode 100644 src/common/buildcraft/api/core/SafeTimeTracker.java create mode 100644 src/common/buildcraft/api/filler/FillerManager.java create mode 100644 src/common/buildcraft/api/filler/IFillerPattern.java create mode 100644 src/common/buildcraft/api/filler/IFillerRegistry.java create mode 100644 src/common/buildcraft/api/fuels/IronEngineCoolant.java create mode 100644 src/common/buildcraft/api/fuels/IronEngineFuel.java create mode 100644 src/common/buildcraft/api/gates/Action.java create mode 100644 src/common/buildcraft/api/gates/ActionManager.java create mode 100644 src/common/buildcraft/api/gates/IAction.java create mode 100644 src/common/buildcraft/api/gates/IActionProvider.java create mode 100644 src/common/buildcraft/api/gates/IActionReceptor.java create mode 100644 src/common/buildcraft/api/gates/IOverrideDefaultTriggers.java create mode 100644 src/common/buildcraft/api/gates/ITrigger.java create mode 100644 src/common/buildcraft/api/gates/ITriggerParameter.java create mode 100644 src/common/buildcraft/api/gates/ITriggerProvider.java create mode 100644 src/common/buildcraft/api/gates/Trigger.java create mode 100644 src/common/buildcraft/api/gates/TriggerParameter.java create mode 100644 src/common/buildcraft/api/inventory/ISecuredInventory.java create mode 100644 src/common/buildcraft/api/inventory/ISelectiveInventory.java create mode 100644 src/common/buildcraft/api/inventory/ISpecialInventory.java create mode 100644 src/common/buildcraft/api/liquids/ILiquid.java create mode 100644 src/common/buildcraft/api/liquids/ILiquidTank.java create mode 100644 src/common/buildcraft/api/liquids/ITankContainer.java create mode 100644 src/common/buildcraft/api/liquids/LiquidData.java create mode 100644 src/common/buildcraft/api/liquids/LiquidDictionary.java create mode 100644 src/common/buildcraft/api/liquids/LiquidManager.java create mode 100644 src/common/buildcraft/api/liquids/LiquidStack.java create mode 100644 src/common/buildcraft/api/liquids/LiquidTank.java create mode 100644 src/common/buildcraft/api/power/IPowerProvider.java create mode 100644 src/common/buildcraft/api/power/IPowerReceptor.java create mode 100644 src/common/buildcraft/api/power/PowerFramework.java create mode 100644 src/common/buildcraft/api/power/PowerProvider.java create mode 100644 src/common/buildcraft/api/recipes/AssemblyRecipe.java create mode 100644 src/common/buildcraft/api/recipes/RefineryRecipe.java create mode 100644 src/common/buildcraft/api/tools/IToolPipette.java create mode 100644 src/common/buildcraft/api/tools/IToolWrench.java create mode 100644 src/common/buildcraft/api/transport/IExtractionHandler.java create mode 100644 src/common/buildcraft/api/transport/IPassiveItemContribution.java create mode 100644 src/common/buildcraft/api/transport/IPipe.java create mode 100644 src/common/buildcraft/api/transport/IPipeConnection.java create mode 100644 src/common/buildcraft/api/transport/IPipeEntry.java create mode 100644 src/common/buildcraft/api/transport/IPipeTile.java create mode 100644 src/common/buildcraft/api/transport/IPipedItem.java create mode 100644 src/common/buildcraft/api/transport/PipeManager.java create mode 100644 src/common/dan200/computer/api/IComputerAccess.java create mode 100644 src/common/dan200/computer/api/IPeripheral.java create mode 100644 src/common/dan200/turtle/api/ITurtleAccess.java create mode 100644 src/common/dan200/turtle/api/ITurtleCommandHandler.java create mode 100644 src/common/dan200/turtle/api/ITurtlePeripheral.java create mode 100644 src/common/dan200/turtle/api/ITurtleUpgrade.java create mode 100644 src/common/dan200/turtle/api/TurtleAPI.java create mode 100644 src/common/dan200/turtle/api/TurtleSide.java create mode 100644 src/common/dan200/turtle/api/TurtleUpgradeType.java create mode 100644 src/common/dan200/turtle/api/TurtleVerb.java create mode 100644 src/common/ic2/api/BaseSeed.java create mode 100644 src/common/ic2/api/CropCard.java create mode 100644 src/common/ic2/api/Crops.java create mode 100644 src/common/ic2/api/Direction.java create mode 100644 src/common/ic2/api/ElectricItem.java create mode 100644 src/common/ic2/api/EnergyNet.java create mode 100644 src/common/ic2/api/ExplosionWhitelist.java create mode 100644 src/common/ic2/api/IBoxable.java create mode 100644 src/common/ic2/api/IElectricItem.java create mode 100644 src/common/ic2/api/IEnergyAcceptor.java create mode 100644 src/common/ic2/api/IEnergyConductor.java create mode 100644 src/common/ic2/api/IEnergyEmitter.java create mode 100644 src/common/ic2/api/IEnergySink.java create mode 100644 src/common/ic2/api/IEnergySource.java create mode 100644 src/common/ic2/api/IEnergyStorage.java create mode 100644 src/common/ic2/api/IEnergyTile.java create mode 100644 src/common/ic2/api/IMetalArmor.java create mode 100644 src/common/ic2/api/INetworkClientTileEntityEventListener.java create mode 100644 src/common/ic2/api/INetworkDataProvider.java create mode 100644 src/common/ic2/api/INetworkItemEventListener.java create mode 100644 src/common/ic2/api/INetworkTileEntityEventListener.java create mode 100644 src/common/ic2/api/INetworkUpdateListener.java create mode 100644 src/common/ic2/api/IPaintableBlock.java create mode 100644 src/common/ic2/api/IReactor.java create mode 100644 src/common/ic2/api/IReactorChamber.java create mode 100644 src/common/ic2/api/IReactorComponent.java create mode 100644 src/common/ic2/api/ITerraformingBP.java create mode 100644 src/common/ic2/api/IWrenchable.java create mode 100644 src/common/ic2/api/Ic2Recipes.java create mode 100644 src/common/ic2/api/Items.java create mode 100644 src/common/ic2/api/NetworkHelper.java create mode 100644 src/common/ic2/api/TECrop.java create mode 100644 src/common/railcraft/common/api/carts/CartBase.java create mode 100644 src/common/railcraft/common/api/carts/CartTools.java create mode 100644 src/common/railcraft/common/api/carts/ICartRenderInterface.java create mode 100644 src/common/railcraft/common/api/carts/IEnergyTransfer.java create mode 100644 src/common/railcraft/common/api/carts/IItemTransfer.java create mode 100644 src/common/railcraft/common/api/carts/ILinkableCart.java create mode 100644 src/common/railcraft/common/api/carts/ILinkageManager.java create mode 100644 src/common/railcraft/common/api/carts/ILiquidTransfer.java create mode 100644 src/common/railcraft/common/api/carts/IMinecart.java create mode 100644 src/common/railcraft/common/api/carts/TransferCartBase.java create mode 100644 src/common/railcraft/common/api/carts/bore/IBoreHead.java create mode 100644 src/common/railcraft/common/api/carts/bore/IMineable.java create mode 100644 src/common/railcraft/common/api/core/INetworkedObject.java create mode 100644 src/common/railcraft/common/api/core/IPostConnection.java create mode 100644 src/common/railcraft/common/api/core/WorldCoordinate.java create mode 100644 src/common/railcraft/common/api/core/items/BallastRegistry.java create mode 100644 src/common/railcraft/common/api/core/items/EnumItemType.java create mode 100644 src/common/railcraft/common/api/core/items/ICrowbar.java create mode 100644 src/common/railcraft/common/api/core/items/IMinecartItem.java create mode 100644 src/common/railcraft/common/api/core/items/ITrackItem.java create mode 100644 src/common/railcraft/common/api/core/items/ItemRegistry.java create mode 100644 src/common/railcraft/common/api/crafting/IBlastFurnaceCraftingManager.java create mode 100644 src/common/railcraft/common/api/crafting/IBlastFurnaceRecipe.java create mode 100644 src/common/railcraft/common/api/crafting/ICokeOvenCraftingManager.java create mode 100644 src/common/railcraft/common/api/crafting/ICokeOvenRecipe.java create mode 100644 src/common/railcraft/common/api/crafting/IRockCrusherCraftingManager.java create mode 100644 src/common/railcraft/common/api/crafting/IRockCrusherRecipe.java create mode 100644 src/common/railcraft/common/api/crafting/IRollingMachineCraftingManager.java create mode 100644 src/common/railcraft/common/api/crafting/RailcraftCraftingManager.java create mode 100644 src/common/railcraft/common/api/signals/EnumSignalAspect.java create mode 100644 src/common/railcraft/common/api/signals/IBlockSignal.java create mode 100644 src/common/railcraft/common/api/signals/ISignalController.java create mode 100644 src/common/railcraft/common/api/signals/ISignalReceiver.java create mode 100644 src/common/railcraft/common/api/signals/SignalTools.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackCustomPlaced.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackCustomShape.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackEmitter.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackInstance.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackLockdown.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackPowered.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackReversable.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackSwitch.java create mode 100644 src/common/railcraft/common/api/tracks/ITrackTile.java create mode 100644 src/common/railcraft/common/api/tracks/RailTools.java create mode 100644 src/common/railcraft/common/api/tracks/TrackInstanceBase.java create mode 100644 src/common/railcraft/common/api/tracks/TrackRegistry.java create mode 100644 src/common/railcraft/common/api/tracks/TrackSpec.java create mode 100644 src/common/universalelectricity/BasicComponents.java create mode 100644 src/common/universalelectricity/Ticker.java create mode 100644 src/common/universalelectricity/UEConfig.java create mode 100644 src/common/universalelectricity/UniversalElectricity.java create mode 100644 src/common/universalelectricity/electricity/ElectricInfo.java create mode 100644 src/common/universalelectricity/electricity/ElectricityManager.java create mode 100644 src/common/universalelectricity/electricity/ElectricityNetwork.java create mode 100644 src/common/universalelectricity/electricity/ElectricityTransferData.java create mode 100644 src/common/universalelectricity/implement/IConductor.java create mode 100644 src/common/universalelectricity/implement/IConnector.java create mode 100644 src/common/universalelectricity/implement/IDisableable.java create mode 100644 src/common/universalelectricity/implement/IElectricityProducer.java create mode 100644 src/common/universalelectricity/implement/IElectricityReceiver.java create mode 100644 src/common/universalelectricity/implement/IElectricityStorage.java create mode 100644 src/common/universalelectricity/implement/IItemElectric.java create mode 100644 src/common/universalelectricity/implement/IRedstoneProvider.java create mode 100644 src/common/universalelectricity/implement/IRedstoneReceptor.java create mode 100644 src/common/universalelectricity/implement/IRotatable.java create mode 100644 src/common/universalelectricity/implement/ITier.java create mode 100644 src/common/universalelectricity/implement/IVoltage.java create mode 100644 src/common/universalelectricity/implement/UEDamageSource.java create mode 100644 src/common/universalelectricity/network/ConnectionHandler.java create mode 100644 src/common/universalelectricity/network/IPacketReceiver.java create mode 100644 src/common/universalelectricity/network/ISimpleConnectionHandler.java create mode 100644 src/common/universalelectricity/network/PacketManager.java create mode 100644 src/common/universalelectricity/network/UECommand.java create mode 100644 src/common/universalelectricity/ore/OreGenBase.java create mode 100644 src/common/universalelectricity/ore/OreGenReplace.java create mode 100644 src/common/universalelectricity/ore/OreGenReplaceStone.java create mode 100644 src/common/universalelectricity/ore/OreGenerator.java create mode 100644 src/common/universalelectricity/prefab/AdvancedTile.java create mode 100644 src/common/universalelectricity/prefab/BlockConductor.java create mode 100644 src/common/universalelectricity/prefab/BlockMachine.java create mode 100644 src/common/universalelectricity/prefab/CommonProxy.java create mode 100644 src/common/universalelectricity/prefab/ItemElectric.java create mode 100644 src/common/universalelectricity/prefab/TileEntityConductor.java create mode 100644 src/common/universalelectricity/prefab/TileEntityDisableable.java create mode 100644 src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java create mode 100644 src/common/universalelectricity/prefab/Vector2.java create mode 100644 src/common/universalelectricity/prefab/Vector3.java create mode 100644 src/common/universalelectricity/prefab/chunk/ChunkEventCaller.java create mode 100644 src/common/universalelectricity/prefab/chunk/IChunkLoadHandler.java create mode 100644 src/common/universalelectricity/prefab/potion/CustomPotion.java create mode 100644 src/common/universalelectricity/prefab/potion/CustomPotionEffect.java create mode 100644 src/common/universalelectricity/recipe/CraftingRecipe.java create mode 100644 src/common/universalelectricity/recipe/IRecipeHandler.java create mode 100644 src/common/universalelectricity/recipe/RecipeManager.java create mode 100644 src/common/universalelectricity/recipe/SmeltingRecipe.java diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..041bad22462a023fe27dd3373151ae2690559529 GIT binary patch literal 11600 zcmZX319WFk5^gxLIk9cq&V&>HV%xSkv2EM7ZQJI=eDj~(x4ZAWd(OS5@l{p#*Q#3` zCNC=v2aN>{1Ox;pDIuZ=1O!a;C(Q);?a%jU>4*vl2oujtSXf?CSeQWG-p1I>(g+Ah z4XRSzL=9EC{wg&xko5T1K}P*Sh68FM=`eWmFaOX`5^$1GkUU?=JYAA7UxK_)5+qb` z1$hAlMxeNZDf|13-@MzMUspWS6CHpLXD26RxoIU@AkF4bB&1vhP$0bmin@SOKi~BB z5TGlx9#AR)AbSDd6O`|{HYO(EpVJ0LumTA~#Z0JLU*wlQHoEr@5%<7Ab;4<#Uc_E~ zh@LP&O7(JJoX|k9qS>~VN?_o}L@7bPFhh5!py8ik*nieM>9qKS>>ucc+7# z00BWpglZBDkps;Ni^BjVg&kmv2(>{Gs11|HoWKAjWAw$s!@v~pSb{}(d`ZjobTh=B zd^F1vG49yBFKfnRjr52K#v=m-<^e0fQD?}HRVt^kb~6|WX$%MG9Pcd@^KBQ zSXm-X1nTN#O9&4qzI;{LkS9)KpNb~H`I^P9bilFBv`$O)}$wLG?5|pQjk3`g$TzFM7p>Z zw=a5*A)3A?#ZvH$cm`93{sDv(R;Ge$Yf8~Z4Xu_ih@$&beGKzP9EM7Pd*C3lP3gd0QAY; zXmbGZ0g?BV-bl7!R{2))1dcURF4s4Y;rzT%yTo8;Te zXQX!=?|^VWsX(dtv81tNsw}FIvhcD*^O!T-#c!;{jhKyWjVMkG4@hVFXYPNdpz6Z5 znW?Gstm(|kJlHJBJnFn=zMI7FVB^T7FqOEan5B5Ov`3Ol(lyyNjD~F}FnvY>`Z#tbJ8#uLVrMi(Yo`hV%8>$4d? z>hXP9_dI%pBz;3oL6eg*e4CMK&c#$C6Bv%&SVX z%vpt3C2EasO>2#R_2UYA1BHhnnj{)@S};p0%R9?Rn@{`a7UULl$7V-_r=_R6XRjx? z=cOmi`@}ofyWl(cJMKF^m>T#!xDa?a_!SHd)E#6Rlo*UQA`arl3Te~0o9b9quvWa# zg3y`Jrx3W1mXLJcd*4!DNZ@%Oxk!n~f+&cnY{Y$dMR<5vTR0wu6>=uVJ|Z)QG-5f5 z2dOOLG8#XDHX$FCU!r_6WGqEIW?UetG6^WDGzmnZE~RoQK`B$Ip4qR4U>3uKvoja<#+&kqvdbAW&8dOD84YV#wDXLeB zB#J01q=X*{@YJl-Udl;|k3ac}-!+5O2Q>~`q>{&y%F?LR8?~JTWz;66E0wG?GetLL zc>y1}-^BU__G`q_hti75j1!LFCh0YpGzc}48;@KfE+5ym8a>23lGzmA{2v>le4~=5 z+%nCy1hw+4gRTI)guFVP=AE2gP#?M<)UVla2XG_bn&DL7Sm99MxFhAoio{aIK!<(| zO%0hu7XNTg1xr~-rAaMI!DG2(=}%ElJ4}sC|DE=hvYbY*UZPH-vC&-6=-9wx@vtCQs5tPP_gqZeS1uhF zEqjJL3H$eR>KmMEt>ZykgY$(;MvIFh4+-ZD=^22$bpsc=CxRzqgp7~~@y6jhynWsv zk1e+{*CMy5OSE37I0~sW*p?tLC$9ppuBjz&-FJXb?owNYcTX1ckkgp#v(+UFFqEz(~r+xhO8{ z<@T3`Y?G#wE#u_!A=@8FhI@{cCg6)}MK=}Q6_FKB;V|>6B#R}B$ztH!AfCCxk)igsg8S& zi%p$omeU{8PE+ad<2!!7fX~B3qUE89Ca#R7j6EsSDR*Kl(l4nvD4QtTXc1|pRoRua z>XfShJW`MCWpOnzw3=-Pe~-;5=a)}DFg;*ktzgwv`B}^^^JzY{@j3V3i7m@Kq(3x^ zSSM~7cV(_ZvJSD+v4XS7u(z`#G^;f@HkvnXbrE|UE2irLMzxmOIWHG3OE1@Pp>W4D zkuoEmK&~boFR$HKFPC`Tw?97xqK&5eA;=KgJRUr_@yz)xJqlh*3gtShPixQihrAO% z*X5M5Ht^(eO>va4E%D|s&2hJQH~8|n?XOE`=OOZs@}sj?d9d*u@I3ggIQc#{o?hM~ zW-xTf^~u<@$-4VG#xe|3Xwvpl%Uo%1+w?S?Uazq8**|P>x4SZKQ(ri+Ion_89(Z@X zW^ukWFFW=;*ZoKPW0)v*V-KPA39y#XFwrmmB{ zDZWlLngCfEP=Hmn$@kHhdSe-{N|#M1FKc3FlxFn~(%Qw>@w?^n%bLqeNTSr1-?Y9$ zRW;rGK-+YLZn4}z6T&0x;F~(Fv+$rV8$pQh{#pd;C&ZrkPN5gnr-N>qGI34_>ZKLzOzX_x<B#?X* z%1S?tR*Z#>uTzsyFH!RT^ixJ#cq}t9XEEBVZNB4s=|FUU ze0l>92n^?J_JR<~k2so&uei<4-t<7WgPs}sNq8P4m(-p-rlhUBw-h|jfIS5qg*2cn z#wj6KkeuV!{;=acOU81#P}AtWExS+uo|*cgZm?P{H<9_C@SE0!)8=r&{?oqK9qErNeeRh!>lv~|q+w;R(RAAiHMpwH0s^~d=aj4P zY0-Y=$a-sJqfF)GlSUhW`+CEy-K#mbvnju>{z6+%)%Yp*t(P|nLCJ&DeHl-dAM3*7 zrltLBE56AuxOXpiM6VyIZ)CohH2-s2X^6pKf1h>QK>I{Sm)t$}q43V!n#o4W!u;qV z%&hV>+GcEC&!}L(+%RI?1QWnaSeRkW^PHck)q+ql%S^779Ljw<^Dftt;4?qx`EHwM)FCdRhAk z^X14~e`+&}IvBv1NaIt-Ic3PiT`II2Jet9uMy1NGPNmY7R^3|rUCH8!c{uXQJi1>* zZ0ejiMXnrf9?$Q4tXD65>H1pacp_TO=-0E#b#?=0DZU zG;h?~)~PC0-DRrVYV5#^yV|*AJib74?i*PJ86> z9=&pygEp`Hx|q%%>BFb}TkWlZuR*e%wHC#P(iXoiFst92f`$r$HVAKkME9@;rX}K8 zfQqw>^^7mgeof6EG?R!I_XD~gW=OV3*h`rpoOKDa(1wy-Vs7 z*^j8#UyD=7tdEgMM8SX&xHfz51Nks6R?&FQpQ&cT|Dt6>_(dgXJbX}UbWEEHt4wWC zuu;f~9Zoh9Bh5&os~xSecI_uuWE-cu->cZSykJ&wF9`bv7s<|OC| zi!8}Km)Q+<8t>KM5#Ihm~X_~-=OC^PS%>|scUR~+AXpZoH8wMU0g%8s}`@ePvh=s<0SSTJFj(S8}G)z+{KpS8rN2E zEA_1P+U};?^Hyus8KV4U0DR+Ischx7n6ml@+T$_r6pkf8ELUl!3%VAEeTe$2b7{c8~#yTm$vU!ujF? z1Chf4;a5Y{nDP1wMSXmH`T}8c*&!Tm+BdP_C{ zCMn=9;f)EEDR9?|XZkHzS8xUBF({f?eG9T93Ry@!A6cHY#Eu28G7Mf=HBU!3g&|2o zY$-CR#(l-m5(7SFh=nC z$FazAupyTltnV&RKTSUOK0!Rxyq2-kkr=v6lC=uN()T7)XBrQr5DIbTVz^@-Rjy`` zCs;YoYW8f@ZMjbfkRboA_Jp7sA^ISj@Pp9caP@F$Nkoz)l5EM%SU&Q2l5@&p!fB%J zf*Xli7obaHs3as+ArdRSv%1NZku1(&xCnt9&hp#xzKrOr$2Z2V4pcB2 z(&*HJ7Dm|EfH*Bbuk?Oya{v0eh<1y-b+@NCJcle6kHe?d3;qLTQJkC4Q|gQ36Cau! zT3g-~hJzm`Sfk{g2fk3Pv{IaHgeqiL?tNDQ!eP51ZgInk(2A8&l{oYxF;f?#kKCha zzqzg@KMi-CYkSlq70VsoriWECs?%CXetLX{dw$$Mz%)Oy&NeJGUtY$X?Oijvsm;o9 zQ}A^#rLog}>OU{GE*Eb{bv$XPy$#$SjDoi4z+5``~Y1m zeO%3rrF<(nC0+w?TmFH84Ujx-g`xX5aWPO;kqC_!Bt034|f;O<&70< z6tD^EcS-JxIlzntjyB|j!S%UuVYPAm*$`Y_fxn>y%ZlL+!IKFW@fnLBNs=&YnM~@% z8+uH5`vyej$IfT{=2hik_iGOqk2XnSkDm6=j`C65DcTv;5)}H@htr2IdKG>Y{t|&L z5h}qXxm(D{(pFPIA=wa@4M$g)1HhY=0+_Vfe7dc0K4uRG3 zJq^nYlRCX5JuU5$U9PT0ch#cNu;0qU62re^9vVlE8;uL2CBx;?_U$aUj(qj^C|}oy zf_A``5Z`B4kazP31c)&xyZ@?Cf>36kzJy6XH!)w#DzQwSejfecj{(L30QmuqXBI_T zf~)J1M2|x7LRUkHqvg;ojid9cGb2nn9k6h4aqf{(NQQcWT&+D!;a{ zO^J!x7SwbqEh=r9*XX-;CsrFEn0=fnQ;n(VvY!KsNznGBNv#0s%;t%y8Wm7n(w zaGsF4@Dk#8s$i~M1O{wNF!A2S8?bOBqbMm+r@W?^u^%99Xq{oR!-o1pwa6>PE0P)T zRUpyBA^YN`EG1(ldIjirzlK7O;48mf^7`ZM@@heM5_pjZkoQ9y(8a^fqZlK@_!R~( z`aYlmc)0Q3fQBVyZRkL)CGpU+;I<^Yj6Z*Z==rO(9|Um(*7jKt>4(4{EZCRssT4=6{~2vBAHnSS@cG#n=oOYucRYO_?%UIxUfH zOsxve+V!pW7j92Ze4OI>OlQAExeE?JUYm58dlv#L`HB0N3RCr0^b3lhaPoxHw{f#^ zZ9VNA7nB`56B|&bm)RF%?lF4eqz z--O;An~D%y^kQ{x%y*Ji4L*~>(x{5q=J0~?;jXo-=ge2WpPJcBfM1*ns+xOiLYV1v z!4u_6I?Kl8U_W5%yK_8HpK2NWeHlhwZApHtBQ9stDU&MNDV-W{9PKUO!_)EnQa_sf zTv%64-X-e8{@V4re^)noH=fv&n7Ej-7?hpG53vlpe6|F2j&x3pO@%#(t;0UaPR+*N zl+jf6DfD6g=46Du=DgMQBh06u8(Fbh1U_^Lh>~B{%Eku+9LNRQx3c5%GBW(~vQmm< z)fHU8}bgovmf6zccJg!`Sl2%5JdIYXkmevkjuDnEl z5nO-L{}j^`5&VTXTJRF7$;cB3+t?csu+lNoF%j`W6A%#a*c%#iDT;{wTl`Osm&nx7 z(Uyyz-o?d*&V`xI#@>XUk&}~?o`H#;iHY_Pg4V&!+ELGy*4lyiUrPS39uXr41A8-D zM>891f`9bt>DxFt@)8mKW9UE6zuIZ!YW81C)(-#f)}Id2|5HQHNXJ0`AKiaMdHyNo zk~ecTvQ!f>vof-F_+x{QnSp`lFaH0l`LD(QkyQV$B{NA?bsndAMK>6cL{u1xdRRyS za5SZmMHK-?B@f1&mGF#6ByfiZ;YWl7IS4w4z`Mf-fr2-b2;NhJHsZF6fduv^s1ed& zpwz&SB5Q0fP#HfovT-=S^3-`yl5>)ibD6en#ZgoqsIxAXRrbNatMH7|zm-qcU5C{js*&#QBj_zR zN+lg)&49^Q485 zq!GqCU2{C3#9fCmeg@5i&5vr5t5)TpfB>N;SUNT2{6L#4QdqEC^A&EOOH4WlaUwU` z>NT^TYWi(P+UndE#WPCss`niq6pZc{Gf44r<*`%9hqF45=sNV6-iG@nYe2#9it&a; z^FX|^Mjg&ws`;#m`wlU|H>21ZqL)sI_;g|H!r<)I(^81r6)ki_ycLD zX|8(J`3o(luqRBHEn{|i3NS@L%^^FZG@$8{o%aZkH*4-j3(vg+~ukE^Yhucue9Mra&iW=biXV7NYL8`7>=s$Mes`-*hTNJ^U!cfRB!otFei%p7k zzHZ(_{Cuz5X^Z~B>LQMa?c5II`xv{qy+j%eN9jGJTp)ul&7$}`>>RGX#LHIl1Z^gy zq^F}`&}sI}F?+ElX$DEMLSll!f~-RFyq@IeX;j)bdsr9NxIZuYxT2L8lt?e>(I(5f zvsX|e094w<@(I84L}e!a*kXXJzy*15$E9K`Ey}b%dz7@@!av?B95`e{d_AM2xY=tU zv;G6Z1X}_J_M}P4qX}0~?L`34-&Qz_v4TK;n@zj0O2g6Dxg^Lb07mui>sK#h#W+o{Bn9i~LBjPKltA(hhr4_jVno5E*yn3{{ zC207Lz`PC+x|R=|6M_A!H--Qx;1;xu(mv=Aup~^Shv+jthL;jZ?qj>~;+8~>E;hAa zZxrViNIInI65+236`@)EBO;i2gSs=WUC^@XQY1Z~(s{fp!a_O4m*kQ0Lc`eiTN@zh zY40m4&Ca|3ZD);9VYTj#z?NQ0n|hF1zm+9>^huVK!d;oMsSRc_x`f5u*+lO^IK>!3 zr_}>F6*jD==oMbU%nE*1t(QY%$Q29gIHI$RR%+}=S)kziCQLVJxHW6N>AX4`%wjad z(fvHEAfxQes0GAe@DMLy_EXbGxv5eJKvx-if6wn_Tl732tU*x&5w)RrG`NP^3&QqQ zg2(o-S=dkHn<@j8-7C?7)Ar)9XltY3kO_OYmnuw!y#=Z(522i95KsY_^+gBChCh-T zC1Q{|Ao(%OF!yDyKmg zPL7^G_ForhB&|TJ%8$h2Xs#J7A1nuf*fN5XF*!tEa(q+wXu;71HxNC&cl|EjDA_43 zUfihI7VhfXnVsX@^3lmaiwOq2;%BXN2!e}V<)r}S_Wn^nEs}6i?9xe+=G@dnC1Cfu za^I}b!M7UT8{)GK|8WOP1d+erW1T7R5hSG>L~Nx(;&+Iq{cIm_cF z!b^WachoSadD&B4{{nZ(W)Z?dX|X`WRNz$r^wmi*{F?_Rus(WsMO{6lO0eaa#(9?E zze~u`*>|i$@I^Qht~stnvepD!>ty7P<19VlLlN(lBa)il0QTN?q4b2!w4wV>@xlkk zjD2yo{iMUpKvYXcyZCosP)sSnVtBgy+yvXvquSNubr+2`;+*zpP1szO)vsxZ)9%;9 z3>VE<8-^y1%(!ejjZO9GZv2gUw^?s`Q{o4|wtb%YbE$LwbN$y&888iV}u zczt}gMtnZBo9heL&f*tnh3q`%D#gf6<@hg)lxupONamhWE9o1EQ04d#7l^SkaGjWotMpO+g1`cpwAcz3 zidbA5Nq-}cxB9z{Su=u2$%0c?05n&7E^gmY)zX6d(5P4LX~B~}p3z{`b!sY4m2fS| z14tQc6yTb)Kj_y%qeg8iWvw#h3qB-_J3E_1HHRSXpIKo$w{e|8Lo~71c^>A!eb;Q! zSXjrk^z*=gu9+GdsMi`@wy72yWsGpS)_|CXYP!^9G;B_7QeJi683ElD#$1x;UxzZscgjFMPJSRI zO}x+I$aS=T6z5&h1Q}iHJmWHItP}2!8+jA?R36)N(ku|qOt^K$g6f^!G1tk2FTPaT z^nr9>#R6(vu<00c+(EhuCC z3(FY{8C>=%C=3r1szjWI9nujRIioeGVC+&&r8Gj==y^wI&id`@b+;#&5NSsF&YJ-x zL0f72PuH%8SZVP-=MVe4Y$BuW&Bt%h;6mn4i}Yc)iQAB=6INX0bT(Y;QR3h%D8+o7 zG|+TDIO7-?!(XZu=+!|+Z*UC^U9Wb2J!6!OZ+ac*4GoR6xT*vXeQ>;#$aI42Nyud}hu3rx{>nTm8j+^nNw@L$SbAJh3-|w_Jytu}mM=?bl~t<+UQL7XjrN`} zQsuZEeRqn>mbT?P-rpU02c3vORjvQkfMa9rREM(#40jFV(-p6aA=mr%M z&3=4Iz8RY5=st$(ejU;dM&sZZDdM*?aP9gAsB)JxmpV;w9gJ(sRfA%a{7ho zC^lcXPs(B31U%JKMt+{^BA5!y$xZA(LHp~zBGPJZjt^WMgOe1s6LE*TJ2jiO*~QGg z-j{8dpu0b(*Th3<=4HqA8sQ2AZ_}1c7xDT2W9Xy8SR_jmtS5{3ZOczj=rkCVugvyV z9+msSQ~u}^MF+e|s7tzqB!&dtRtxsPf1T7`h>)}qi9OJyE3XSS=8S(yXhnjwfq-iY z?1Cg!!$WV}iwwOCYB*}DucoKm2}emIyMa~4Q@vvo@%E-Dho!X!v|RZQ6YYshj*Ji0 zW(sP;sr0t7+Ijsq!U z*L>nx$JA}Oof@-))4fhggvkDN+|V!=JDcl0YB^}z?%et~+4!AnJ3ShjkHoP(!?75@ za3|5L!%b2go9Ih9Xm1{lx51NCN`O1D&A6w|Cb(gH+Z=fP4Z%6atGzNoT7_`t%WGe< zg?)nBK5jm3IOA;1AJ#XMzEy-JL1vsS26{qB>?ZvKE2Yq;X93w0}jD(i81Uoq0zU1EReLfC~4}8Gr zM3IkkSS3vj9j)4UzbD5UXorEXhjnNl!A>C@AwhN|Npz=~9zW2BPfvRa+bb@QpTPKj z)Qca?W;DFU-;JE3R+Y`VkNd1X_9?0018yMhDtvYoQMoQ=v0gAN}qZ5%^0(5&Kf2&Y^3{f@bt zu;o=Pwl@u|yU=}{W9(>$jMH_(j~5f(e2!|C47bSfte0(kiQ;~%^@}5&oHkv{(PW)5 zv^l$ry~~At^?kwO$dK0OnIPMx-_gl(5yNhUvsat#s=p#5{RY0?l6AZfZ6v9aMXRp6 zvsDOS^x zuKOo>zF0B}2?oW(1+^P!`uEk`Hgi@E535g}_oO{uDpk3aJZ#gBLD7<6e$be2D?$yi z|6R8Ifk2LGCV$*+=s(nVovwejtEKWyRAyQk{5Eu98{c4q&-;>3#M~yZZ6@luBz4k1 z8=CcgE&T#<=Rdqs(a<^?;S<7q>0*B}d->$u>wmc7LwwrL~`;!3?qbcvF#&ayKEJPybE`|s&5OeQKN z0&%`eTyE!yfEo8n#mZ1~*7sWF+6Kc4Jk-!XO+SIW8Bg|hip?_V`ydq1D?ET#ttwPJ zC2y-CYM$zF@|ie5OA71%IAQ{@p`psM9Bo4?MTJuw4Ut-^{ZwmbDx#!ng?St^RlnmDEuvCO4` zfq{8`?uXZN;&Om{Y^vj5^|tenI9!e=sfUM$>~Sh8;cjI;M6uvc3(Z-sb`dKtGzWaJ8W&4qSAIK>QMxzXoAGmME>$U4&OxOnZryX! zPW6e}m%uj@Rr)b+uDvU--;qhypF_KcVl4P1cpMY#%{_5h2Ff=lp2Fv3%>>r~JI>Lc zQ@@LG!mL#|*ni1%W2inT96fHE&Oga1K|KGQEhWBQc%xz`iF5;NW?*({Dsn=-MMbZz zQb;~~IQo+%I}t-BtGuiIo(P)cS<+42?3T;P9ZiLAI3CvEecYa^>TJk0?&Z=^Im(*{ zC#*h$Djw0=%&bCnjwsS3!4Rhlww&cg(XEC$`8ZCqp*75Id(P`9_eX$tdXz~dmP9#o zrrt;d*VqXE%mP-V7%uc9)`2Lf&bRXz>I&j_= Block.blocksList.length + BuildCraftAPI.LAST_ORIGINAL_ITEM) { + sig.itemClassName = item.getClass().getSimpleName(); + } + + sig.itemName = item.getItemNameIS(new ItemStack(item)); + + return sig; + } + + public static BlockSignature getBlockSignature(Block block) { + return BlueprintManager.blockBptProps[0].getSignature(block); + } + + static { + // Initialize defaults for block properties. + for (int i = 0; i < BlueprintManager.blockBptProps.length; ++i) { + new BptBlock(i); + } + } +} diff --git a/src/common/buildcraft/api/blueprints/BptBlock.java b/src/common/buildcraft/api/blueprints/BptBlock.java new file mode 100644 index 000000000..a97003fdf --- /dev/null +++ b/src/common/buildcraft/api/blueprints/BptBlock.java @@ -0,0 +1,266 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.blueprints; + +import java.util.ArrayList; +import java.util.LinkedList; + +import buildcraft.api.core.BuildCraftAPI; + +import net.minecraft.src.Block; +import net.minecraft.src.BlockContainer; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntity; + +/** + * This class allow to specify specific behavior for blocks stored in + * blueprints: + * + * - what items needs to be used to create that block - how the block has to be + * built on the world - how to rotate the block - what extra data to store / + * load in the blueprint + * + * Default implementations of this can be seen in the package + * buildcraft.api.bptblocks. The class BptBlockUtils provide + * some additional utilities. + * + * Blueprints perform "id translation" in case the block ids between a blueprint + * and the world installation are different. In order to translate block ids, + * blocks needs to be uniquely identified. By default, this identification is + * done by: + * + * - the block simple class name - the tile simple class name (if any) - the + * block name + * + * In certain circumstances, the above is not enough (e.g. if several blocks + * share the same class and the same name, with no tile). In this case, + * additional data may be provided by children of this class: + * + * - mod name - custom signature + * + * At blueprint load time, BuildCraft will check that each block id of the + * blueprint corresponds to the block id in the installation. If not, it will + * perform a search through the block list, and upon matching signature, it will + * translate all blocks ids of the blueprint to the installation ones. If no + * such block id is found, BuildCraft will assume that the block is not + * installed and will not load the blueprint. + */ +public class BptBlock { + + public final int blockId; + + public BptBlock(int blockId) { + this.blockId = blockId; + + BlueprintManager.blockBptProps[blockId] = this; + } + + /** + * Returns the requirements needed to build this block. When the + * requirements are met, they will be removed all at once from the builder, + * before calling buildBlock. + */ + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + if (slot.blockId != 0) { + if (slot.storedRequirements.size() != 0) { + requirements.addAll(slot.storedRequirements); + } else { + requirements.add(new ItemStack(slot.blockId, 1, slot.meta)); + } + } + } + + /** + * This is called each time an item matches a reqquirement, that is: (req id + * == stack id) for damageable items (req id == stack id && req dmg == stack + * dmg) for other items by default, it will increase damage of damageable + * items by the amount of damage of the requirement, and remove the intended + * amount of non damageable item. + * + * Client may override this behavior for default items. Note that this + * subprogram may be called twice with the same parameters, once with a copy + * of requirements and stack to check if the entire requirements can be + * fullfilled, and once with the real inventory. Implementer is responsible + * for updating req (with the remaining requirements if any) and stack + * (after usage) + * + * returns: what was used (similer to req, but created from stack, so that any NBT based differences are drawn from the correct source) + */ + public ItemStack useItem(BptSlotInfo slot, IBptContext context, ItemStack req, ItemStack stack) { + ItemStack result = stack.copy(); + if (stack.isItemStackDamageable()) { + if (req.getItemDamage() + stack.getItemDamage() <= stack.getMaxDamage()) { + stack.setItemDamage(req.getItemDamage() + stack.getItemDamage()); + result.setItemDamage(req.getItemDamage()); + req.stackSize = 0; + } + + if (stack.getItemDamage() >= stack.getMaxDamage()) { + stack.stackSize = 0; + } + } else { + if (stack.stackSize >= req.stackSize) { + result.stackSize = req.stackSize; + stack.stackSize -= req.stackSize; + req.stackSize = 0; + } else { + req.stackSize -= stack.stackSize; + stack.stackSize = 0; + } + } + + if (stack.stackSize == 0 && stack.getItem().getContainerItem() != null) { + Item container = stack.getItem().getContainerItem(); + + stack.itemID = container.shiftedIndex; + stack.stackSize = 1; + stack.setItemDamage(0); + } + return result; + } + + /** + * Return true if the block on the world correspond to the block stored in + * the blueprint at the location given by the slot. By default, this + * subprogram is permissive and doesn't take into account metadata. + * + * Added metadata sensitivity //Krapht + */ + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z) + && slot.meta == context.world().getBlockMetadata(slot.x, slot.y, slot.z); + } + + /** + * Perform a 90 degree rotation to the slot. + */ + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + + } + + /** + * Places the block in the world, at the location specified in the slot. + */ + public void buildBlock(BptSlotInfo slot, IBptContext context) { + // Meta needs to be specified twice, depending on the block behavior + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, slot.blockId, slot.meta); + context.world().setBlockMetadataWithNotify(slot.x, slot.y, slot.z, slot.meta); + + if (Block.blocksList[slot.blockId] instanceof BlockContainer) { + TileEntity tile = context.world().getBlockTileEntity(slot.x, slot.y, slot.z); + + slot.cpt.setInteger("x", slot.x); + slot.cpt.setInteger("y", slot.y); + slot.cpt.setInteger("z", slot.z); + + if (tile != null) { + tile.readFromNBT(slot.cpt); + } + } + } + + /** + * Return true if the block should not be placed to the world. Requirements + * will not be asked on such a block, and building will not be called. + */ + public boolean ignoreBuilding(BptSlotInfo slot) { + return false; + } + + /** + * Initializes a slot from the blueprint according to an objet placed on {x, + * y, z} on the world. This typically means adding entries in slot.cpt. Note + * that "id" and "meta" will be set automatically, corresponding to the + * block id and meta. + * + * By default, if the block is a BlockContainer, tile information will be to + * save / load the block. + */ + public void initializeFromWorld(BptSlotInfo slot, IBptContext context, int x, int y, int z) { + if (Block.blocksList[slot.blockId] instanceof BlockContainer) { + TileEntity tile = context.world().getBlockTileEntity(x, y, z); + + if (tile != null) { + tile.writeToNBT(slot.cpt); + } + } + + if (Block.blocksList[slot.blockId] != null) { + ArrayList req = Block.blocksList[slot.blockId].getBlockDropped(context.world(), x, y, z, context.world() + .getBlockMetadata(x, y, z), 0); + + if (req != null) { + slot.storedRequirements.addAll(req); + } + } + } + + /** + * Called on a block when the blueprint has finished to place all the + * blocks. This may be useful to adjust variable depending on surrounding + * blocks that may not be there already at initial building. + */ + public void postProcessing(BptSlotInfo slot, IBptContext context) { + + } + + /** + * By default, block class name, block tile name and block name are used to + * define block signature. Overriding this subprogram may allow to replace + * some of these with stars, specify the mod that this block kind is coming + * from or add custom data to the signature. + */ + public BlockSignature getSignature(Block block) { + BlockSignature sig = new BlockSignature(); + + if (block.blockID > BuildCraftAPI.LAST_ORIGINAL_BLOCK) { + sig.blockClassName = block.getClass().getSimpleName(); + + if (block instanceof BlockContainer) { + //TODO: Try to see if we can get a world instance to call with instead of null + TileEntity tile = ((BlockContainer) block).createNewTileEntity(null); + + if (tile != null) { + sig.tileClassName = tile.getClass().getSimpleName(); + } + } + } + + sig.blockName = block.getBlockName(); + sig.replaceNullWithStar(); + + return sig; + } + + /** + * By default, block name, block and tile classes, mod name and custom + * signature are matched to verify if a blueprint block corresponds to the + * installation block - except for the default blocks which don't check for + * classes. For any value, * means match with anything. For compatibilty and + * evolution reasons, mods may want to write a different policy, allowing to + * migrate one format to the other. + */ + public boolean match(Block block, BlockSignature sig) { + if (block == null) { + return false; + } + + BlockSignature inst = BlueprintManager.getBlockSignature(block); + + return starMatch(sig.blockName, inst.blockName) && starMatch(sig.blockClassName, inst.blockClassName) + && starMatch(sig.tileClassName, inst.tileClassName) && starMatch(sig.customField, inst.customField) + && starMatch(sig.mod, inst.mod); + } + + private boolean starMatch(String s1, String s2) { + return s1.equals("*") || s2.equals("*") || s1.equals(s2); + } +} diff --git a/src/common/buildcraft/api/blueprints/BptBlockUtils.java b/src/common/buildcraft/api/blueprints/BptBlockUtils.java new file mode 100644 index 000000000..57b5f63ed --- /dev/null +++ b/src/common/buildcraft/api/blueprints/BptBlockUtils.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.blueprints; + +import java.util.LinkedList; + + +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.NBTTagList; + +public class BptBlockUtils { + + public static void requestInventoryContents(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + ItemStack[] stacks = getItemStacks(slot, context); + + for (ItemStack stack : stacks) { + if (stack != null) { + requirements.add(stack); + } + } + } + + public static void initializeInventoryContents(BptSlotInfo slot, IBptContext context, IInventory inventory) { + ItemStack[] stacks = new ItemStack[inventory.getSizeInventory()]; + + for (int i = 0; i < inventory.getSizeInventory(); ++i) { + stacks[i] = inventory.getStackInSlot(i); + } + + setItemStacks(slot, context, stacks); + } + + public static void buildInventoryContents(BptSlotInfo slot, IBptContext context, IInventory inventory) { + ItemStack[] stacks = getItemStacks(slot, context); + + for (int i = 0; i < stacks.length; ++i) { + inventory.setInventorySlotContents(i, stacks[i]); + } + } + + public static ItemStack[] getItemStacks(BptSlotInfo slot, IBptContext context) { + NBTTagList list = (NBTTagList) slot.cpt.getTag("inv"); + + if (list == null) { + return new ItemStack[0]; + } + + ItemStack stacks[] = new ItemStack[list.tagCount()]; + + for (int i = 0; i < list.tagCount(); ++i) { + ItemStack stack = ItemStack.loadItemStackFromNBT((NBTTagCompound) list.tagAt(i)); + + if (stack != null && stack.itemID != 0 && stack.stackSize > 0) { + stacks[i] = context.mapItemStack(stack); + } + } + + return stacks; + } + + public static void setItemStacks(BptSlotInfo slot, IBptContext context, ItemStack[] stacks) { + NBTTagList nbttaglist = new NBTTagList(); + + for (int i = 0; i < stacks.length; ++i) { + NBTTagCompound cpt = new NBTTagCompound(); + nbttaglist.appendTag(cpt); + ItemStack stack = stacks[i]; + + if (stack != null && stack.stackSize != 0) { + stack.writeToNBT(cpt); + context.storeId(stack.itemID); + } + } + + slot.cpt.setTag("inv", nbttaglist); + } + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/blueprints/BptSlotInfo.java b/src/common/buildcraft/api/blueprints/BptSlotInfo.java new file mode 100644 index 000000000..fea06b76d --- /dev/null +++ b/src/common/buildcraft/api/blueprints/BptSlotInfo.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.blueprints; + +import java.util.LinkedList; + +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; + +/** + * This class records a slot, either from a blueprint or from a block placed in + * the world. + */ +public class BptSlotInfo { + + public int blockId = 0; + public int meta = 0; + public int x; + public int y; + public int z; + + /** + * This field contains requirements for a given block when stored in the + * blueprint. Modders can either rely on this list or compute their own int + * BptBlock. + */ + public LinkedList storedRequirements = new LinkedList(); + + /** + * This tree contains additional data to be stored in the blueprint. By + * default, it will be initialized from BptBlock.initializeFromWorld with + * the standard readNBT function of the corresponding tile (if any) and will + * be loaded from BptBlock.buildBlock using the standard writeNBT function. + */ + public NBTTagCompound cpt = new NBTTagCompound(); + + @Override + public BptSlotInfo clone() { + BptSlotInfo obj = new BptSlotInfo(); + + obj.x = x; + obj.y = y; + obj.z = z; + obj.blockId = blockId; + obj.meta = meta; + obj.cpt = (NBTTagCompound) cpt.copy(); + + return obj; + } + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/blueprints/IBptContext.java b/src/common/buildcraft/api/blueprints/IBptContext.java new file mode 100644 index 000000000..95254e89b --- /dev/null +++ b/src/common/buildcraft/api/blueprints/IBptContext.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.blueprints; + +import buildcraft.api.core.IBox; +import buildcraft.api.core.Position; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; + +/** + * This interface provide contextual information when building or initializing + * blueprint slots. + */ +public interface IBptContext { + + /** + * If bptItemStack is an ItemStack extracted from the blueprint containing + * this mapping, this will return an item stack with the id of the current + * world + */ + public ItemStack mapItemStack(ItemStack bptItemStack); + + /** + * Blueprints may be created in a world with a given id setting, and then + * ported to a world with different ids. Heuristics are used to retreive + * these new ids automatically. This interface provide services to map ids + * from a blueprints to current ids in the world, and should be used + * whenever storing block numbers or item stacks in blueprints.. + */ + public int mapWorldId(int bptWorldId); + + /** + * This asks the id mapping to store a mapping from this Id, which may be + * either an itemId or a blockId. In effect, the blueprint will record it + * and make it available upon blueprint load. Note that block present in the + * blueprint are automatically stored upon blueprint save, so this is really + * only needed when writing ids that are e.g. in inventory stacks. + */ + public void storeId(int worldId); + + public Position rotatePositionLeft(Position pos); + + public IBox surroundingBox(); + + public World world(); +} diff --git a/src/common/buildcraft/api/blueprints/ItemSignature.java b/src/common/buildcraft/api/blueprints/ItemSignature.java new file mode 100644 index 000000000..fcc12224e --- /dev/null +++ b/src/common/buildcraft/api/blueprints/ItemSignature.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.blueprints; + +public class ItemSignature { + + public String itemClassName; + public String itemName; + + public ItemSignature(String str) { + String[] values = str.split("/"); + + itemClassName = values[1]; + itemName = values[2]; + + replaceNullWithStar(); + + } + + public ItemSignature() { + replaceNullWithStar(); + } + + @Override + public String toString() { + replaceNullWithStar(); + + return "#I/" + itemClassName + "/" + itemName; + } + + public void replaceNullWithStar() { + if (itemClassName == null) { + itemClassName = "*"; + } + + if (itemName == null) { + itemName = "*"; + } + } +} \ No newline at end of file diff --git a/src/common/buildcraft/api/bptblocks/BptBlockBed.java b/src/common/buildcraft/api/bptblocks/BptBlockBed.java new file mode 100644 index 000000000..cd304b27c --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockBed.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; + +public class BptBlockBed extends BptBlock { + + public BptBlockBed(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + if ((slot.meta & 8) == 0) { + requirements.add(new ItemStack(Item.bed)); + } + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + int orientation = (slot.meta & 7); + int others = slot.meta - orientation; + + switch (orientation) { + case 0: + slot.meta = 1 + others; + break; + case 1: + slot.meta = 2 + others; + break; + case 2: + slot.meta = 3 + others; + break; + case 3: + slot.meta = 0 + others; + break; + } + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + if ((slot.meta & 8) != 0) { + return; + } + + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, slot.blockId, slot.meta); + + int x2 = slot.x; + int z2 = slot.z; + + switch (slot.meta) { + case 0: + z2++; + break; + case 1: + x2--; + break; + case 2: + z2--; + break; + case 3: + x2++; + break; + } + + context.world().setBlockAndMetadataWithNotify(x2, slot.y, z2, slot.blockId, slot.meta + 8); + } + + @Override + public boolean ignoreBuilding(BptSlotInfo slot) { + return (slot.meta & 8) != 0; + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockCustomStack.java b/src/common/buildcraft/api/bptblocks/BptBlockCustomStack.java new file mode 100644 index 000000000..861a7cad7 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockCustomStack.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockCustomStack extends BptBlock { + + final ItemStack customStack; + + public BptBlockCustomStack(int blockId, ItemStack customStack) { + super(blockId); + + this.customStack = customStack; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(customStack.copy()); + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockDelegate.java b/src/common/buildcraft/api/bptblocks/BptBlockDelegate.java new file mode 100644 index 000000000..43bac6ae0 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockDelegate.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BlueprintManager; +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockDelegate extends BptBlock { + + final int delegateTo; + + public BptBlockDelegate(int blockId, int delegateTo) { + super(blockId); + + this.delegateTo = delegateTo; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + BptSlotInfo newSlot = slot.clone(); + slot.blockId = delegateTo; + + if (BlueprintManager.blockBptProps[delegateTo] != null) { + BlueprintManager.blockBptProps[delegateTo].addRequirements(newSlot, context, requirements); + } else { + super.addRequirements(newSlot, context, requirements); + } + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + BptSlotInfo newSlot = slot.clone(); + slot.blockId = delegateTo; + + if (BlueprintManager.blockBptProps[delegateTo] != null) { + return BlueprintManager.blockBptProps[delegateTo].isValid(newSlot, context); + } else { + return super.isValid(newSlot, context); + } + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + BptSlotInfo newSlot = slot.clone(); + slot.blockId = delegateTo; + + if (BlueprintManager.blockBptProps[delegateTo] != null) { + BlueprintManager.blockBptProps[delegateTo].rotateLeft(newSlot, context); + } else { + super.rotateLeft(newSlot, context); + } + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockDirt.java b/src/common/buildcraft/api/bptblocks/BptBlockDirt.java new file mode 100644 index 000000000..776d0ac8e --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockDirt.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.Block; +import net.minecraft.src.ItemStack; + +public class BptBlockDirt extends BptBlock { + + public BptBlockDirt(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(Block.dirt)); + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, Block.dirt.blockID, slot.meta); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + int id = context.world().getBlockId(slot.x, slot.y, slot.z); + + return id == Block.dirt.blockID || id == Block.grass.blockID || id == Block.tilledField.blockID; + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockDoor.java b/src/common/buildcraft/api/bptblocks/BptBlockDoor.java new file mode 100644 index 000000000..86283402e --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockDoor.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockDoor extends BptBlock { + + final ItemStack stack; + + public BptBlockDoor(int blockId, ItemStack stack) { + super(blockId); + + this.stack = stack; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + if ((slot.meta & 8) == 0) { + requirements.add(stack.copy()); + } + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + int orientation = (slot.meta & 3); + int others = slot.meta - orientation; + + switch (orientation) { + case 0: + slot.meta = 1 + others; + break; + case 1: + slot.meta = 2 + others; + break; + case 2: + slot.meta = 3 + others; + break; + case 3: + slot.meta = 0 + others; + break; + } + } + + @Override + public boolean ignoreBuilding(BptSlotInfo slot) { + return (slot.meta & 8) != 0; + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, slot.blockId, slot.meta); + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y + 1, slot.z, slot.blockId, slot.meta + 8); + + context.world().setBlockMetadataWithNotify(slot.x, slot.y + 1, slot.z, slot.meta + 8); + context.world().setBlockMetadataWithNotify(slot.x, slot.y, slot.z, slot.meta); + + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockIgnore.java b/src/common/buildcraft/api/bptblocks/BptBlockIgnore.java new file mode 100644 index 000000000..7d8ed01e9 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockIgnore.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockIgnore extends BptBlock { + + public BptBlockIgnore(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 0, 0)); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return true; + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + + } + + @Override + public boolean ignoreBuilding(BptSlotInfo slot) { + return true; + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockIgnoreMeta.java b/src/common/buildcraft/api/bptblocks/BptBlockIgnoreMeta.java new file mode 100644 index 000000000..abcbcc4ed --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockIgnoreMeta.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockIgnoreMeta extends BptBlock { + + public BptBlockIgnoreMeta(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z); + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockInventory.java b/src/common/buildcraft/api/bptblocks/BptBlockInventory.java new file mode 100644 index 000000000..18f899004 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockInventory.java @@ -0,0 +1,27 @@ +package buildcraft.api.bptblocks; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; +import net.minecraft.src.IInventory; + +public class BptBlockInventory extends BptBlock { + + public BptBlockInventory(int blockId) { + super(blockId); + + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + super.buildBlock(slot, context); + + IInventory inv = (IInventory) context.world().getBlockTileEntity(slot.x, slot.y, slot.z); + + for (int i = 0; i < inv.getSizeInventory(); ++i) { + inv.setInventorySlotContents(i, null); + } + + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockLever.java b/src/common/buildcraft/api/bptblocks/BptBlockLever.java new file mode 100644 index 000000000..48a697ef5 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockLever.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockLever extends BptBlockWallSide { + + public BptBlockLever(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + int status = slot.meta - (slot.meta & 7); + + slot.meta -= status; + super.rotateLeft(slot, context); + slot.meta += status; + + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockLiquid.java b/src/common/buildcraft/api/bptblocks/BptBlockLiquid.java new file mode 100644 index 000000000..132464477 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockLiquid.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockLiquid extends BptBlock { + + private final ItemStack bucketStack; + + public BptBlockLiquid(int blockId, ItemStack bucketStack) { + super(blockId); + + this.bucketStack = bucketStack; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + if (slot.meta == 0) { + requirements.add(bucketStack.copy()); + } + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + if (slot.meta == 0) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z) + && context.world().getBlockMetadata(slot.x, slot.y, slot.z) == 0; + } else { + return true; + } + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + + } + + @Override + public boolean ignoreBuilding(BptSlotInfo slot) { + return slot.meta != 0; + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + if (slot.meta == 0) { + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, slot.blockId, 0); + } + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockPiston.java b/src/common/buildcraft/api/bptblocks/BptBlockPiston.java new file mode 100644 index 000000000..e9606590e --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockPiston.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +public class BptBlockPiston extends BptBlockRotateMeta { + + public BptBlockPiston(int blockId) { + super(blockId, new int[] { 2, 5, 3, 4 }, true); + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + int meta = slot.meta & 7; + + context.world().setBlockAndMetadataWithNotify(slot.x, slot.y, slot.z, slot.blockId, meta); + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockPumpkin.java b/src/common/buildcraft/api/bptblocks/BptBlockPumpkin.java new file mode 100644 index 000000000..824f25d17 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockPumpkin.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockPumpkin extends BptBlock { + + public BptBlockPumpkin(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + switch (slot.meta) { + case 0: + slot.meta = 1; + break; + case 1: + slot.meta = 2; + break; + case 2: + slot.meta = 3; + break; + case 3: + slot.meta = 0; + break; + } + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockRedstoneRepeater.java b/src/common/buildcraft/api/bptblocks/BptBlockRedstoneRepeater.java new file mode 100644 index 000000000..165195d70 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockRedstoneRepeater.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; + +public class BptBlockRedstoneRepeater extends BptBlock { + + public BptBlockRedstoneRepeater(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(Item.redstoneRepeater)); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + int step = slot.meta - (slot.meta & 3); + + switch (slot.meta - step) { + case 0: + slot.meta = 1 + step; + break; + case 1: + slot.meta = 2 + step; + break; + case 2: + slot.meta = 3 + step; + break; + case 3: + slot.meta = 0 + step; + break; + } + } +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockRotateInventory.java b/src/common/buildcraft/api/bptblocks/BptBlockRotateInventory.java new file mode 100644 index 000000000..67dfbd85a --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockRotateInventory.java @@ -0,0 +1,26 @@ +package buildcraft.api.bptblocks; + +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; +import net.minecraft.src.IInventory; + +public class BptBlockRotateInventory extends BptBlockRotateMeta { + + public BptBlockRotateInventory(int blockId, int[] rotations, boolean rotateForward) { + super(blockId, rotations, rotateForward); + + } + + @Override + public void buildBlock(BptSlotInfo slot, IBptContext context) { + super.buildBlock(slot, context); + + IInventory inv = (IInventory) context.world().getBlockTileEntity(slot.x, slot.y, slot.z); + + for (int i = 0; i < inv.getSizeInventory(); ++i) { + inv.setInventorySlotContents(i, null); + } + + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockRotateMeta.java b/src/common/buildcraft/api/bptblocks/BptBlockRotateMeta.java new file mode 100644 index 000000000..90e19e89b --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockRotateMeta.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockRotateMeta extends BptBlock { + + int[] rot; + boolean rotateForward; + + int infoMask = 0; + + public BptBlockRotateMeta(int blockId, int[] rotations, boolean rotateForward) { + super(blockId); + + rot = rotations; + + for (int i = 0; i < rot.length; ++i) { + if (rot[i] < 4) { + infoMask = (infoMask < 3 ? 3 : infoMask); + } else if (rot[i] < 8) { + infoMask = (infoMask < 7 ? 7 : infoMask); + } else if (rot[i] < 16) { + infoMask = (infoMask < 15 ? 15 : infoMask); + } + } + + this.rotateForward = rotateForward; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + int pos = slot.meta & infoMask; + int others = slot.meta - pos; + + if (rotateForward) { + if (pos == rot[0]) { + pos = rot[1]; + } else if (pos == rot[1]) { + pos = rot[2]; + } else if (pos == rot[2]) { + pos = rot[3]; + } else if (pos == rot[3]) { + pos = rot[0]; + } + } else { + if (pos == rot[0]) { + pos = rot[3]; + } else if (pos == rot[1]) { + pos = rot[2]; + } else if (pos == rot[2]) { + pos = rot[0]; + } else if (pos == rot[3]) { + pos = rot[1]; + } + } + + slot.meta = pos + others; + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockSign.java b/src/common/buildcraft/api/bptblocks/BptBlockSign.java new file mode 100644 index 000000000..98905abbd --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockSign.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BlockSignature; +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; +import buildcraft.api.core.Orientations; + +import net.minecraft.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; + +public class BptBlockSign extends BptBlock { + + boolean isWall; + + public BptBlockSign(int blockId, boolean isWall) { + super(blockId); + + this.isWall = isWall; + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(Item.sign)); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + if (!isWall) { + double angle = ((slot.meta) * 360.0) / 16.0; + angle += 90.0; + if (angle >= 360) { + angle -= 360; + } + slot.meta = (int) (angle / 360.0 * 16.0); + } else { + slot.meta = Orientations.values()[slot.meta].rotateLeft().ordinal(); + } + } + + @Override + public BlockSignature getSignature(Block block) { + BlockSignature sig = super.getSignature(block); + + if (isWall) { + sig.customField = "wall"; + } else { + sig.customField = "floor"; + } + + return sig; + } + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/bptblocks/BptBlockStairs.java b/src/common/buildcraft/api/bptblocks/BptBlockStairs.java new file mode 100644 index 000000000..c67ab60a3 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockStairs.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockStairs extends BptBlock { + + public BptBlockStairs(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public boolean isValid(BptSlotInfo slot, IBptContext context) { + return slot.blockId == context.world().getBlockId(slot.x, slot.y, slot.z); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + switch (slot.meta) { + case 0: + slot.meta = 2; + break; + case 1: + slot.meta = 3; + break; + case 2: + slot.meta = 1; + break; + case 3: + slot.meta = 0; + break; + } + } + +} diff --git a/src/common/buildcraft/api/bptblocks/BptBlockWallSide.java b/src/common/buildcraft/api/bptblocks/BptBlockWallSide.java new file mode 100644 index 000000000..70da89f79 --- /dev/null +++ b/src/common/buildcraft/api/bptblocks/BptBlockWallSide.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.bptblocks; + +import java.util.LinkedList; + +import buildcraft.api.blueprints.BptBlock; +import buildcraft.api.blueprints.BptSlotInfo; +import buildcraft.api.blueprints.IBptContext; + +import net.minecraft.src.ItemStack; + +public class BptBlockWallSide extends BptBlock { + + public BptBlockWallSide(int blockId) { + super(blockId); + } + + @Override + public void addRequirements(BptSlotInfo slot, IBptContext context, LinkedList requirements) { + requirements.add(new ItemStack(slot.blockId, 1, 0)); + } + + @Override + public void rotateLeft(BptSlotInfo slot, IBptContext context) { + final int XPos = 2; + final int XNeg = 1; + final int ZPos = 4; + final int ZNeg = 3; + + switch (slot.meta) { + case XPos: + slot.meta = ZPos; + break; + case ZNeg: + slot.meta = XPos; + break; + case XNeg: + slot.meta = ZNeg; + break; + case ZPos: + slot.meta = XNeg; + break; + } + } +} diff --git a/src/common/buildcraft/api/core/BuildCraftAPI.java b/src/common/buildcraft/api/core/BuildCraftAPI.java new file mode 100644 index 000000000..73eb2a81e --- /dev/null +++ b/src/common/buildcraft/api/core/BuildCraftAPI.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +import net.minecraft.src.Block; +import net.minecraft.src.World; + +public class BuildCraftAPI { + + @Deprecated + // To be removed, see LiquidManager + public static final int BUCKET_VOLUME = 1000; + public static final int LAST_ORIGINAL_BLOCK = 122; + public static final int LAST_ORIGINAL_ITEM = 126; + + public static boolean[] softBlocks = new boolean[Block.blocksList.length]; + /** + * Return true if the block given in parameter is pass through (e.g. air, + * water...) + */ + public static boolean softBlock(int blockId) { + return blockId == 0 || softBlocks[blockId] || Block.blocksList[blockId] == null; + } + + /** + * Return true if the block cannot be broken, typically bedrock and lava + */ + public static boolean unbreakableBlock(int blockId) { + return blockId == Block.bedrock.blockID || blockId == Block.lavaStill.blockID || blockId == Block.lavaMoving.blockID; + } + + @Deprecated + // To be removed + public static void breakBlock(World world, int x, int y, int z) { + int blockId = world.getBlockId(x, y, z); + + if (blockId != 0) { + Block.blocksList[blockId].dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0); + } + + world.setBlockWithNotify(x, y, z, 0); + } + + static { + for (int i = 0; i < softBlocks.length; ++i) { + softBlocks[i] = false; + } + } +} diff --git a/src/common/buildcraft/api/core/IAreaProvider.java b/src/common/buildcraft/api/core/IAreaProvider.java new file mode 100644 index 000000000..09df298ae --- /dev/null +++ b/src/common/buildcraft/api/core/IAreaProvider.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +/** + * To be implemented by TileEntities able to provide a square area on the world, + * typically BuildCraft markers. + */ +public interface IAreaProvider { + + public int xMin(); + + public int yMin(); + + public int zMin(); + + public int xMax(); + + public int yMax(); + + public int zMax(); + + /** + * Remove from the world all objects used to define the area. + */ + public void removeFromWorld(); + +} diff --git a/src/common/buildcraft/api/core/IBox.java b/src/common/buildcraft/api/core/IBox.java new file mode 100644 index 000000000..1d90fb773 --- /dev/null +++ b/src/common/buildcraft/api/core/IBox.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +import net.minecraft.src.World; + +public interface IBox { + + public void expand(int amount); + + public void contract(int amount); + + public boolean contains(int x, int y, int z); + + public Position pMin(); + + public Position pMax(); + + public void createLasers(World world, LaserKind kind); + + public void deleteLasers(); + +} diff --git a/src/common/buildcraft/api/core/LaserKind.java b/src/common/buildcraft/api/core/LaserKind.java new file mode 100644 index 000000000..af66cae75 --- /dev/null +++ b/src/common/buildcraft/api/core/LaserKind.java @@ -0,0 +1,14 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +public enum LaserKind { + Red, Blue, Stripes +} diff --git a/src/common/buildcraft/api/core/Orientations.java b/src/common/buildcraft/api/core/Orientations.java new file mode 100644 index 000000000..d48ce2879 --- /dev/null +++ b/src/common/buildcraft/api/core/Orientations.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +import net.minecraftforge.common.ForgeDirection; + +public enum Orientations { + YNeg, // 0 + YPos, // 1 + ZNeg, // 2 + ZPos, // 3 + XNeg, // 4 + XPos, // 5 + Unknown; + + public Orientations reverse() { + switch (this) { + case YPos: + return Orientations.YNeg; + case YNeg: + return Orientations.YPos; + case ZPos: + return Orientations.ZNeg; + case ZNeg: + return Orientations.ZPos; + case XPos: + return Orientations.XNeg; + case XNeg: + return Orientations.XPos; + default: + return Orientations.Unknown; + } + } + + public ForgeDirection toDirection(){ + switch(this){ + case YNeg: + return ForgeDirection.DOWN; + case YPos: + return ForgeDirection.UP; + case ZNeg: + return ForgeDirection.NORTH; + case ZPos: + return ForgeDirection.SOUTH; + case XNeg: + return ForgeDirection.WEST; + case XPos: + return ForgeDirection.EAST; + default: + return ForgeDirection.UNKNOWN; + + } + } + + public Orientations rotateLeft() { + switch (this) { + case XPos: + return ZPos; + case ZNeg: + return XPos; + case XNeg: + return ZNeg; + case ZPos: + return XNeg; + default: + return this; + } + } + + public static Orientations[] dirs() { + return new Orientations[] { YNeg, YPos, ZNeg, ZPos, XNeg, XPos }; + } +} diff --git a/src/common/buildcraft/api/core/Position.java b/src/common/buildcraft/api/core/Position.java new file mode 100644 index 000000000..c09b649e3 --- /dev/null +++ b/src/common/buildcraft/api/core/Position.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; + +public class Position { + + public double x, y, z; + public Orientations orientation; + + public Position(double ci, double cj, double ck) { + x = ci; + y = cj; + z = ck; + orientation = Orientations.Unknown; + } + + public Position(double ci, double cj, double ck, Orientations corientation) { + x = ci; + y = cj; + z = ck; + orientation = corientation; + } + + public Position(Position p) { + x = p.x; + y = p.y; + z = p.z; + orientation = p.orientation; + } + + public Position(NBTTagCompound nbttagcompound) { + x = nbttagcompound.getDouble("i"); + y = nbttagcompound.getDouble("j"); + z = nbttagcompound.getDouble("k"); + + orientation = Orientations.Unknown; + } + + public Position(TileEntity tile) { + x = tile.xCoord; + y = tile.yCoord; + z = tile.zCoord; + } + + public void moveRight(double step) { + switch (orientation) { + case ZPos: + x = x - step; + break; + case ZNeg: + x = x + step; + break; + case XPos: + z = z + step; + break; + case XNeg: + z = z - step; + break; + default: + } + } + + public void moveLeft(double step) { + moveRight(-step); + } + + public void moveForwards(double step) { + switch (orientation) { + case YPos: + y = y + step; + break; + case YNeg: + y = y - step; + break; + case ZPos: + z = z + step; + break; + case ZNeg: + z = z - step; + break; + case XPos: + x = x + step; + break; + case XNeg: + x = x - step; + break; + default: + } + } + + public void moveBackwards(double step) { + moveForwards(-step); + } + + public void moveUp(double step) { + switch (orientation) { + case ZPos: + case ZNeg: + case XPos: + case XNeg: + y = y + step; + break; + default: + } + + } + + public void moveDown(double step) { + moveUp(-step); + } + + public void writeToNBT(NBTTagCompound nbttagcompound) { + nbttagcompound.setDouble("i", x); + nbttagcompound.setDouble("j", y); + nbttagcompound.setDouble("k", z); + } + + @Override + public String toString() { + return "{" + x + ", " + y + ", " + z + "}"; + } + + public Position min(Position p) { + return new Position(p.x > x ? x : p.x, p.y > y ? y : p.y, p.z > z ? z : p.z); + } + + public Position max(Position p) { + return new Position(p.x < x ? x : p.x, p.y < y ? y : p.y, p.z < z ? z : p.z); + } + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/core/SafeTimeTracker.java b/src/common/buildcraft/api/core/SafeTimeTracker.java new file mode 100644 index 000000000..8f278adbc --- /dev/null +++ b/src/common/buildcraft/api/core/SafeTimeTracker.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.core; + +import net.minecraft.src.World; + +public class SafeTimeTracker { + + private long lastMark = 0; + + /** + * Return true if a given delay has passed since last time marked was called + * successfully. + */ + public boolean markTimeIfDelay(World world, long delay) { + if (world == null) { + return false; + } + + long currentTime = world.getWorldTime(); + + if (currentTime < lastMark) { + lastMark = currentTime; + return false; + } else if (lastMark + delay <= currentTime) { + lastMark = world.getWorldTime(); + return true; + } else { + return false; + } + + } + + public void markTime(World world) { + lastMark = world.getWorldTime(); + } +} diff --git a/src/common/buildcraft/api/filler/FillerManager.java b/src/common/buildcraft/api/filler/FillerManager.java new file mode 100644 index 000000000..ac3ba43d2 --- /dev/null +++ b/src/common/buildcraft/api/filler/FillerManager.java @@ -0,0 +1,7 @@ +package buildcraft.api.filler; + +public class FillerManager { + + public static IFillerRegistry registry; + +} diff --git a/src/common/buildcraft/api/filler/IFillerPattern.java b/src/common/buildcraft/api/filler/IFillerPattern.java new file mode 100644 index 000000000..6dbab18b0 --- /dev/null +++ b/src/common/buildcraft/api/filler/IFillerPattern.java @@ -0,0 +1,21 @@ +package buildcraft.api.filler; + +import buildcraft.api.core.IBox; +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntity; + +public interface IFillerPattern { + + public int getId(); + + public void setId(int id); + + public boolean iteratePattern(TileEntity tile, IBox box, ItemStack stackToPlace); + + public String getTextureFile(); + + public int getTextureIndex(); + + public String getName(); + +} diff --git a/src/common/buildcraft/api/filler/IFillerRegistry.java b/src/common/buildcraft/api/filler/IFillerRegistry.java new file mode 100644 index 000000000..c9cdec29b --- /dev/null +++ b/src/common/buildcraft/api/filler/IFillerRegistry.java @@ -0,0 +1,15 @@ +package buildcraft.api.filler; + +import net.minecraft.src.IInventory; + +public interface IFillerRegistry { + + public void addRecipe(IFillerPattern pattern, Object aobj[]); + + public IFillerPattern findMatchingRecipe(IInventory inventorycrafting); + + public int getPatternNumber(IFillerPattern pattern); + + public IFillerPattern getPattern(int n); + +} diff --git a/src/common/buildcraft/api/fuels/IronEngineCoolant.java b/src/common/buildcraft/api/fuels/IronEngineCoolant.java new file mode 100644 index 000000000..fd6b9fb8a --- /dev/null +++ b/src/common/buildcraft/api/fuels/IronEngineCoolant.java @@ -0,0 +1,33 @@ +package buildcraft.api.fuels; + +import java.util.LinkedList; + +import buildcraft.api.liquids.LiquidStack; + + +public class IronEngineCoolant { + + public static LinkedList coolants = new LinkedList(); + + public static IronEngineCoolant getCoolantForLiquid(LiquidStack liquid) { + if(liquid == null) + return null; + if(liquid.itemID <= 0) + return null; + + for(IronEngineCoolant coolant : coolants) + if(coolant.liquid.isLiquidEqual(liquid)) + return coolant; + + return null; + } + + public final LiquidStack liquid; + public final float coolingPerUnit; + + public IronEngineCoolant(LiquidStack liquid, float coolingPerUnit) { + this.liquid = liquid; + this.coolingPerUnit = coolingPerUnit; + } + +} diff --git a/src/common/buildcraft/api/fuels/IronEngineFuel.java b/src/common/buildcraft/api/fuels/IronEngineFuel.java new file mode 100644 index 000000000..a76536eb2 --- /dev/null +++ b/src/common/buildcraft/api/fuels/IronEngineFuel.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.fuels; + +import java.util.LinkedList; + +import buildcraft.api.liquids.LiquidManager; +import buildcraft.api.liquids.LiquidStack; + + +public class IronEngineFuel { + + public static LinkedList fuels = new LinkedList(); + + public static IronEngineFuel getFuelForLiquid(LiquidStack liquid) { + if(liquid == null) + return null; + if(liquid.itemID <= 0) + return null; + + for(IronEngineFuel fuel : fuels) + if(fuel.liquid.isLiquidEqual(liquid)) + return fuel; + + return null; + } + + public final LiquidStack liquid; + public final float powerPerCycle; + public final int totalBurningTime; + + public IronEngineFuel(int liquidId, float powerPerCycle, int totalBurningTime) { + this(new LiquidStack(liquidId, LiquidManager.BUCKET_VOLUME, 0), powerPerCycle, totalBurningTime); + } + public IronEngineFuel(LiquidStack liquid, float powerPerCycle, int totalBurningTime) { + this.liquid = liquid; + this.powerPerCycle = powerPerCycle; + this.totalBurningTime = totalBurningTime; + } +} diff --git a/src/common/buildcraft/api/gates/Action.java b/src/common/buildcraft/api/gates/Action.java new file mode 100644 index 000000000..2d8ed3eff --- /dev/null +++ b/src/common/buildcraft/api/gates/Action.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + + +public abstract class Action implements IAction { + + protected int id; + + public Action(int id) { + this.id = id; + ActionManager.actions[id] = this; + } + + @Override + public int getId() { + return this.id; + } + + @Override + public abstract String getTexture(); + + @Override + public int getIndexInTexture() { + return 0; + } + + @Override + public boolean hasParameter() { + return false; + } + + @Override + public String getDescription() { + return ""; + } +} diff --git a/src/common/buildcraft/api/gates/ActionManager.java b/src/common/buildcraft/api/gates/ActionManager.java new file mode 100644 index 000000000..145d2d91f --- /dev/null +++ b/src/common/buildcraft/api/gates/ActionManager.java @@ -0,0 +1,85 @@ +package buildcraft.api.gates; + +import java.util.LinkedList; + +import buildcraft.api.transport.IPipe; + +import net.minecraft.src.Block; +import net.minecraft.src.TileEntity; + +public class ActionManager { + + public static Trigger[] triggers = new Trigger[1024]; + public static Action[] actions = new Action[1024]; + + private static LinkedList triggerProviders = new LinkedList(); + private static LinkedList actionProviders = new LinkedList(); + + public static void registerTriggerProvider(ITriggerProvider provider) { + if (provider != null && !triggerProviders.contains(provider)) { + triggerProviders.add(provider); + } + } + + public static LinkedList getNeighborTriggers(Block block, TileEntity entity) { + LinkedList triggers = new LinkedList(); + + for (ITriggerProvider provider : triggerProviders) { + LinkedList toAdd = provider.getNeighborTriggers(block, entity); + + if (toAdd != null) { + for (ITrigger t : toAdd) { + if (!triggers.contains(t)) { + triggers.add(t); + } + } + } + } + + return triggers; + } + + public static void registerActionProvider(IActionProvider provider) { + if (provider != null && !actionProviders.contains(provider)) { + actionProviders.add(provider); + } + } + + public static LinkedList getNeighborActions(Block block, TileEntity entity) { + LinkedList actions = new LinkedList(); + + for (IActionProvider provider : actionProviders) { + LinkedList toAdd = provider.getNeighborActions(block, entity); + + if (toAdd != null) { + for (IAction t : toAdd) { + if (!actions.contains(t)) { + actions.add(t); + } + } + } + } + + return actions; + } + + public static LinkedList getPipeTriggers(IPipe pipe) { + LinkedList triggers = new LinkedList(); + + for (ITriggerProvider provider : triggerProviders) { + LinkedList toAdd = provider.getPipeTriggers(pipe); + + if (toAdd != null) { + for (ITrigger t : toAdd) { + if (!triggers.contains(t)) { + triggers.add(t); + } + } + } + } + + return triggers; + } + + +} diff --git a/src/common/buildcraft/api/gates/IAction.java b/src/common/buildcraft/api/gates/IAction.java new file mode 100644 index 000000000..f31910ac7 --- /dev/null +++ b/src/common/buildcraft/api/gates/IAction.java @@ -0,0 +1,11 @@ +package buildcraft.api.gates; + +public interface IAction { + + int getId(); + String getTexture(); + int getIndexInTexture(); + boolean hasParameter(); + String getDescription(); + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/gates/IActionProvider.java b/src/common/buildcraft/api/gates/IActionProvider.java new file mode 100644 index 000000000..7b6dd67b9 --- /dev/null +++ b/src/common/buildcraft/api/gates/IActionProvider.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + +import java.util.LinkedList; + +import net.minecraft.src.Block; +import net.minecraft.src.TileEntity; + +public interface IActionProvider { + + /** + * Returns the list of actions available to a gate next to the given block. + */ + public abstract LinkedList getNeighborActions(Block block, TileEntity tile); + +} diff --git a/src/common/buildcraft/api/gates/IActionReceptor.java b/src/common/buildcraft/api/gates/IActionReceptor.java new file mode 100644 index 000000000..faab00084 --- /dev/null +++ b/src/common/buildcraft/api/gates/IActionReceptor.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) SpaceToad, 2012 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + + +public interface IActionReceptor { + + public void actionActivated(IAction action); + +} diff --git a/src/common/buildcraft/api/gates/IOverrideDefaultTriggers.java b/src/common/buildcraft/api/gates/IOverrideDefaultTriggers.java new file mode 100644 index 000000000..ed7a3919a --- /dev/null +++ b/src/common/buildcraft/api/gates/IOverrideDefaultTriggers.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + +import java.util.LinkedList; + + +/** + * This interface has to be implemented by a TileEntity or a Pipe that wants to + * provide triggers different from the ones installed by default with + * BuildCraft. + */ +public interface IOverrideDefaultTriggers { + + LinkedList getTriggers(); + +} diff --git a/src/common/buildcraft/api/gates/ITrigger.java b/src/common/buildcraft/api/gates/ITrigger.java new file mode 100644 index 000000000..67c4c62de --- /dev/null +++ b/src/common/buildcraft/api/gates/ITrigger.java @@ -0,0 +1,41 @@ +package buildcraft.api.gates; + +import net.minecraft.src.TileEntity; + +public interface ITrigger { + + public abstract int getId(); + + /** + * Return the texture file for this trigger icon + */ + public abstract String getTextureFile(); + + /** + * Return the icon id in the texture file + */ + public abstract int getIndexInTexture(); + + /** + * Return true if this trigger can accept parameters + */ + public abstract boolean hasParameter(); + + /** + * Return the trigger description in the UI + */ + public abstract String getDescription(); + + /** + * Return true if the tile given in parameter activates the trigger, given + * the parameters. + */ + public abstract boolean isTriggerActive(TileEntity tile, ITriggerParameter parameter); + + /** + * Create parameters for the trigger. As for now, there is only one kind of + * trigger parameter available so this subprogram is final. + */ + public abstract ITriggerParameter createParameter(); + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/gates/ITriggerParameter.java b/src/common/buildcraft/api/gates/ITriggerParameter.java new file mode 100644 index 000000000..d8565f09a --- /dev/null +++ b/src/common/buildcraft/api/gates/ITriggerParameter.java @@ -0,0 +1,18 @@ +package buildcraft.api.gates; + +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; + +public interface ITriggerParameter { + + public abstract ItemStack getItemStack(); + + public abstract void set(ItemStack stack); + + public abstract void writeToNBT(NBTTagCompound compound); + + public abstract void readFromNBT(NBTTagCompound compound); + + public abstract ItemStack getItem(); + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/gates/ITriggerProvider.java b/src/common/buildcraft/api/gates/ITriggerProvider.java new file mode 100644 index 000000000..9adeda050 --- /dev/null +++ b/src/common/buildcraft/api/gates/ITriggerProvider.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + +import java.util.LinkedList; + +import buildcraft.api.transport.IPipe; + +import net.minecraft.src.Block; +import net.minecraft.src.TileEntity; + +public interface ITriggerProvider { + + /** + * Returns the list of triggers that are available from the pipe holding the + * gate. + */ + public abstract LinkedList getPipeTriggers(IPipe pipe); + + /** + * Returns the list of triggers available to a gate next to the given block. + */ + public abstract LinkedList getNeighborTriggers(Block block, TileEntity tile); + +} diff --git a/src/common/buildcraft/api/gates/Trigger.java b/src/common/buildcraft/api/gates/Trigger.java new file mode 100644 index 000000000..464fc8e10 --- /dev/null +++ b/src/common/buildcraft/api/gates/Trigger.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + +import net.minecraft.src.TileEntity; + +/** + * This class has to be implemented to create new triggers kinds to BuildCraft + * gates. There is an instance per kind, which will get called wherever the + * trigger can be active. + */ +public abstract class Trigger implements ITrigger { + + protected int id; + + /** + * Creates a new triggers, and stores it in the trigger list + */ + public Trigger(int id) { + this.id = id; + ActionManager.triggers[id] = this; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#getId() + */ + @Override + public int getId() { + return this.id; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#getTextureFile() + */ + @Override + public abstract String getTextureFile(); + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#getIndexInTexture() + */ + @Override + public int getIndexInTexture() { + return 0; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#hasParameter() + */ + @Override + public boolean hasParameter() { + return false; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#getDescription() + */ + @Override + public String getDescription() { + return ""; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#isTriggerActive(net.minecraft.src.TileEntity, net.minecraft.src.buildcraft.api.gates.TriggerParameter) + */ + @Override + public boolean isTriggerActive(TileEntity tile, ITriggerParameter parameter) { + return false; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITrigger#createParameter() + */ + @Override + public final ITriggerParameter createParameter() { + return new TriggerParameter(); + } +} diff --git a/src/common/buildcraft/api/gates/TriggerParameter.java b/src/common/buildcraft/api/gates/TriggerParameter.java new file mode 100644 index 000000000..5c22f83b9 --- /dev/null +++ b/src/common/buildcraft/api/gates/TriggerParameter.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.gates; + +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; + +public class TriggerParameter implements ITriggerParameter { + + protected ItemStack stack; + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITriggerParameter#getItemStack() + */ + @Override + public ItemStack getItemStack() { + return stack; + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITriggerParameter#set(net.minecraft.src.ItemStack) + */ + @Override + public void set(ItemStack stack) { + if (stack != null) { + this.stack = stack.copy(); + this.stack.stackSize = 1; + } + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITriggerParameter#writeToNBT(net.minecraft.src.NBTTagCompound) + */ + @Override + public void writeToNBT(NBTTagCompound compound) { + if (stack != null) { + compound.setInteger("itemID", stack.itemID); + compound.setInteger("itemDMG", stack.getItemDamage()); + } + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITriggerParameter#readFromNBT(net.minecraft.src.NBTTagCompound) + */ + @Override + public void readFromNBT(NBTTagCompound compound) { + int itemID = compound.getInteger("itemID"); + + if (itemID != 0) { + stack = new ItemStack(itemID, 1, compound.getInteger("itemDMG")); + } + } + + /* (non-Javadoc) + * @see net.minecraft.src.buildcraft.api.gates.ITriggerParameter#getItem() + */ + @Override + public ItemStack getItem() { + return stack; + } + +} diff --git a/src/common/buildcraft/api/inventory/ISecuredInventory.java b/src/common/buildcraft/api/inventory/ISecuredInventory.java new file mode 100644 index 000000000..d76530daf --- /dev/null +++ b/src/common/buildcraft/api/inventory/ISecuredInventory.java @@ -0,0 +1,20 @@ +package buildcraft.api.inventory; + +import buildcraft.api.core.Orientations; + +public interface ISecuredInventory { + + /** + * @param name + * @return true if the user/player with the given name has access permissions on this machine. + */ + boolean canAccess(String name); + + /** + * Informs the inventory with whose permissions the next item or liquid transaction will be performed. It is up to the inventory to determine the effect. + * @param orientation Orientation the transaction will be performed from. + * @param name Name of the user/player who owns the transaction. + */ + void prepareTransaction(Orientations orientation, String name); + +} diff --git a/src/common/buildcraft/api/inventory/ISelectiveInventory.java b/src/common/buildcraft/api/inventory/ISelectiveInventory.java new file mode 100644 index 000000000..ea79739d5 --- /dev/null +++ b/src/common/buildcraft/api/inventory/ISelectiveInventory.java @@ -0,0 +1,17 @@ +package buildcraft.api.inventory; + +import buildcraft.api.core.Orientations; +import net.minecraft.src.ItemStack; + +public interface ISelectiveInventory extends ISpecialInventory { + /** + * Requests specified items to be extracted from the inventory + * @param desired Array which can contain ItemStacks, Items, or classes describing the type of item accepted or excluded. + * @param exclusion If true desired items are not eligible for returning. + * @param doRemove If false no actual extraction may occur. + * @param from Orientation the ItemStack is requested from. + * @param maxItemCount Maximum amount of items to extract (spread over all returned item stacks) + * @return Array of item stacks extracted from the inventory + */ + ItemStack[] extractItem(Object[] desired, boolean exclusion, boolean doRemove, Orientations from, int maxItemCount); +} diff --git a/src/common/buildcraft/api/inventory/ISpecialInventory.java b/src/common/buildcraft/api/inventory/ISpecialInventory.java new file mode 100644 index 000000000..1f4426ab4 --- /dev/null +++ b/src/common/buildcraft/api/inventory/ISpecialInventory.java @@ -0,0 +1,26 @@ +package buildcraft.api.inventory; + +import buildcraft.api.core.Orientations; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; + +public interface ISpecialInventory extends IInventory { + + /** + * Offers an ItemStack for addition to the inventory. + * @param stack ItemStack offered for addition. Do not manipulate this! + * @param doAdd If false no actual addition should take place. + * @param from Orientation the ItemStack is offered from. + * @return Amount of items used from the passed stack. + */ + int addItem(ItemStack stack, boolean doAdd, Orientations from); + /** + * Requests items to be extracted from the inventory + * @param doRemove If false no actual extraction may occur. + * @param from Orientation the ItemStack is requested from. + * @param maxItemCount Maximum amount of items to extract (spread over all returned item stacks) + * @return Array of item stacks extracted from the inventory + */ + ItemStack[] extractItem(boolean doRemove, Orientations from, int maxItemCount); + +} diff --git a/src/common/buildcraft/api/liquids/ILiquid.java b/src/common/buildcraft/api/liquids/ILiquid.java new file mode 100644 index 000000000..a060c3922 --- /dev/null +++ b/src/common/buildcraft/api/liquids/ILiquid.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.liquids; + +public interface ILiquid { + + public int stillLiquidId(); + + public boolean isMetaSensitive(); + + public int stillLiquidMeta(); + +} diff --git a/src/common/buildcraft/api/liquids/ILiquidTank.java b/src/common/buildcraft/api/liquids/ILiquidTank.java new file mode 100644 index 000000000..d0d3de86e --- /dev/null +++ b/src/common/buildcraft/api/liquids/ILiquidTank.java @@ -0,0 +1,27 @@ +package buildcraft.api.liquids; + +public interface ILiquidTank { + + /** + * @return LiquidStack representing the liquid contained in the tank, null if empty. + */ + LiquidStack getLiquid(); + void setLiquid(LiquidStack liquid); + void setCapacity(int capacity); + int getCapacity(); + + /** + * + * @param resource + * @param doFill + * @return Amount of liquid used for filling. + */ + int fill(LiquidStack resource, boolean doFill); + /** + * + * @param maxDrain + * @param doDrain + * @return Null if nothing was drained, otherwise a LiquidStack containing the drained. + */ + LiquidStack drain(int maxDrain, boolean doDrain); +} diff --git a/src/common/buildcraft/api/liquids/ITankContainer.java b/src/common/buildcraft/api/liquids/ITankContainer.java new file mode 100644 index 000000000..78e05b2e8 --- /dev/null +++ b/src/common/buildcraft/api/liquids/ITankContainer.java @@ -0,0 +1,46 @@ +package buildcraft.api.liquids; + +import buildcraft.api.core.Orientations; + +public interface ITankContainer { + + /** + * Fills liquid into internal tanks, distribution is left to the ITankContainer. + * @param from Orientation the liquid is pumped in from. + * @param resource LiquidStack representing the maximum amount of liquid filled into the ITankContainer + * @param doFill If false filling will only be simulated. + * @return Amount of resource that was filled into internal tanks. + */ + int fill(Orientations from, LiquidStack resource, boolean doFill); + /** + * Fills liquid into the specified internal tank. + * @param from Orientation the liquid is pumped in from. + * @param resource LiquidStack representing the maximum amount of liquid filled into the ITankContainer + * @param doFill If false filling will only be simulated. + * @return Amount of resource that was filled into internal tanks. + */ + int fill(int tankIndex, LiquidStack resource, boolean doFill); + + /** + * Drains liquid out of internal tanks, distribution is left to the ITankContainer. + * @param from Orientation the liquid is drained to. + * @param maxDrain Maximum amount of liquid to drain. + * @param doDrain If false draining will only be simulated. + * @return LiquidStack representing the liquid and amount actually drained from the ITankContainer + */ + LiquidStack drain(Orientations from, int maxDrain, boolean doDrain); + /** + * Drains liquid out of the specified internal tank. + * @param from Orientation the liquid is drained to. + * @param maxDrain Maximum amount of liquid to drain. + * @param doDrain If false draining will only be simulated. + * @return LiquidStack representing the liquid and amount actually drained from the ITankContainer + */ + LiquidStack drain(int tankIndex, int maxDrain, boolean doDrain); + + /** + * @return Array of {@link LiquidTank}s contained in this ITankContainer + */ + ILiquidTank[] getTanks(); + +} diff --git a/src/common/buildcraft/api/liquids/LiquidData.java b/src/common/buildcraft/api/liquids/LiquidData.java new file mode 100644 index 000000000..2eac0a079 --- /dev/null +++ b/src/common/buildcraft/api/liquids/LiquidData.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.liquids; + +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; + +public class LiquidData { + + public final LiquidStack stillLiquid; + public final LiquidStack movingLiquid; + + public final ItemStack filled; + public final ItemStack container; + + public LiquidData(int stillLiquidId, int movingLiquidId, Item filled) { + this(new LiquidStack(stillLiquidId, LiquidManager.BUCKET_VOLUME), new LiquidStack(movingLiquidId, LiquidManager.BUCKET_VOLUME), new ItemStack(filled, 1), new ItemStack(Item.bucketEmpty)); + } + + public LiquidData(int stillLiquidId, int movingLiquidId, ItemStack filled) { + this(new LiquidStack(stillLiquidId, LiquidManager.BUCKET_VOLUME), new LiquidStack(movingLiquidId, LiquidManager.BUCKET_VOLUME), filled, new ItemStack(Item.bucketEmpty)); + } + + public LiquidData(LiquidStack stillLiquid, ItemStack filled, ItemStack container) { + this(stillLiquid, stillLiquid, filled, container); + } + + public LiquidData(LiquidStack stillLiquid, LiquidStack movingLiquid, ItemStack filled, ItemStack container) { + this.stillLiquid = stillLiquid; + this.movingLiquid = movingLiquid; + this.filled = filled; + this.container = container; + + if(stillLiquid == null || filled == null || container == null) + throw new RuntimeException("stillLiquid, filled, or container is null, this is an error"); + } + +} diff --git a/src/common/buildcraft/api/liquids/LiquidDictionary.java b/src/common/buildcraft/api/liquids/LiquidDictionary.java new file mode 100644 index 000000000..08f4c8142 --- /dev/null +++ b/src/common/buildcraft/api/liquids/LiquidDictionary.java @@ -0,0 +1,57 @@ +package buildcraft.api.liquids; + +import java.util.HashMap; +import java.util.Map; + +/** + * When creating liquids you should register them with this class. + * + * @author CovertJaguar + */ +public abstract class LiquidDictionary +{ + + private static Map liquids = new HashMap(); + + /** + * When creating liquids you should call this function. + * + * Upon passing it a name and liquid item it will return either + * a preexisting implementation of that liquid or the liquid passed in. + * + * + * @param name the name of the liquid + * @param liquid the liquid to use if one doesn't exist + * @return + */ + public static LiquidStack getOrCreateLiquid(String name, LiquidStack liquid) + { + LiquidStack existing = liquids.get(name); + if(existing != null) { + return existing.copy(); + } + liquids.put(name, liquid.copy()); + return liquid; + } + + /** + * Returns the liquid matching the name, + * if such a liquid exists. + * + * Can return null. + * + * @param name the name of the liquid + * @param amount the amout of liquid + * @return + */ + public static LiquidStack getLiquid(String name, int amount) + { + LiquidStack liquid = liquids.get(name); + if(liquid == null) + return null; + + liquid = liquid.copy(); + liquid.amount = amount; + return liquid; + } +} diff --git a/src/common/buildcraft/api/liquids/LiquidManager.java b/src/common/buildcraft/api/liquids/LiquidManager.java new file mode 100644 index 000000000..514f176c5 --- /dev/null +++ b/src/common/buildcraft/api/liquids/LiquidManager.java @@ -0,0 +1,64 @@ +package buildcraft.api.liquids; + +import java.util.LinkedList; + +import net.minecraft.src.ItemStack; + +public class LiquidManager { + + public static final int BUCKET_VOLUME = 1000; + public static LinkedList liquids = new LinkedList(); + + public static LiquidStack getLiquidForFilledItem(ItemStack filledItem) { + if (filledItem == null) + return null; + + for (LiquidData liquid : liquids) + if (liquid.filled.isItemEqual(filledItem)) + return liquid.stillLiquid; + + return null; + } + + public static int getLiquidIDForFilledItem(ItemStack filledItem) { + LiquidStack liquidForFilledItem = getLiquidForFilledItem(filledItem); + + if (liquidForFilledItem == null) + return 0; + + return liquidForFilledItem.itemID; + } + + public static ItemStack getFilledItemForLiquid(LiquidStack liquid) { + for (LiquidData data : liquids) + if(data.stillLiquid.isLiquidEqual(liquid)) + return data.filled.copy(); + + return null; + } + + public static ItemStack fillLiquidContainer(int liquidId, int quantity, ItemStack emptyContainer) { + return fillLiquidContainer(new LiquidStack(liquidId, quantity, 0), emptyContainer); + } + + public static ItemStack fillLiquidContainer(LiquidStack liquid, ItemStack emptyContainer) { + for(LiquidData data : liquids) + if(liquid.containsLiquid(data.stillLiquid) + && data.container.isItemEqual(emptyContainer)) + return data.filled.copy(); + return null; + } + + public static boolean isLiquid(ItemStack block) { + if (block.itemID == 0) + return false; + + for (LiquidData liquid : liquids) + if (liquid.stillLiquid.isLiquidEqual(block) || liquid.movingLiquid.isLiquidEqual(block)) + return true; + + return false; + } + + +} diff --git a/src/common/buildcraft/api/liquids/LiquidStack.java b/src/common/buildcraft/api/liquids/LiquidStack.java new file mode 100644 index 000000000..145b1d656 --- /dev/null +++ b/src/common/buildcraft/api/liquids/LiquidStack.java @@ -0,0 +1,109 @@ +package buildcraft.api.liquids; + +import net.minecraft.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; + +/** + * ItemStack substitute for liquids + * @author SirSengir + */ +public class LiquidStack { + public int itemID; + public int amount; + public int itemMeta; + + private LiquidStack() { + } + + public LiquidStack(int itemID, int amount) { + this(itemID, amount, 0); + } + + public LiquidStack(Item item, int amount) { + this(item.shiftedIndex, amount, 0); + } + + public LiquidStack(Block block, int amount) { + this(block.blockID, amount, 0); + } + + public LiquidStack(int itemID, int amount, int itemDamage) { + this.itemID = itemID; + this.amount = amount; + this.itemMeta = itemDamage; + } + + public NBTTagCompound writeToNBT(NBTTagCompound nbttagcompound) { + nbttagcompound.setShort("Id", (short) itemID); + nbttagcompound.setInteger("Amount", amount); + nbttagcompound.setShort("Meta", (short) itemMeta); + return nbttagcompound; + } + + public void readFromNBT(NBTTagCompound nbttagcompound) { + itemID = nbttagcompound.getShort("Id"); + amount = nbttagcompound.getInteger("Amount"); + itemMeta = nbttagcompound.getShort("Meta"); + } + + /** + * @return A copy of this LiquidStack + */ + public LiquidStack copy() { + return new LiquidStack(itemID, amount, itemMeta); + } + + /** + * @param other + * @return true if this LiquidStack contains the same liquid as the one passed in. + */ + public boolean isLiquidEqual(LiquidStack other) { + if(other == null) + return false; + + return itemID == other.itemID && itemMeta == other.itemMeta; + } + + /** + * @param other + * @return true if this LiquidStack contains the other liquid (liquids are equal and amount >= other.amount). + */ + public boolean containsLiquid(LiquidStack other) { + if(!isLiquidEqual(other)) + return false; + + return amount >= other.amount; + } + + /** + * @param other ItemStack containing liquids. + * @return true if this LiquidStack contains the same liquid as the one passed in. + */ + public boolean isLiquidEqual(ItemStack other) { + if(other == null) + return false; + + return itemID == other.itemID && itemMeta == other.getItemDamage(); + } + + /** + * @return ItemStack representation of this LiquidStack + */ + public ItemStack asItemStack() { + return new ItemStack(itemID, 1, itemMeta); + } + + /** + * Reads a liquid stack from the passed nbttagcompound and returns it. + * + * @param nbttagcompound + * @return + */ + public static LiquidStack loadLiquidStackFromNBT(NBTTagCompound nbttagcompound) { + LiquidStack liquidstack = new LiquidStack(); + liquidstack.readFromNBT(nbttagcompound); + return liquidstack.itemID == 0 ? null : liquidstack; + } +} diff --git a/src/common/buildcraft/api/liquids/LiquidTank.java b/src/common/buildcraft/api/liquids/LiquidTank.java new file mode 100644 index 000000000..cf6c668f5 --- /dev/null +++ b/src/common/buildcraft/api/liquids/LiquidTank.java @@ -0,0 +1,100 @@ +package buildcraft.api.liquids; + +/** + * Reference implementation of ILiquidTank. Use this or implement your own. + */ +public class LiquidTank implements ILiquidTank { + private LiquidStack liquid; + private int capacity; + + public LiquidTank(int capacity) { + this(null, capacity); + } + + public LiquidTank(int liquidId, int quantity, int capacity) { + this(new LiquidStack(liquidId, quantity), capacity); + } + public LiquidTank(LiquidStack liquid, int capacity) { + this.liquid = liquid; + this.capacity = capacity; + } + + @Override + public LiquidStack getLiquid() { + return this.liquid; + } + + @Override + public void setLiquid(LiquidStack liquid) { + this.liquid = liquid; + } + + @Override + public void setCapacity(int capacity) { + this.capacity = capacity; + } + + @Override + public int getCapacity() { + return this.capacity; + } + + @Override + public int fill(LiquidStack resource, boolean doFill) { + if(resource == null || resource.itemID <= 0) + return 0; + + if(liquid == null || liquid.itemID <= 0) { + if(resource.amount <= capacity) { + if(doFill) + this.liquid = resource.copy(); + return resource.amount; + } else { + if(doFill) { + this.liquid = resource.copy(); + this.liquid.amount = capacity; + } + return capacity; + } + } + + if(!liquid.isLiquidEqual(resource)) + return 0; + + int space = capacity - liquid.amount; + if(resource.amount <= space) { + if(doFill) + this.liquid.amount += resource.amount; + return resource.amount; + } else { + + if(doFill) + this.liquid.amount = capacity; + return space; + } + + } + @Override + public LiquidStack drain(int maxDrain, boolean doDrain) { + if(liquid == null || liquid.itemID <= 0) + return null; + if(liquid.amount <= 0) + return null; + + int used = maxDrain; + if(liquid.amount < used) + used = liquid.amount; + + if(doDrain) { + liquid.amount -= used; + } + + LiquidStack drained = new LiquidStack(liquid.itemID, used, liquid.itemMeta); + + // Reset liquid if emptied + if(liquid.amount <= 0) + liquid = null; + + return drained; + } +} diff --git a/src/common/buildcraft/api/power/IPowerProvider.java b/src/common/buildcraft/api/power/IPowerProvider.java new file mode 100644 index 000000000..0700f7a65 --- /dev/null +++ b/src/common/buildcraft/api/power/IPowerProvider.java @@ -0,0 +1,41 @@ +package buildcraft.api.power; + +import buildcraft.api.core.Orientations; +import buildcraft.api.core.SafeTimeTracker; +import net.minecraft.src.NBTTagCompound; + +public interface IPowerProvider { + + int getLatency(); + + int getMinEnergyReceived(); + + int getMaxEnergyReceived(); + + int getMaxEnergyStored(); + + int getActivationEnergy(); + + float getEnergyStored(); + + void configure(int latency, int minEnergyReceived, int maxEnergyReceived, int minActivationEnergy, int maxStoredEnergy); + + void configurePowerPerdition(int powerLoss, int powerLossRegularity); + + boolean update(IPowerReceptor receptor); + + boolean preConditions(IPowerReceptor receptor); + + float useEnergy(float min, float max, boolean doUse); + + void readFromNBT(NBTTagCompound nbttagcompound); + + void writeToNBT(NBTTagCompound nbttagcompound); + + void receiveEnergy(float quantity, Orientations from); + + boolean isPowerSource(Orientations from); + + SafeTimeTracker getTimeTracker(); + +} diff --git a/src/common/buildcraft/api/power/IPowerReceptor.java b/src/common/buildcraft/api/power/IPowerReceptor.java new file mode 100644 index 000000000..6304c6f09 --- /dev/null +++ b/src/common/buildcraft/api/power/IPowerReceptor.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.power; + + +public interface IPowerReceptor { + + public void setPowerProvider(IPowerProvider provider); + + public IPowerProvider getPowerProvider(); + + public void doWork(); + + public int powerRequest(); + +} diff --git a/src/common/buildcraft/api/power/PowerFramework.java b/src/common/buildcraft/api/power/PowerFramework.java new file mode 100644 index 000000000..5ed84872c --- /dev/null +++ b/src/common/buildcraft/api/power/PowerFramework.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.power; + +import net.minecraft.src.NBTTagCompound; + +public abstract class PowerFramework { + + static private String baseNBTName = "net.minecraft.src.buildcarft.Power"; + + public static PowerFramework currentFramework; + + public abstract IPowerProvider createPowerProvider(); + + public void loadPowerProvider(IPowerReceptor receptor, NBTTagCompound compound) { + + IPowerProvider provider = createPowerProvider(); + + if (compound.hasKey(baseNBTName)) { + NBTTagCompound cpt = compound.getCompoundTag(baseNBTName); + if (cpt.getString("class").equals(this.getClass().getName())) { + provider.readFromNBT(cpt.getCompoundTag("contents")); + } + } + + receptor.setPowerProvider(provider); + } + + public void savePowerProvider(IPowerReceptor receptor, NBTTagCompound compound) { + + IPowerProvider provider = receptor.getPowerProvider(); + + if (provider == null) { + return; + } + + NBTTagCompound cpt = new NBTTagCompound(); + + cpt.setString("class", this.getClass().getName()); + + NBTTagCompound contents = new NBTTagCompound(); + + provider.writeToNBT(contents); + + cpt.setTag("contents", contents); + compound.setTag(baseNBTName, cpt); + } + +} diff --git a/src/common/buildcraft/api/power/PowerProvider.java b/src/common/buildcraft/api/power/PowerProvider.java new file mode 100644 index 000000000..b2b4663e2 --- /dev/null +++ b/src/common/buildcraft/api/power/PowerProvider.java @@ -0,0 +1,162 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.power; + +import buildcraft.api.core.Orientations; +import buildcraft.api.core.SafeTimeTracker; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; + +public abstract class PowerProvider implements IPowerProvider { + + protected int latency; + protected int minEnergyReceived; + protected int maxEnergyReceived; + protected int maxEnergyStored; + protected int minActivationEnergy; + protected float energyStored = 0; + + protected int powerLoss = 1; + protected int powerLossRegularity = 100; + + public SafeTimeTracker timeTracker = new SafeTimeTracker(); + public SafeTimeTracker energyLossTracker = new SafeTimeTracker(); + + public int[] powerSources = { 0, 0, 0, 0, 0, 0 }; + + @Override public SafeTimeTracker getTimeTracker() { return this.timeTracker; } + + @Override public int getLatency() { return this.latency; } + @Override public int getMinEnergyReceived() { return this.minEnergyReceived; } + @Override public int getMaxEnergyReceived() { return this.maxEnergyReceived; } + @Override public int getMaxEnergyStored() { return this.maxEnergyStored; } + @Override public int getActivationEnergy() { return this.minActivationEnergy; } + @Override public float getEnergyStored() { return this.energyStored; } + + @Override + public void configure(int latency, int minEnergyReceived, int maxEnergyReceived, int minActivationEnergy, int maxStoredEnergy) { + this.latency = latency; + this.minEnergyReceived = minEnergyReceived; + this.maxEnergyReceived = maxEnergyReceived; + this.maxEnergyStored = maxStoredEnergy; + this.minActivationEnergy = minActivationEnergy; + } + + @Override + public void configurePowerPerdition(int powerLoss, int powerLossRegularity) { + this.powerLoss = powerLoss; + this.powerLossRegularity = powerLossRegularity; + } + + @Override + public boolean update(IPowerReceptor receptor) { + if (!preConditions(receptor)) { + return false; + } + + TileEntity tile = (TileEntity) receptor; + boolean result = false; + + if (energyStored >= minActivationEnergy) { + if (latency == 0) { + receptor.doWork(); + result = true; + } else { + if (timeTracker.markTimeIfDelay(tile.worldObj, latency)) { + receptor.doWork(); + result = true; + } + } + } + + if (powerLoss > 0 && energyLossTracker.markTimeIfDelay(tile.worldObj, powerLossRegularity)) { + + energyStored -= powerLoss; + if (energyStored < 0) { + energyStored = 0; + } + } + + for (int i = 0; i < 6; ++i) { + if (powerSources[i] > 0) { + powerSources[i]--; + } + } + + return result; + } + + @Override + public boolean preConditions(IPowerReceptor receptor) { + return true; + } + + @Override + public float useEnergy(float min, float max, boolean doUse) { + float result = 0; + + if (energyStored >= min) { + if (energyStored <= max) { + result = energyStored; + if (doUse) { + energyStored = 0; + } + } else { + result = max; + if (doUse) { + energyStored -= max; + } + } + } + + return result; + } + + @Override + public void readFromNBT(NBTTagCompound nbttagcompound) { + latency = nbttagcompound.getInteger("latency"); + minEnergyReceived = nbttagcompound.getInteger("minEnergyReceived"); + maxEnergyReceived = nbttagcompound.getInteger("maxEnergyReceived"); + maxEnergyStored = nbttagcompound.getInteger("maxStoreEnergy"); + minActivationEnergy = nbttagcompound.getInteger("minActivationEnergy"); + + try { + energyStored = nbttagcompound.getFloat("storedEnergy"); + } catch (Throwable c) { + energyStored = 0; + } + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) { + nbttagcompound.setInteger("latency", latency); + nbttagcompound.setInteger("minEnergyReceived", minEnergyReceived); + nbttagcompound.setInteger("maxEnergyReceived", maxEnergyReceived); + nbttagcompound.setInteger("maxStoreEnergy", maxEnergyStored); + nbttagcompound.setInteger("minActivationEnergy", minActivationEnergy); + nbttagcompound.setFloat("storedEnergy", energyStored); + } + + @Override + public void receiveEnergy(float quantity, Orientations from) { + powerSources[from.ordinal()] = 2; + + energyStored += quantity; + + if (energyStored > maxEnergyStored) { + energyStored = maxEnergyStored; + } + } + + @Override + public boolean isPowerSource(Orientations from) { + return powerSources[from.ordinal()] != 0; + } +} diff --git a/src/common/buildcraft/api/recipes/AssemblyRecipe.java b/src/common/buildcraft/api/recipes/AssemblyRecipe.java new file mode 100644 index 000000000..ccb0a2176 --- /dev/null +++ b/src/common/buildcraft/api/recipes/AssemblyRecipe.java @@ -0,0 +1,46 @@ +package buildcraft.api.recipes; + +import java.util.LinkedList; + +import net.minecraft.src.ItemStack; + +public class AssemblyRecipe { + + public static LinkedList assemblyRecipes = new LinkedList(); + + public final ItemStack[] input; + public final ItemStack output; + public final float energy; + + public AssemblyRecipe(ItemStack[] input, int energy, ItemStack output) { + this.input = input; + this.output = output; + this.energy = energy; + } + + public boolean canBeDone(ItemStack[] items) { + + for (ItemStack in : input) { + + if (in == null) + continue; + + int found = 0; // Amount of ingredient found in inventory + + for (ItemStack item : items) { + if (item == null) + continue; + + if (item.isItemEqual(in)) + found += item.stackSize; // Adds quantity of stack to amount + // found + } + + if (found < in.stackSize) + return false; // Return false if the amount of ingredient found + // is not enough + } + + return true; + } +} diff --git a/src/common/buildcraft/api/recipes/RefineryRecipe.java b/src/common/buildcraft/api/recipes/RefineryRecipe.java new file mode 100644 index 000000000..fd92c5434 --- /dev/null +++ b/src/common/buildcraft/api/recipes/RefineryRecipe.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.recipes; + +import java.util.LinkedList; + +import buildcraft.api.liquids.LiquidStack; + + +public class RefineryRecipe { + + private static LinkedList recipes = new LinkedList(); + + public static void registerRefineryRecipe(RefineryRecipe recipe) { + if (!recipes.contains(recipe)) { + recipes.add(recipe); + } + } + + public static RefineryRecipe findRefineryRecipe(LiquidStack liquid1, LiquidStack liquid2) { + for(RefineryRecipe recipe : recipes) + if(recipe.matches(liquid1, liquid2)) + return recipe; + + return null; + } + + public final LiquidStack ingredient1; + public final LiquidStack ingredient2; + public final LiquidStack result; + + public final int energy; + public final int delay; + + public RefineryRecipe(int ingredientId1, int ingredientQty1, int ingredientId2, int ingredientQty2, int resultId, int resultQty, + int energy, int delay) { + this(new LiquidStack(ingredientId1, ingredientQty1, 0), new LiquidStack(ingredientId2, ingredientQty2, 0), new LiquidStack(resultId, resultQty, 0), energy, delay); + } + public RefineryRecipe(LiquidStack ingredient1, LiquidStack ingredient2, LiquidStack result, int energy, int delay) { + this.ingredient1 = ingredient1; + this.ingredient2 = ingredient2; + this.result = result; + this.energy = energy; + this.delay = delay; + } + + public boolean matches(LiquidStack liquid1, LiquidStack liquid2) { + + // No inputs, return. + if(liquid1 == null && liquid2 == null) + return false; + + // Return if two ingredients are required but only one was supplied. + if((ingredient1 != null && ingredient2 != null) + && (liquid1 == null || liquid2 == null)) + return false; + + if(ingredient1 != null) { + + if(ingredient2 == null) + return ingredient1.isLiquidEqual(liquid1) || ingredient1.isLiquidEqual(liquid2); + else + return (ingredient1.isLiquidEqual(liquid1) && ingredient2.isLiquidEqual(liquid2)) + || (ingredient2.isLiquidEqual(liquid1) && ingredient1.isLiquidEqual(liquid2)); + + } else if(ingredient2 != null) + return ingredient2.isLiquidEqual(liquid1) || ingredient2.isLiquidEqual(liquid2); + else + return false; + + } +} diff --git a/src/common/buildcraft/api/tools/IToolPipette.java b/src/common/buildcraft/api/tools/IToolPipette.java new file mode 100644 index 000000000..8fb8a8c87 --- /dev/null +++ b/src/common/buildcraft/api/tools/IToolPipette.java @@ -0,0 +1,34 @@ +package buildcraft.api.tools; + +import buildcraft.api.liquids.LiquidStack; +import net.minecraft.src.ItemStack; + +public interface IToolPipette { + + /** + * @param pipette ItemStack of the pipette. + * @return Capacity of the pipette. + */ + int getCapacity(ItemStack pipette); + /** + * @param pipette + * @return true if the pipette can pipette. + */ + boolean canPipette(ItemStack pipette); + /** + * Fills the pipette with the given liquid stack. + * @param pipette + * @param liquid + * @param doFill + * @return Amount of liquid used in filling the pipette. + */ + int fill(ItemStack pipette, LiquidStack liquid, boolean doFill); + /** + * Drains liquid from the pipette + * @param pipette + * @param maxDrain + * @param doDrain + * @return Liquid stack representing the liquid and amount drained from the pipette. + */ + LiquidStack drain(ItemStack pipette, int maxDrain, boolean doDrain); +} diff --git a/src/common/buildcraft/api/tools/IToolWrench.java b/src/common/buildcraft/api/tools/IToolWrench.java new file mode 100644 index 000000000..e46a67bd1 --- /dev/null +++ b/src/common/buildcraft/api/tools/IToolWrench.java @@ -0,0 +1,35 @@ +package buildcraft.api.tools; + +import net.minecraft.src.EntityPlayer; + +/*** + * Implement this interface on subclasses of Item to have that item work as a + * wrench for buildcraft + */ +public interface IToolWrench { + + /*** + * Called to ensure that the wrench can be used. To get the ItemStack that + * is used, check player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates for the block being wrenched + * + * @return true if wrenching is allowed, false if not + */ + public boolean canWrench(EntityPlayer player, int x, int y, int z); + + /*** + * Callback after the wrench has been used. This can be used to decrease + * durability or for other purposes. To get the ItemStack that was used, + * check player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates of the block being wrenched + */ + public void wrenchUsed(EntityPlayer player, int x, int y, int z); +} diff --git a/src/common/buildcraft/api/transport/IExtractionHandler.java b/src/common/buildcraft/api/transport/IExtractionHandler.java new file mode 100644 index 000000000..35943853f --- /dev/null +++ b/src/common/buildcraft/api/transport/IExtractionHandler.java @@ -0,0 +1,19 @@ +package buildcraft.api.transport; + +import net.minecraft.src.World; + +/** + * Implement and register with the PipeManager if you want to suppress connections from wooden pipes. + */ +public interface IExtractionHandler { + + /** + * Can this pipe extract items from the block located at these coordinates? + */ + boolean canExtractItems(IPipe pipe, World world, int i, int j, int k); + + /** + * Can this pipe extract liquids from the block located at these coordinates? + */ + boolean canExtractLiquids(IPipe pipe, World world, int i, int j, int k); +} diff --git a/src/common/buildcraft/api/transport/IPassiveItemContribution.java b/src/common/buildcraft/api/transport/IPassiveItemContribution.java new file mode 100644 index 000000000..4c6940686 --- /dev/null +++ b/src/common/buildcraft/api/transport/IPassiveItemContribution.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) SpaceToad, 2012 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.transport; + +import net.minecraft.src.NBTTagCompound; + +public interface IPassiveItemContribution { + + public void readFromNBT(NBTTagCompound nbttagcompound); + + public void writeToNBT(NBTTagCompound nbttagcompound); + +} diff --git a/src/common/buildcraft/api/transport/IPipe.java b/src/common/buildcraft/api/transport/IPipe.java new file mode 100644 index 000000000..f25ccede2 --- /dev/null +++ b/src/common/buildcraft/api/transport/IPipe.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.transport; + +import net.minecraft.src.TileEntity; + +public interface IPipe { + + enum DrawingState { + DrawingPipe, DrawingRedWire, DrawingBlueWire, DrawingGreenWire, DrawingYellowWire, DrawingGate + } + + enum WireColor { + Red, Blue, Green, Yellow; + + public WireColor reverse() { + switch (this) { + case Red: + return Yellow; + case Blue: + return Green; + case Green: + return Blue; + default: + return Red; + } + } + } + + public boolean isWired(WireColor color); + + public boolean hasInterface(); + + public TileEntity getContainer(); + + public boolean isWireConnectedTo(TileEntity tile, WireColor color); + +} diff --git a/src/common/buildcraft/api/transport/IPipeConnection.java b/src/common/buildcraft/api/transport/IPipeConnection.java new file mode 100644 index 000000000..b15e4f25d --- /dev/null +++ b/src/common/buildcraft/api/transport/IPipeConnection.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.transport; + +import buildcraft.api.core.Orientations; + +public interface IPipeConnection { + + public boolean isPipeConnected(Orientations with); +} diff --git a/src/common/buildcraft/api/transport/IPipeEntry.java b/src/common/buildcraft/api/transport/IPipeEntry.java new file mode 100644 index 000000000..c9d5ed2f7 --- /dev/null +++ b/src/common/buildcraft/api/transport/IPipeEntry.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.transport; + +import net.minecraft.src.ItemStack; +import buildcraft.api.core.Orientations; + +/** + * Interface used to put objects into pipes, implemented by pipe tile entities. + */ +public interface IPipeEntry { + + void entityEntering(ItemStack payload, Orientations orientation); + void entityEntering(IPipedItem item, Orientations orientation); + + boolean acceptItems(); + +} diff --git a/src/common/buildcraft/api/transport/IPipeTile.java b/src/common/buildcraft/api/transport/IPipeTile.java new file mode 100644 index 000000000..e7a819f91 --- /dev/null +++ b/src/common/buildcraft/api/transport/IPipeTile.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) SpaceToad, 2011 + * http://www.mod-buildcraft.com + * + * BuildCraft is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * http://www.mod-buildcraft.com/MMPL-1.0.txt + */ + +package buildcraft.api.transport; + +public interface IPipeTile { + + IPipe getPipe(); + + boolean isInitialized(); +} diff --git a/src/common/buildcraft/api/transport/IPipedItem.java b/src/common/buildcraft/api/transport/IPipedItem.java new file mode 100644 index 000000000..2caf1a3b4 --- /dev/null +++ b/src/common/buildcraft/api/transport/IPipedItem.java @@ -0,0 +1,100 @@ +package buildcraft.api.transport; + +import buildcraft.api.core.Orientations; +import buildcraft.api.core.Position; +import buildcraft.api.core.SafeTimeTracker; +import net.minecraft.src.EntityItem; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; + +public interface IPipedItem { + + public abstract void remove(); + + /* GETTING & SETTING */ + public abstract void setWorld(World world); + + public abstract Position getPosition(); + + public abstract void setPosition(double x, double y, double z); + + /** + * @return the speed + */ + public abstract float getSpeed(); + + /** + * @param speed the speed to set + */ + public abstract void setSpeed(float speed); + + /** + * @return the item + */ + public abstract ItemStack getItemStack(); + + /** + * @param item the item to set + */ + public abstract void setItemStack(ItemStack item); + + /** + * @return the container + */ + public abstract TileEntity getContainer(); + + /** + * @param container the container to set + */ + public abstract void setContainer(TileEntity container); + + /** + * @return the synchroTracker + */ + public abstract SafeTimeTracker getSynchroTracker(); + + /** + * @param synchroTracker the synchroTracker to set + */ + public abstract void setSynchroTracker(SafeTimeTracker synchroTracker); + + /** + * @return the deterministicRandomization + */ + public abstract int getDeterministicRandomization(); + + /** + * @param deterministicRandomization the deterministicRandomization to set + */ + public abstract void setDeterministicRandomization(int deterministicRandomization); + + /** + * @return the entityId + */ + public abstract int getEntityId(); + + /** + * @param entityId the entityId to set + */ + public abstract void setEntityId(int entityId); + + /* SAVING & LOADING */ + public abstract void readFromNBT(NBTTagCompound nbttagcompound); + + public abstract void writeToNBT(NBTTagCompound nbttagcompound); + + public abstract EntityItem toEntityItem(Orientations dir); + + public abstract float getEntityBrightness(float f); + + public abstract boolean isCorrupted(); + + public abstract void addContribution(String key, IPassiveItemContribution contribution); + + public abstract IPassiveItemContribution getContribution(String key); + + public abstract boolean hasContributions(); + +} \ No newline at end of file diff --git a/src/common/buildcraft/api/transport/PipeManager.java b/src/common/buildcraft/api/transport/PipeManager.java new file mode 100644 index 000000000..c4ac01e77 --- /dev/null +++ b/src/common/buildcraft/api/transport/PipeManager.java @@ -0,0 +1,45 @@ +package buildcraft.api.transport; + +import java.util.TreeMap; +import java.util.ArrayList; +import java.util.List; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Side; + +import net.minecraft.src.World; + +public abstract class PipeManager { + + private static TreeMap allServerEntities = new TreeMap(); + private static TreeMap allClientEntities = new TreeMap(); + + public static List extractionHandlers = new ArrayList(); + + public static void registerExtractionHandler(IExtractionHandler handler) { + extractionHandlers.add(handler); + } + + public static boolean canExtractItems(IPipe pipe, World world, int i, int j, int k) { + for(IExtractionHandler handler : extractionHandlers) + if(!handler.canExtractItems(pipe, world, i, j, k)) + return false; + + return true; + } + + public static boolean canExtractLiquids(IPipe pipe, World world, int i, int j, int k) { + for(IExtractionHandler handler : extractionHandlers) + if(!handler.canExtractLiquids(pipe, world, i, j, k)) + return false; + + return true; + } + + public static TreeMap getAllEntities(){ + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) { + return allClientEntities; + } + return allServerEntities; + } +} diff --git a/src/common/dan200/computer/api/IComputerAccess.java b/src/common/dan200/computer/api/IComputerAccess.java new file mode 100644 index 000000000..52a034e22 --- /dev/null +++ b/src/common/dan200/computer/api/IComputerAccess.java @@ -0,0 +1,131 @@ + +package dan200.computer.api; + +/** + * The interface passed to peripherals by computers or turtles, providing methods + * that they can call. This should not be implemented by your classes. Do not interact + * with computers except via this interface. + */ +public interface IComputerAccess +{ + /** + * Creates a new numbered directory in a subPath of the users game save, and return that number. To be used with mountSaveDir.
+ * For example: n = createNewSaveDir( "computer/cdrom" ), will create a new + * numbered folder in the "computer/cdrom" subdirectory of the users save file, and return that number. + * mountSaveDir( "computer/rom", n ) could then be used to mount that folder onto the computers directory + * structure, and the value n could be saved out and used again in future to give the peripheral + * persistant storage. + * @param subPath A relative file path from the users world save, where the directory should be located. + * @return The numeric represenation of the name of the folder created. Will be positive. + * @see #mountSaveDir(String, String, int, boolean, long) + */ + public int createNewSaveDir( String subPath ); + + /** + * Equivalent to mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly, long spaceLimit ) with no space limit. + * Mounts created with this method will have unlimited capacity. + * @see #mountSaveDir(String, String, int, boolean, long) + */ + public String mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly ); + + /** + * Mounts a directory into the computers file system, from a real directory a subPath of the users game save, + * with a numerical name. To be used with createNewSaveDir.
+ * For example: n = createNewSaveDir( "computer/cdrom" ), will create a new + * numbered folder in the "computer/cdrom" subdirectory of the users save file, and return that number. + * mountSaveDir( "computer/rom", n ) could then be used to mount that folder onto the computers directory + * structure, and the value n can be saved out by the peripheral and used again, to give the peripheral + * persistant storage.
+ * When a directory is mounted, it will appear in the computers file system, and the user will be + * able to use file operation to read from and write to the directory (unless readOnly, then only writes will be allowed). + * @param desiredLocation The desired location in the computers file system where you would like the directory to appear. + * If this location already exists, a number will be appended until a free name is found, and the + * actual location will be returned. eg: "cdrom" can become "cdrom2" if two peripherals attempt to + * mount "cdrom", or a "cdrom" folder already exists. + * @param subPath The real relative file path from the users world save, where the directory to mount can be located. + * @param id The numerical name of the folder to mount from the subPath: ex: mountSaveDir( "cdrom", "computer/cdrom", 7 ) + * will mount the directory "computer/cdrom/7". Use createNewSaveDir to obtain a unique directory id. + * @param readOnly Whether the computer will be disallowed from making changes to the mounted directory and modifing or creating files therin. + * @param spaceLimit The size limit of the mount, in bytes. + * @return The location in the computers file system where the directory was mounted. This may differ from "desiredLocation", so the + * return value should be kept track of so the folder can be unmounted later. + * @see #createNewSaveDir(String) + * @see #mountFixedDir(String, String, boolean, long) + * @see #unmount(String) + */ + public String mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly, long spaceLimit ); + + /** + * Equivalent to mountFixedDir( String desiredLocation, String path, boolean readOnly, long spaceLimit ) with no space limit. + * Mounts created with this method will have unlimited capacity. + * @see #mountFixedDir(String, String, boolean, long) + */ + public String mountFixedDir( String desiredLocation, String path, boolean readOnly ); + + /** + * Mounts a directory into the computers file system, from a real directory in the Minecraft install folder.
+ * For example: mountFixedDir( "stuff", "mods/mymod/lua/stuff", true ), will mount the "lua/stuff" folder from + * your mod's directory into the computers filesystem at the location "stuff", with readonly permission, giving the + * computer access to those files.
+ * When a directory is mounted, it will appear in the computers file system, and the user will be + * able to use file operation to read from and write to the directory (unless readOnly, then only writes will be allowed).
+ * mountFixedDir can also be used to mount files, for example: mountFixedDir( "rom/apis/myapi", "mods/mymod/lua/myapi.lua", true ) can + * be used to have the peripheral install an API onto the computer it attaches to. + * @param desiredLocation The desired location in the computers file system where you would like the directory to appear. + * If this location already exists, a number will be appended until a free name is found, and the + * actual location will be returned. eg: "cdrom" can become "cdrom2" if two peripherals attempt to + * mount "cdrom", or a "cdrom" folder already exists. + * @param subPath The real relative file path from the minecraft install root, where the directory to mount can be located. + * @param readOnly Whether the computer will be disallowed from making changes to the mounted directory and modifing or creating files therin. + * @param spaceLimit The size limit of the mount, in bytes. + * @return The location in the computers file system where the directory was mounted. This may differ from "desiredLocation", so the + * return value should be kept track of so the folder can be unmounted later. + * @see #mountSaveDir(String, String, int, boolean, long) + * @see #unmount(String) + */ + public String mountFixedDir( String desiredLocation, String path, boolean readOnly, long spaceLimit ); + + /** + * Unmounts a directory previously mounted onto the computers file system by mountSaveDir or mountFixedDir.
+ * When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be able to + * access it. All directories mounted by a mountFixedDir or mountSaveDir are automatically unmounted when the peripheral + * is attached if they have not been explicitly unmounted. + * @param location The desired location in the computers file system of the directory to unmount. + * This must be the location of a directory previously mounted by mountFixedDir() or mountSaveDir(), as + * indicated by their return value. + * @see #mountSaveDir(String, String, int, boolean, long) + * @see #mountFixedDir(String, String, boolean, long) + */ + public void unmount( String location ); + + /** + * Returns the numerical ID of this computer.
+ * This is the same number obtained by calling os.getComputerID() or running the "id" program from lua, + * and is guarunteed unique. This number will be positive. + * @return The identifier. + */ + public int getID(); + + /** + * Equivalent to queueEvent( String event, Object[] arguments ) with an empty arguments array. + * @see #queueEvent(String, Object[]) + */ + public void queueEvent( String event ); + + /** + * Causes an event to be raised on this computer, which the computer can respond to by calling + * os.pullEvent(). This can be used to notify the computer when things happen in the world or to + * this peripheral. + * @param event A string identifying the type of event that has occurred, this will be + * returned as the first value from os.pullEvent(). It is recommended that you + * you choose a name that is unique, and recognisable as originating from your + * peripheral. eg: If your peripheral type is "button", a suitable event would be + * "button_pressed". + * @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will + * be supplied as extra return values to os.pullEvent(). Objects in the array will be converted + * to lua data types in the same fashion as the return values of IPeripheral.callMethod().
+ * You may supply null to indicate that no arguments are to be supplied. + * @see IPeripheral#callMethod + */ + public void queueEvent( String event, Object[] arguments ); +} diff --git a/src/common/dan200/computer/api/IPeripheral.java b/src/common/dan200/computer/api/IPeripheral.java new file mode 100644 index 000000000..8dfeb8dce --- /dev/null +++ b/src/common/dan200/computer/api/IPeripheral.java @@ -0,0 +1,103 @@ + +package dan200.computer.api; + +/** + * The interface that defines a peripheral. This should be implemented by the + * TileEntity of any block that you wish to be interacted with by + * computer or turtle. + */ +public interface IPeripheral +{ + /** + * Should return a string that uniquely identifies this type of peripheral. + * This can be queried from lua by calling peripheral.getType() + * @return A string identifying the type of peripheral. + */ + public String getType(); + + /** + * Should return an array of strings that identify the methods that this + * peripheral exposes to Lua. This will be called once before each attachment, + * and should not change when called multiple times. + * @return An array of strings representing method names. + * @see #callMethod + */ + public String[] getMethodNames(); + + /** + * This is called when a lua program on an attached computer calls peripheral.call() with + * one of the methods exposed by getMethodNames().
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is making the call. Remember that multiple + * computers can be attached to a peripheral at once. + * @param method An integer identifying which of the methods from getMethodNames() the computer + * wishes to call. The integer indicates the index into the getMethodNames() table + * that corresponds to the string passed into peripheral.call() + * @param arguments An array of objects, representing the arguments passed into peripheral.call().
+ * Lua values of type "string" will be represented by Object type String.
+ * Lua values of type "number" will be represented by Object type Double.
+ * Lua values of type "boolean" will be represented by Object type Boolean.
+ * Lua values of any other type will be represented by a null object.
+ * This array will be empty if no arguments are passed. + * @return An array of objects, representing values you wish to return to the lua program.
+ * Integers, Doubles, Floats, Strings, Booleans and null be converted to their corresponding lua type.
+ * All other types will be converted to nil.
+ * You may return null to indicate no values should be returned. + * @throws Exception If you throw any exception from this function, a lua error will be raised with the + * same message as your exception. Use this to throw appropriate errors if the wrong + * arguments are supplied to your method. + * @see #getMethodNames + */ + public Object[] callMethod( IComputerAccess computer, int method, Object[] arguments ) throws Exception; + + /** + * Is called before the computer attempts to attach to the peripheral, and should return whether to allow + * the attachment. Use this to restrict the number of computers that can attach, or to limit attachments to + * certain world directions.
+ * If true is returned, attach() will be called shortly afterwards, and the computer will be able to make method calls. + * If false is returned, attach() will not be called, and the peripheral will be invisible to the computer. + * @param side The world direction (0=bottom, 1=top, etc) that the computer lies relative to the peripheral. + * @return Whether to allow the attachment, as a boolean. + * @see #attach + */ + public boolean canAttachToSide( int side ); + + /** + * Is called when canAttachToSide has returned true, and a computer is attaching to the peripheral. + * This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a peripheral, + * or when a turtle travels into a square next to a peripheral. + * Between calls to attach() and detach(), the attached computer can make method calls on the peripheral using peripheral.call(). + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when attachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is being attached. Remember that multiple + * computers can be attached to a peripheral at once. + * @param computerSide A string indicating which "side" of the computer the peripheral is attaching, + * relative to the computers orientation. This value will be one of "top", "bottom", + * "left", "right", "front" or "back". This can be used to uniquely identify the + * peripheral when raising events or returning values to the computer. + * @see #canAttachToSide + * @see #detach + */ + public void attach( IComputerAccess computer, String computerSide ); + + /** + * Is called when a computer is detaching from the peripheral. + * This will occur when a computer shuts down, when the peripheral is removed while attached to computers, + * or when a turtle moves away from a square attached to a peripheral. + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is being detached. Remember that multiple + * computers can be attached to a peripheral at once. + * @see #canAttachToSide + * @see #detach + */ + public void detach( IComputerAccess computer ); +} diff --git a/src/common/dan200/turtle/api/ITurtleAccess.java b/src/common/dan200/turtle/api/ITurtleAccess.java new file mode 100644 index 000000000..e60327251 --- /dev/null +++ b/src/common/dan200/turtle/api/ITurtleAccess.java @@ -0,0 +1,144 @@ + +package dan200.turtle.api; + +/** + * The interface passed to upgrades by turtles, providing methods that they can call. + * This should not be implemented by your classes. Do not interact with turtles except via this interface and ITurtleUpgrade. + */ +public interface ITurtleAccess +{ + /** + * Returns the world in which the turtle resides. + * @return the world in which the turtle resides. + */ + public net.minecraft.src.World getWorld(); + + /** + * Returns a vector containing the integer block co-ordinates at which the turtle resides. + * @return a vector containing the integer block co-ordinates at which the turtle resides. + */ + public net.minecraft.src.Vec3 getPosition(); + + /** + * Returns the world direction the turtle is currently facing. + * @return the world direction the turtle is currently facing. + */ + public int getFacingDir(); + + /** + * Returns the size of the turtles inventory, in number of slots. This will currently always be 16. + * @return the size of the turtles inventory, in number of slots. This will currently always be 16. + */ + public int getInventorySize(); + + /** + * Returns which slot the turtle currently has selected in its inventory using turtle.select(). + * Unlike the 1-based lua representation, this will be between 0 and getInventorySize() - 1. + * @return which slot the turtle currently has selected in its inventory + */ + public int getSelectedSlot(); + + /** + * Returns the item stack that the turtle has in one of its inventory slots. + * @param index which inventory slot to retreive, should be between 0 and getInventorySize() - 1 + * @return the item stack that the turtle has in one of its inventory slots. May be null. + */ + public net.minecraft.src.ItemStack getSlotContents( int index ); + + /** + * Changes the item stack that the turtle has in one of its inventory slots. + * @param index which inventory slot to change, should be between 0 and getInventorySize() - 1 + * @param stack an item stack to put in the slot. May be null. + */ + public void setSlotContents( int index, net.minecraft.src.ItemStack stack ); + + /** + * Tries to store an item stack into the turtles current inventory, starting from the turtles + * currently selected inventory slot. + * @param stack The item stack to try and store. + * @return true if the stack was completely stored in the inventory, false if + * it was only partially stored, or could not fit at all. If false is returned + * and the stack was partially stored, the ItemStack passed into "stack" will now + * represent the stack of items that is left over. + */ + public boolean storeItemStack( net.minecraft.src.ItemStack stack ); + + /** + * Drops an item stack from the turtle onto the floor, or into an inventory is there is one + * adjacent to the turtle in the direction specified. + * @param stack The item stack to drop. + * @param dir The world direction to drop the item + * @return true if the stack was dropped, or completely stored in the adjacent inventory, false if + * it was only partially stored in the adjacent inventory, or could not fit at all. If false is returned + * and the stack was partially stored, the ItemStack passed into "stack" will now + * represent the stack of items that is left over. + */ + public boolean dropItemStack( net.minecraft.src.ItemStack stack, int dir ); + + /** + * "Deploys" an item stack in the direction specified. This simulates a player right clicking, and calls onItemUse() on the Item class. + * Will return true if some kind of deployment happened, and may modify the item stack. For block item types, this can be + * used to place blocks. Some kinds of items (such as shears when facing a sheep) may modify the turtles inventory during this call. + * @param stack The item stack to deploy + * @param dir The world direction to deploy the item + * @return true if the stack was deployed, false if it was not. + */ + public boolean deployWithItemStack( net.minecraft.src.ItemStack stack, int dir ); + + /** + * Tries to "attack" entities with an item stack in the direction specified. This simulates a player left clicking, but will + * not affect blocks. If an entity is attacked and killed during this call, its dropped items will end up in the turtles + * inventory. + * @param stack The item stack to attack with + * @param dir The world direction to attack with the item + * @return true if something was attacked, false if it was not + */ + public boolean attackWithItemStack( net.minecraft.src.ItemStack stack, int dir, float damageMultiplier ); + + /** + * Returns the current fuel level of the turtle, this is the same integer returned by turtle.getFuelLevel(), + * that decreases by 1 every time the turtle moves. Can be used to have your tool or peripheral require or supply + * fuel to the turtle. + * @return the fuel level + */ + public int getFuelLevel(); + + /** + * Tries to increase the fuel level of a turtle by burning an item stack. If the item passed in is a fuel source, fuel + * will increase and true will be returned. Otherwise, nothing will happen and false will be returned. + * @param stack The stack to try to refuel with + * @return Whether the turtle was refueled + */ + public boolean refuelWithItemStack( net.minecraft.src.ItemStack stack ); + + /** + * Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle. + * @return Whether the turtle was able to consume the ammount of fuel specified. Will return false if you supply a number + * greater than the current fuel level of the turtle. + */ + public boolean consumeFuel( int fuel ); + + /** + * Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed + * on the main thread, so are guaranteed to be able to access Minecraft objects safely, and will be queued up + * with the turtles standard movement and tool commands. An issued command will return an unique integer, which will + * be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has completed. Look at the + * lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality. + * @param handler an object which will execute the custom command when its point in the queue is reached + * @return the unique command identifier described above + * @see ITurtleCommandHandler + */ + public int issueCommand( ITurtleCommandHandler handler ); + + /** + * Returns the upgrade on the specified side of the turtle, if there is one. + * @return the upgrade on the specified side of the turtle, if there is one. + */ + public ITurtleUpgrade getUpgrade( TurtleSide side ); + + /** + * Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one. + * @return the peripheral created by the upgrade on the specified side of the turtle, if there is one. + */ + public ITurtlePeripheral getPeripheral( TurtleSide side ); +} diff --git a/src/common/dan200/turtle/api/ITurtleCommandHandler.java b/src/common/dan200/turtle/api/ITurtleCommandHandler.java new file mode 100644 index 000000000..5d397c875 --- /dev/null +++ b/src/common/dan200/turtle/api/ITurtleCommandHandler.java @@ -0,0 +1,20 @@ + +package dan200.turtle.api; + +/** + * An interface for objects executing custom turtle commands, used with ITurtleAccess.issueCommand + * @see ITurtleAccess#issueCommand( ITurtleCommandHandler ) + */ +public interface ITurtleCommandHandler +{ + /** + * Will be called by the turtle on the main thread when it is time to execute the custom command. + * The handler should either perform the work of the command, and return true for success, or return + * false to indicate failure if the command cannot be executed at this time. + * @param turtle access to the turtle for whom the command was issued + * @return true for success, false for failure. If true is returned, the turtle will wait 0.4 seconds + * before executing the next command in its queue, as it does for the standard turtle commands. + * @see ITurtleAccess#issueCommand( ITurtleCommandHandler ) + */ + public boolean handleCommand( ITurtleAccess turtle ); +} diff --git a/src/common/dan200/turtle/api/ITurtlePeripheral.java b/src/common/dan200/turtle/api/ITurtlePeripheral.java new file mode 100644 index 000000000..6d56ee90d --- /dev/null +++ b/src/common/dan200/turtle/api/ITurtlePeripheral.java @@ -0,0 +1,22 @@ + +package dan200.turtle.api; +import dan200.computer.api.IPeripheral; + +/** + * A subclass of IPeripheral specifically for peripherals + * created by ITurtleUpgrade's of type Peripheral. When an + * ITurtlePeripheral is created, its IPeripheral methods will be called + * just as if the peripheral was a seperate adjacent block in the world, + * and update() will be called once per tick. + * @see ITurtleUpgrade + */ +public interface ITurtlePeripheral extends IPeripheral +{ + /** + * A method called on each created turtle peripheral once per tick, + * over the lifetime of the turtle. May be used to update the state + * of the peripheral, and may interact with IComputerAccess or ITurtleAccess + * however it likes at this time. + */ + public void update(); +} diff --git a/src/common/dan200/turtle/api/ITurtleUpgrade.java b/src/common/dan200/turtle/api/ITurtleUpgrade.java new file mode 100644 index 000000000..aff9c448c --- /dev/null +++ b/src/common/dan200/turtle/api/ITurtleUpgrade.java @@ -0,0 +1,97 @@ + +package dan200.turtle.api; + +/** + * The primary interface for defining an upgrade for Turtles. A turtle upgrade + * can either be a new tool, or a new peripheral. + * @see TurtleAPI#registerUpgrade( ITurtleUpgrade ) + */ +public interface ITurtleUpgrade +{ + /** + * Gets a unique numerical identifier representing this type of turtle upgrade. + * Like Minecraft block and item IDs, you should strive to make this number unique + * among all turtle upgrades that have been released for ComputerCraft. + * The ID must be in the range 64 to 255, as the ID is stored as an 8-bit value, + * and 0-64 is reserved for future use by ComputerCraft. The upgrade will + * fail registration if an already used ID is specified. + * @see TurtleAPI#registerUpgrade( ITurtleUpgrade ) + */ + public int getUpgradeID(); + + /** + * Return a String to describe this type of upgrade in turtle item names. + * Examples of built-in adjectives are "Wireless", "Mining" and "Crafty". + */ + public String getAdjective(); + + /** + * Return whether this upgrade adds a tool or a peripheral to the turtle. + * Currently, turtle crafting is restricted to one tool & one peripheral per turtle. + * @see TurtleUpgradeType for the differences between the two. + */ + public TurtleUpgradeType getType(); + + /** + * Return an item stack representing the type of item that a turtle must be crafted + * with to create a turtle which holds this upgrade. + * Currently, turtle crafting is restricted to one tool & one peripheral per turtle. + */ + public net.minecraft.src.ItemStack getCraftingItem(); + + /** + * Return whether this turtle upgrade is an easter egg, and should be attempted to be hidden + * from the creative mode inventory and recipe book plugins. + */ + public boolean isSecret(); + + /** + * Return which texture file should be used to render this upgrade when rendering a turtle + * in the world or as an item. + * @param turtle Access to the turtle that is being rendered, this will be null when + * the method is being called to render the turtle as an Item. For turtles in the world, + * this can be used to have the upgrade change appearance based on state. + * @param side Which side of the turtle (left or right) that the upgrade being rendered resides on. + * @see #getIconIndex + */ + public String getIconTexture( ITurtleAccess turtle, TurtleSide side ); + + /** + * Return which icon index should be used to render this upgrade when rendering a turtle + * in the world or as an item. + * @param turtle Access to the turtle that is being rendered, this will be null when + * the method is being called to render the turtle as an Item. For turtles in the world, + * this can be used to have the upgrade change appearance based on state. + * @param side Which side of the turtle (left or right) that the upgrade being rendered resides on. + * @see #getIconTexture + */ + public int getIconIndex( ITurtleAccess turtle, TurtleSide side ); + + /** + * Will only be called for Peripheral upgrades. Creates a peripheral for a turtle + * being placed using this upgrade. The peripheral created will be stored + * for the lifetime of the turtle, will have update() called once-per-tick, and will be + * attach'd detach'd and have methods called in the same manner as a Computer peripheral. + * @param turtle Access to the turtle that the peripheral is being created for. + * @param side Which side of the turtle (left or right) that the upgrade resides on. + * @returns The newly created peripheral. You may return null if this upgrade is a Tool + * and this method is not expected to be called. + */ + public ITurtlePeripheral createPeripheral( ITurtleAccess turtle, TurtleSide side ); + + /** + * Will only be called for Tool upgrades. Called when turtle.dig() or turtle.attack() is called + * by the turtle, and the tool is required to do some work. + * @param turtle Access to the turtle that the tool resides on. + * @param side Which side of the turtle (left or right) the tool resides on. + * @param verb Which action (dig or attack) the turtle is being called on to perform. + * @param direction Which world direction the action should be performed in, relative to the turtles + * position. This will either be up, down, or the direction the turtle is facing, depending on + * whether dig, digUp or digDown was called. + * @return Whether the turtle was able to perform the action, and hence whether the turtle.dig() + * or turtle.attack() lua method should return true. If true is returned, the tool will perform + * a swinging animation. You may return false if this upgrade is a Peripheral + * and this method is not expected to be called. + */ + public boolean useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, int direction ); +} diff --git a/src/common/dan200/turtle/api/TurtleAPI.java b/src/common/dan200/turtle/api/TurtleAPI.java new file mode 100644 index 000000000..ab4264e8a --- /dev/null +++ b/src/common/dan200/turtle/api/TurtleAPI.java @@ -0,0 +1,73 @@ + +package dan200.turtle.api; +import java.lang.reflect.Method; + +/** + * The static entry point to the ComputerCraft Turtle Upgrade API. + * Members in this class must be called after mod_CCTurtle has been initialised, + * but may be called before it is loaded. + */ +public class TurtleAPI +{ + /** + * Registers a new turtle upgrade for use in the ComputerCraft. After calling this, + * users should be able to craft Turtles with your new upgrade. It is recommended to call + * this during the load() method of your mod. + * @throws Exception if you try to register an upgrade with an already used or reserved upgradeID + * @see ITurtleUpgrade + */ + public static void registerUpgrade( ITurtleUpgrade upgrade ) + { + if( upgrade != null ) + { + findCCTurtle(); + if( ccTurtle_registerTurtleUpgrade != null ) + { + try { + ccTurtle_registerTurtleUpgrade.invoke( null, new Object[]{ upgrade } ); + } catch( Exception e ) { + // It failed + } + } + } + } + + // The functions below here are private, and are used to interface with the non-API ComputerCraft classes. + // Reflection is used here so you can develop your mod in MCP without decompiling ComputerCraft and including + // it in your solution. + + private static void findCCTurtle() + { + if( !ccTurtleSearched ) { + // Search for CCTurtle + try { + ccTurtle = Class.forName( "dan200.turtle.shared.CCTurtle" ); + ccTurtle_registerTurtleUpgrade = findCCTurtleMethod( "registerTurtleUpgrade", new Class[] { + ITurtleUpgrade.class + } ); + + } catch( ClassNotFoundException e ) { + System.out.println("ComputerCraft: CCTurtle not found."); + + } finally { + ccTurtleSearched = true; + + } + } + } + + private static Method findCCTurtleMethod( String name, Class[] args ) + { + try { + return ccTurtle.getMethod( name, args ); + + } catch( NoSuchMethodException e ) { + System.out.println("ComputerCraft: CCTurtle method " + name + " not found."); + return null; + } + } + + private static boolean ccTurtleSearched = false; + private static Class ccTurtle = null; + private static Method ccTurtle_registerTurtleUpgrade = null; +} diff --git a/src/common/dan200/turtle/api/TurtleSide.java b/src/common/dan200/turtle/api/TurtleSide.java new file mode 100644 index 000000000..bc64f7110 --- /dev/null +++ b/src/common/dan200/turtle/api/TurtleSide.java @@ -0,0 +1,18 @@ + +package dan200.turtle.api; + +/** + * An enum representing the two sides of the turtle that a turtle upgrade might reside. + */ +public enum TurtleSide +{ + /** + * The turtles left side (where the pickaxe usually is on a Wireless Mining Turtle) + */ + Left, + + /** + * The turtles right side (where the modem usually is on a Wireless Mining Turtle) + */ + Right, +} diff --git a/src/common/dan200/turtle/api/TurtleUpgradeType.java b/src/common/dan200/turtle/api/TurtleUpgradeType.java new file mode 100644 index 000000000..d1b694999 --- /dev/null +++ b/src/common/dan200/turtle/api/TurtleUpgradeType.java @@ -0,0 +1,22 @@ + +package dan200.turtle.api; + +/** + * An enum representing the two different types of upgrades that an ITurtleUpgrade + * implementation can add to a turtle. + * @see ITurtleUpgrade + */ +public enum TurtleUpgradeType +{ + /** + * A tool is rendered as an item on the side of the turtle, and responds to the turtle.dig() + * and turtle.attack() methods (Such as pickaxe or sword on Mining and Melee turtles). + */ + Tool, + + /** + * A peripheral adds a special peripheral which is attached to the side of the turtle, + * and can be interacted with the peripheral API (Such as the modem on Wireless Turtles). + */ + Peripheral, +} diff --git a/src/common/dan200/turtle/api/TurtleVerb.java b/src/common/dan200/turtle/api/TurtleVerb.java new file mode 100644 index 000000000..4da83c6cf --- /dev/null +++ b/src/common/dan200/turtle/api/TurtleVerb.java @@ -0,0 +1,21 @@ + +package dan200.turtle.api; + +/** + * An enum representing the two different actions that an ITurtleUpgrade of type + * Tool may be called on to perform by a turtle. + * @see ITurtleUpgrade + * @see ITurtleUpgrade#useTool + */ +public enum TurtleVerb +{ + /** + * The turtle called turtle.dig(), turtle.digUp() or turtle.digDown() + */ + Dig, + + /** + * The turtle called turtle.attack(), turtle.attackUp() or turtle.attackDown() + */ + Attack, +} diff --git a/src/common/ic2/api/BaseSeed.java b/src/common/ic2/api/BaseSeed.java new file mode 100644 index 000000000..bcc37a04b --- /dev/null +++ b/src/common/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/common/ic2/api/CropCard.java b/src/common/ic2/api/CropCard.java new file mode 100644 index 000000000..c1c558571 --- /dev/null +++ b/src/common/ic2/api/CropCard.java @@ -0,0 +1,475 @@ +package ic2.api; + +import java.util.HashMap; + +import net.minecraft.src.Entity; +import net.minecraft.src.EntityLiving; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.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/common/ic2/api/Crops.java b/src/common/ic2/api/Crops.java new file mode 100644 index 000000000..e2fbe1aa1 --- /dev/null +++ b/src/common/ic2/api/Crops.java @@ -0,0 +1,47 @@ +package ic2.api; + +import java.util.HashMap; + +import net.minecraft.src.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/common/ic2/api/Direction.java b/src/common/ic2/api/Direction.java new file mode 100644 index 000000000..52381c16e --- /dev/null +++ b/src/common/ic2/api/Direction.java @@ -0,0 +1,106 @@ +package ic2.api; + +import net.minecraft.src.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: Direction.values()) { + 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; +} + diff --git a/src/common/ic2/api/ElectricItem.java b/src/common/ic2/api/ElectricItem.java new file mode 100644 index 000000000..3f4a4972e --- /dev/null +++ b/src/common/ic2/api/ElectricItem.java @@ -0,0 +1,128 @@ +package ic2.api; + +import java.lang.reflect.Method; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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/common/ic2/api/EnergyNet.java b/src/common/ic2/api/EnergyNet.java new file mode 100644 index 000000000..2e98537e9 --- /dev/null +++ b/src/common/ic2/api/EnergyNet.java @@ -0,0 +1,119 @@ +package ic2.api; + +import java.lang.reflect.Method; + +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; + +/** + * 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() + ".common.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 + */ + public void addTileEntity(TileEntity addedTileEntity) { + try { + if (EnergyNet_addTileEntity == null) EnergyNet_addTileEntity = Class.forName(getPackage() + ".common.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 + */ + public void removeTileEntity(TileEntity removedTileEntity) { + try { + if (EnergyNet_removeTileEntity == null) EnergyNet_removeTileEntity = Class.forName(getPackage() + ".common.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 + */ + public int emitEnergyFrom(IEnergySource energySource, int amount) { + try { + if (EnergyNet_emitEnergyFrom == null) EnergyNet_emitEnergyFrom = Class.forName(getPackage() + ".common.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 + */ + public long getTotalEnergyConducted(TileEntity tileEntity) { + try { + if (EnergyNet_getTotalEnergyConducted == null) EnergyNet_getTotalEnergyConducted = Class.forName(getPackage() + ".common.EnergyNet").getMethod("getTotalEnergyConducted", TileEntity.class); + + return ((Long) EnergyNet_getTotalEnergyConducted.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) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else 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; +} + diff --git a/src/common/ic2/api/ExplosionWhitelist.java b/src/common/ic2/api/ExplosionWhitelist.java new file mode 100644 index 000000000..d36ccc362 --- /dev/null +++ b/src/common/ic2/api/ExplosionWhitelist.java @@ -0,0 +1,46 @@ +package ic2.api; + +import java.util.*; + +import net.minecraft.src.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/common/ic2/api/IBoxable.java b/src/common/ic2/api/IBoxable.java new file mode 100644 index 000000000..9125954a8 --- /dev/null +++ b/src/common/ic2/api/IBoxable.java @@ -0,0 +1,18 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/IElectricItem.java b/src/common/ic2/api/IElectricItem.java new file mode 100644 index 000000000..20a19e477 --- /dev/null +++ b/src/common/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 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/common/ic2/api/IEnergyAcceptor.java b/src/common/ic2/api/IEnergyAcceptor.java new file mode 100644 index 000000000..4b0019238 --- /dev/null +++ b/src/common/ic2/api/IEnergyAcceptor.java @@ -0,0 +1,20 @@ +package ic2.api; + +import net.minecraft.src.TileEntity; + +/** + * 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/common/ic2/api/IEnergyConductor.java b/src/common/ic2/api/IEnergyConductor.java new file mode 100644 index 000000000..3d755404f --- /dev/null +++ b/src/common/ic2/api/IEnergyConductor.java @@ -0,0 +1,51 @@ +package ic2.api; + +/** + * 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/common/ic2/api/IEnergyEmitter.java b/src/common/ic2/api/IEnergyEmitter.java new file mode 100644 index 000000000..94699b9a5 --- /dev/null +++ b/src/common/ic2/api/IEnergyEmitter.java @@ -0,0 +1,21 @@ +package ic2.api; + +import net.minecraft.src.TileEntity; + +/** + * 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/common/ic2/api/IEnergySink.java b/src/common/ic2/api/IEnergySink.java new file mode 100644 index 000000000..a0ed9a55a --- /dev/null +++ b/src/common/ic2/api/IEnergySink.java @@ -0,0 +1,23 @@ +package ic2.api; + +/** + * Allows a tile entity (mostly a machine) to receive energy. + */ +public interface IEnergySink extends IEnergyAcceptor { + /** + * Determine whether the sink requires energy. + * + * @return Whether the sink is requiring energy + */ + boolean 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); +} + diff --git a/src/common/ic2/api/IEnergySource.java b/src/common/ic2/api/IEnergySource.java new file mode 100644 index 000000000..39d14a20d --- /dev/null +++ b/src/common/ic2/api/IEnergySource.java @@ -0,0 +1,15 @@ +package ic2.api; + +/** + * 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/common/ic2/api/IEnergyStorage.java b/src/common/ic2/api/IEnergyStorage.java new file mode 100644 index 000000000..a89bd7dcd --- /dev/null +++ b/src/common/ic2/api/IEnergyStorage.java @@ -0,0 +1,27 @@ +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(); + + /** + * 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(); +} diff --git a/src/common/ic2/api/IEnergyTile.java b/src/common/ic2/api/IEnergyTile.java new file mode 100644 index 000000000..10445432a --- /dev/null +++ b/src/common/ic2/api/IEnergyTile.java @@ -0,0 +1,18 @@ +package ic2.api; + +/** + * 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/common/ic2/api/IMetalArmor.java b/src/common/ic2/api/IMetalArmor.java new file mode 100644 index 000000000..fe8db2edf --- /dev/null +++ b/src/common/ic2/api/IMetalArmor.java @@ -0,0 +1,20 @@ +package ic2.api; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.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/common/ic2/api/INetworkClientTileEntityEventListener.java b/src/common/ic2/api/INetworkClientTileEntityEventListener.java new file mode 100644 index 000000000..594f1d7f8 --- /dev/null +++ b/src/common/ic2/api/INetworkClientTileEntityEventListener.java @@ -0,0 +1,17 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/INetworkDataProvider.java b/src/common/ic2/api/INetworkDataProvider.java new file mode 100644 index 000000000..da393868f --- /dev/null +++ b/src/common/ic2/api/INetworkDataProvider.java @@ -0,0 +1,18 @@ +package ic2.api; + +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/common/ic2/api/INetworkItemEventListener.java b/src/common/ic2/api/INetworkItemEventListener.java new file mode 100644 index 000000000..a0126b399 --- /dev/null +++ b/src/common/ic2/api/INetworkItemEventListener.java @@ -0,0 +1,18 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/INetworkTileEntityEventListener.java b/src/common/ic2/api/INetworkTileEntityEventListener.java new file mode 100644 index 000000000..4433cb898 --- /dev/null +++ b/src/common/ic2/api/INetworkTileEntityEventListener.java @@ -0,0 +1,14 @@ +package ic2.api; + +/** + * 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/common/ic2/api/INetworkUpdateListener.java b/src/common/ic2/api/INetworkUpdateListener.java new file mode 100644 index 000000000..be2adb881 --- /dev/null +++ b/src/common/ic2/api/INetworkUpdateListener.java @@ -0,0 +1,14 @@ +package ic2.api; + +/** + * 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/common/ic2/api/IPaintableBlock.java b/src/common/ic2/api/IPaintableBlock.java new file mode 100644 index 000000000..fb579cd2a --- /dev/null +++ b/src/common/ic2/api/IPaintableBlock.java @@ -0,0 +1,21 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/IReactor.java b/src/common/ic2/api/IReactor.java new file mode 100644 index 000000000..8c6a9291c --- /dev/null +++ b/src/common/ic2/api/IReactor.java @@ -0,0 +1,134 @@ +package ic2.api; + +import net.minecraft.src.ChunkCoordinates; +import net.minecraft.src.ItemStack; +import net.minecraft.src.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 in EU/t + */ + public int getOutput(); + + /** + * Add's the given amount of energy to the Reactor's output. + * + * @return Energy output after adding the value, in EU/t + */ + public int addOutput(int energy); + + /** + * Get's the EU worth of a single basic Uranium pulse + * Please use this variable to alter energy output, as it represents the config modifiers as well. + */ + 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/common/ic2/api/IReactorChamber.java b/src/common/ic2/api/IReactorChamber.java new file mode 100644 index 000000000..fad40c275 --- /dev/null +++ b/src/common/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/common/ic2/api/IReactorComponent.java b/src/common/ic2/api/IReactorComponent.java new file mode 100644 index 000000000..26de8f2c2 --- /dev/null +++ b/src/common/ic2/api/IReactorComponent.java @@ -0,0 +1,97 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/ITerraformingBP.java b/src/common/ic2/api/ITerraformingBP.java new file mode 100644 index 000000000..490d4ee2e --- /dev/null +++ b/src/common/ic2/api/ITerraformingBP.java @@ -0,0 +1,35 @@ +package ic2.api; + +import net.minecraft.src.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/common/ic2/api/IWrenchable.java b/src/common/ic2/api/IWrenchable.java new file mode 100644 index 000000000..f29253617 --- /dev/null +++ b/src/common/ic2/api/IWrenchable.java @@ -0,0 +1,50 @@ +package ic2.api; + +import net.minecraft.src.EntityPlayer; + +/** + * 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(); +} + diff --git a/src/common/ic2/api/Ic2Recipes.java b/src/common/ic2/api/Ic2Recipes.java new file mode 100644 index 000000000..6d286cb16 --- /dev/null +++ b/src/common/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.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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() + ".common.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/common/ic2/api/Items.java b/src/common/ic2/api/Items.java new file mode 100644 index 000000000..5835eb5dd --- /dev/null +++ b/src/common/ic2/api/Items.java @@ -0,0 +1,401 @@ +package ic2.api; + +import net.minecraft.src.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() + ".common.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/common/ic2/api/NetworkHelper.java b/src/common/ic2/api/NetworkHelper.java new file mode 100644 index 000000000..5287671bc --- /dev/null +++ b/src/common/ic2/api/NetworkHelper.java @@ -0,0 +1,236 @@ +package ic2.api; + +import java.lang.reflect.Method; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntity; +import net.minecraft.src.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() + ".common.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() + ".common.NetworkManager").getMethod("initiateTileEntityEvent", TileEntity.class, Integer.TYPE, Boolean.TYPE); + if (instance == null) instance = getInstance(); + + NetworkManager_initiateTileEntityEvent.invoke(null, 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() + ".common.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() + ".common.NetworkManager").getMethod("announceBlockUpdate", World.class, Integer.TYPE, Integer.TYPE, Integer.TYPE); + + NetworkManager_announceBlockUpdate.invoke(null, 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() + ".common.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() + ".common.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() + ".common.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) return pkg.getName().substring(0, pkg.getName().lastIndexOf('.')); + else return "ic2"; + } + + /** + * Get the NetworkManager instance, used internally. + * + * @return NetworkManager instance + */ + private static Object getInstance() { + try { + return Class.forName(getPackage() + ".common.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; +} + diff --git a/src/common/ic2/api/TECrop.java b/src/common/ic2/api/TECrop.java new file mode 100644 index 000000000..c341d0325 --- /dev/null +++ b/src/common/ic2/api/TECrop.java @@ -0,0 +1,161 @@ +package ic2.api; + +import net.minecraft.src.Block; +import net.minecraft.src.ItemStack; +import net.minecraft.src.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/common/railcraft/common/api/carts/CartBase.java b/src/common/railcraft/common/api/carts/CartBase.java new file mode 100644 index 000000000..d3403ba14 --- /dev/null +++ b/src/common/railcraft/common/api/carts/CartBase.java @@ -0,0 +1,118 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; + +/** + * Generally minecarts should extend this class or there will be + * oddities if a user links two carts with different max speeds. + * + * It also contains some generic code that most carts will find useful. + * + * @author CovertJaguar + */ +public abstract class CartBase extends EntityMinecart implements IMinecart +{ + + private float trainSpeed = 1.2f; + + public CartBase(World world) + { + super(world); + CartTools.setCartOwner(this, "[Railcraft]"); + } + + public World getWorld() + { + return worldObj; + } + + @Override + public final float getMaxSpeedRail() + { + return Math.min(getCartMaxSpeed(), trainSpeed); + } + + @Override + public float getCartMaxSpeed() + { + return 1.2f; + } + + @Override + public final void setTrainSpeed(float speed) + { + this.trainSpeed = speed; + } + + @Override + public final boolean interact(EntityPlayer player) + { + if(MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, player))) { + return true; + } + if(CartTools.getCartOwner(this).equals("[Railcraft]")) { + CartTools.setCartOwner(this, player); + } + return doInteract(player); + } + + public boolean doInteract(EntityPlayer player) + { + return super.interact(player); + } + + @Override + public boolean doesCartMatchFilter(ItemStack stack, EntityMinecart cart) + { + if(stack == null || cart == null) { + return false; + } + ItemStack cartItem = cart.getCartItem(); + return cartItem != null && stack.isItemEqual(cartItem); + } + + @Override + public void setDead() + { + for(int var1 = 0; var1 < this.getSizeInventory(); ++var1) { + ItemStack var2 = this.getStackInSlot(var1); + this.setInventorySlotContents(var1, null); + + if(!worldObj.isRemote && var2 != null) { + float var3 = this.rand.nextFloat() * 0.8F + 0.1F; + float var4 = this.rand.nextFloat() * 0.8F + 0.1F; + float var5 = this.rand.nextFloat() * 0.8F + 0.1F; + + while(var2.stackSize > 0) { + int var6 = this.rand.nextInt(21) + 10; + + if(var6 > var2.stackSize) { + var6 = var2.stackSize; + } + + var2.stackSize -= var6; + EntityItem var7 = new EntityItem(this.worldObj, this.posX + (double)var3, this.posY + (double)var4, this.posZ + (double)var5, new ItemStack(var2.itemID, var6, var2.getItemDamage())); + + if(var2.hasTagCompound()) { + var7.item.setTagCompound((NBTTagCompound)var2.getTagCompound().copy()); + } + + float var8 = 0.05F; + var7.motionX = (double)((float)this.rand.nextGaussian() * var8); + var7.motionY = (double)((float)this.rand.nextGaussian() * var8 + 0.2F); + var7.motionZ = (double)((float)this.rand.nextGaussian() * var8); + this.worldObj.spawnEntityInWorld(var7); + } + } + } + + super.setDead(); + } +} diff --git a/src/common/railcraft/common/api/carts/CartTools.java b/src/common/railcraft/common/api/carts/CartTools.java new file mode 100644 index 000000000..4fa0e650d --- /dev/null +++ b/src/common/railcraft/common/api/carts/CartTools.java @@ -0,0 +1,372 @@ +package railcraft.common.api.carts; + +import railcraft.common.api.core.items.IMinecartItem; +import cpw.mods.fml.common.registry.EntityRegistry; +import java.util.ArrayList; +import java.util.List; +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.BlockRail; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemMinecart; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; + +public abstract class CartTools +{ + + public static ILinkageManager serverLinkageManager; + /** + * Registers a subclass of EntityMinecart with the game engine. + * + * This is just a convenience function, it is not required to call this function + * if you call ModLoader.registerEntityID() and MinecraftForge.registerEntity() + * elsewhere. + * + * @param mod The mod doing the registration + * @param type The class of the cart + * @param tag The String identifier + * @param internalId The mods internal entity id + */ + public static void registerMinecart(Object mod, Class type, String tag, int internalId) + { + EntityRegistry.registerModEntity(type, tag, internalId, mod, 80, 3, true); + } + + /** + * Returns an instance of ILinkageManager. + * + * Will return null if Railcraft is not installed. + * + * @param world The World, may be required in the future + * @return an instance of ILinkageManager + */ + public static ILinkageManager getLinkageManager(World world) + { + return serverLinkageManager; + } + + /** + * Sets a carts owner. + * + * The is really only needed by the bukkit ports. + * + * @param owner + */ + public static void setCartOwner(EntityMinecart cart, EntityPlayer owner) + { + cart.getEntityData().setString("owner", owner.username); + } + + /** + * Sets a carts owner. + * + * The is really only needed by the bukkit ports. + * + * @param owner + */ + public static void setCartOwner(EntityMinecart cart, String owner) + { + cart.getEntityData().setString("owner", owner); + } + + /** + * Gets a carts owner. (player.username) + * + * The is really only needed by the bukkit ports. + * + * @param owner + */ + public static String getCartOwner(EntityMinecart cart) + { + return cart.getEntityData().getString("owner"); + } + + /** + * Will return true if the cart matches the provided filter item. + * + * @param stack the Filter + * @param cart the Cart + * @return true if the item matches the cart + * @see IMinecart + */ + public static boolean doesCartMatchFilter(ItemStack stack, EntityMinecart cart) + { + if(stack == null) { + return false; + } + if(cart instanceof IMinecart) { + return ((IMinecart)cart).doesCartMatchFilter(stack, cart); + } + ItemStack cartItem = cart.getCartItem(); + return cartItem != null && stack.isItemEqual(cartItem); + } + + /** + * Spawns a new cart entity using the provided item. + * + * The backing item must implement IMinecartItem + * and/or extend ItemMinecart. + * + * Generally Forge requires all cart items to extend ItemMinecart. + * + * @param owner The player name that should used as the owner + * @param cart An ItemStack containing a cart item, will not be changed by the function + * @param world The World object + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @return the cart placed or null if failed + * @see IMinecartItem, ItemMinecart + */ + public static EntityMinecart placeCart(String owner, ItemStack cart, World world, int i, int j, int k) + { + if(cart == null) { + return null; + } + cart = cart.copy(); + if(cart.getItem() instanceof IMinecartItem) { + IMinecartItem mi = (IMinecartItem)cart.getItem(); + return mi.placeCart(owner, cart, world, i, j, k); + } else if(cart.getItem() instanceof ItemMinecart) { + try { + boolean placed = cart.getItem().onItemUseFirst(cart, null, world, i, j, k, 0, 0, 0, 0); + if(placed) { + List carts = getMinecartsAt(world, i, j, k, 0.3f); + if(carts.size() > 0) { + setCartOwner(carts.get(0), owner); + return carts.get(0); + } + } + } catch (Exception e) { + return null; + } + } + + return null; + } + + /** + * Offers an item stack to linked carts or drops it if no one wants it. + * @param cart + * @param stack + */ + public static void offerOrDropItem(EntityMinecart cart, ItemStack stack) + { + EntityMinecart link_A = getLinkageManager(cart.worldObj).getLinkedCartA(cart); + EntityMinecart link_B = getLinkageManager(cart.worldObj).getLinkedCartB(cart); + + if(stack != null && stack.stackSize > 0 && link_A instanceof IItemTransfer) { + stack = ((IItemTransfer)link_A).offerItem(cart, stack); + } + if(stack != null && stack.stackSize > 0 && link_B instanceof IItemTransfer) { + stack = ((IItemTransfer)link_B).offerItem(cart, stack); + } + + if(stack != null && stack.stackSize > 0) { + cart.entityDropItem(stack, 1); + } + } + + public static boolean isMinecartOnRailAt(World world, int i, int j, int k, float sensitivity) + { + return isMinecartOnRailAt(world, i, j, k, sensitivity, null, true); + } + + public static boolean isMinecartOnRailAt(World world, int i, int j, int k, float sensitivity, Class type, boolean subclass) + { + if(BlockRail.isRailBlockAt(world, i, j, k)) { + return isMinecartAt(world, i, j, k, sensitivity, type, subclass); + } + return false; + } + + public static boolean isMinecartOnAnySide(World world, int i, int j, int k, float sensitivity) + { + return isMinecartOnAnySide(world, i, j, k, sensitivity, null, true); + } + + public static boolean isMinecartOnAnySide(World world, int i, int j, int k, float sensitivity, Class type, boolean subclass) + { + List list = new ArrayList(); + for(int side = 0; side < 6; side++) { + list.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); + } + + if(type == null) { + return !list.isEmpty(); + } else { + for(EntityMinecart cart : list) { + if((subclass && type.isInstance(cart)) || cart.getClass() == type) { + return true; + } + } + } + return false; + } + + public static boolean isMinecartAt(World world, int i, int j, int k, float sensitivity) + { + return isMinecartAt(world, i, j, k, sensitivity, null, true); + } + + public static boolean isMinecartAt(World world, int i, int j, int k, float sensitivity, Class type, boolean subclass) + { + List list = getMinecartsAt(world, i, j, k, sensitivity); + + if(type == null) { + return !list.isEmpty(); + } else { + for(EntityMinecart cart : list) { + if((subclass && type.isInstance(cart)) || cart.getClass() == type) { + return true; + } + } + } + return false; + } + + public static List getMinecartsOnAllSides(World world, int i, int j, int k, float sensitivity) + { + List carts = new ArrayList(); + for(int side = 0; side < 6; side++) { + carts.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); + } + + return carts; + } + + public static List getMinecartsOnAllSides(World world, int i, int j, int k, float sensitivity, Class type, boolean subclass) + { + List list = new ArrayList(); + List carts = new ArrayList(); + for(int side = 0; side < 6; side++) { + list.addAll(getMinecartsOnSide(world, i, j, k, sensitivity, ForgeDirection.getOrientation(side))); + } + + for(EntityMinecart cart : list) { + if((subclass && type.isInstance(cart)) || cart.getClass() == type) { + carts.add(cart); + } + } + return carts; + } + + private static int getYOnSide(int y, ForgeDirection side) + { + switch (side) { + case UP: + return y + 1; + case DOWN: + return y - 1; + default: + return y; + } + } + + private static int getXOnSide(int x, ForgeDirection side) + { + switch (side) { + case EAST: + return x + 1; + case WEST: + return x - 1; + default: + return x; + } + } + + private static int getZOnSide(int z, ForgeDirection side) + { + switch (side) { + case NORTH: + return z - 1; + case SOUTH: + return z + 1; + default: + return z; + } + } + + public static List getMinecartsOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) + { + return getMinecartsAt(world, getXOnSide(i, side), getYOnSide(j, side), getZOnSide(k, side), sensitivity); + } + + public static boolean isMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) + { + return getMinecartOnSide(world, i, j, k, sensitivity, side) != null; + } + + public static EntityMinecart getMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side) + { + for(EntityMinecart cart : getMinecartsOnSide(world, i, j, k, sensitivity, side)) { + return cart; + } + return null; + } + + public static boolean isMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side, Class type, boolean subclass) + { + return getMinecartOnSide(world, i, j, k, sensitivity, side, type, subclass) != null; + } + + public static EntityMinecart getMinecartOnSide(World world, int i, int j, int k, float sensitivity, ForgeDirection side, Class type, boolean subclass) + { + for(EntityMinecart cart : getMinecartsOnSide(world, i, j, k, sensitivity, side)) { + if(type == null || (subclass && type.isInstance(cart)) || cart.getClass() == type) { + return cart; + } + } + return null; + } + + /** + * + * @param world + * @param i + * @param j + * @param k + * @param sensitivity Controls the size of the search box, ranges from (-inf, 0.49]. + * @return + */ + public static List getMinecartsAt(World world, int i, int j, int k, float sensitivity) + { + sensitivity = Math.min(sensitivity, 0.49f); + List entities = world.getEntitiesWithinAABB(net.minecraft.src.EntityMinecart.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(i + sensitivity, j + sensitivity, k + sensitivity, i + 1 - sensitivity, j + 1 - sensitivity, k + 1 - sensitivity)); + List carts = new ArrayList(); + for(Object o : entities) { + carts.add((EntityMinecart)o); + } + return carts; + } + + public static List getMinecartsIn(World world, int i1, int j1, int k1, int i2, int j2, int k2) + { + List entities = world.getEntitiesWithinAABB(net.minecraft.src.EntityMinecart.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(i1, j1, k1, i2, j2, k2)); + List carts = new ArrayList(); + for(Object o : entities) { + carts.add((EntityMinecart)o); + } + return carts; + } + + /** + * Returns the cart's "speed". It is not capped by the carts max speed, + * it instead returns the cart's "potential" speed. + * Used by collision and linkage logic. + * Do not use this to determine how fast a cart is currently moving. + * @param cart + * @return speed + */ + public static double getCartSpeedUncapped(EntityMinecart cart) + { + return Math.sqrt(cart.motionX * cart.motionX + cart.motionZ * cart.motionZ); + } + + public static boolean cartVelocityIsLessThan(EntityMinecart cart, float vel) + { + return Math.abs(cart.motionX) < vel && Math.abs(cart.motionZ) < vel; + } +} diff --git a/src/common/railcraft/common/api/carts/ICartRenderInterface.java b/src/common/railcraft/common/api/carts/ICartRenderInterface.java new file mode 100644 index 000000000..4fcb413f9 --- /dev/null +++ b/src/common/railcraft/common/api/carts/ICartRenderInterface.java @@ -0,0 +1,24 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.Block; + +/** + * Used by the renderer to renders blocks in carts. + * @author CovertJaguar + */ +public interface ICartRenderInterface +{ + + /** + * Return the block that should be rendered in the cart. + * @return The Block to render + */ + public Block getBlock(); + + /** + * Return the metadata for the block + * that should be rendered in the cart. + * @return metadata + */ + public int getBlockMetadata(); +} diff --git a/src/common/railcraft/common/api/carts/IEnergyTransfer.java b/src/common/railcraft/common/api/carts/IEnergyTransfer.java new file mode 100644 index 000000000..49fee703a --- /dev/null +++ b/src/common/railcraft/common/api/carts/IEnergyTransfer.java @@ -0,0 +1,82 @@ +package railcraft.common.api.carts; + +/** + * This interface is implemented by the Energy Cart + * and is used by the Energy Loaders to charge/discharge carts. + * It is roughly equivalent to the IItemTransfer interface + * and based on ElectricItem and IElectricItem. + * + * @author CovertJaguar + * @see IItemTransfer + */ +public interface IEnergyTransfer +{ + + /** + * Injects the specified amount of EU into the device. + * + * The function returns the remainder of the EU after + * any EU used is subtracted. + * + * @param source Object initiating the transfer, should be an Entity or Tile Entity + * @param amount amount of energy to transfer in EU + * @param tier tier of the source device, has to be at least as high as the target device + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually change the item, just determine the return value + * @return The amount of EU not used + */ + public int injectEnergy(Object source, int amount, int tier, boolean ignoreTransferLimit, boolean simulate, boolean passAlong); + + /** + * Requests a certain amount of EU from the device. + * + * The is function will subtract EU from the device's store of power + * and return a portion up to, but not exceeding, the amount of EU requested. + * + * @param source Object initiating the transfer, should be an Entity or Tile Entity + * @param amount amount of energy to transfer in EU + * @param tier tier of the source device, has to be at least as high as the target device + * @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit() + * @param simulate don't actually change the item, just determine the return value + * @param passAlong whether neighboring carts should be asked to provide any missing power. + * @return The amount of EU transferred + */ + public int extractEnergy(Object source, int amount, int tier, boolean ignoreTransferLimit, boolean simulate, boolean passAlong); + + /** + * Return true if energy can be injected into this device. + * + * @return true if can inject energy + */ + public boolean canInjectEnergy(); + + /** + * Return true if energy can be extracted from this device. + * + * @return true if can extract energy + */ + public boolean canExtractEnergy(); + + /** + * The max capacity of the device. + * + * @return max capacity + */ + public int getCapacity(); + + /** + * Returns the current energy contained in the device. + * + * @return current energy + */ + public int getEnergy(); + + public int getTier(); + + /** + * The device's transfer rate in EU/t. + * + * @return the transfer rate + */ + public int getTransferLimit(); +} diff --git a/src/common/railcraft/common/api/carts/IItemTransfer.java b/src/common/railcraft/common/api/carts/IItemTransfer.java new file mode 100644 index 000000000..a5af647d5 --- /dev/null +++ b/src/common/railcraft/common/api/carts/IItemTransfer.java @@ -0,0 +1,65 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.ItemStack; +import railcraft.common.api.core.items.EnumItemType; + +/** + * This interface allows items to be passed around with out needing + * to know anything about the underlying implementation of the inventories. + * + * @author CovertJaguar + */ +public interface IItemTransfer +{ + + /** + * Offers an ItemStack to the object implementing this interface. + * This function will return null if the item is accepted in full, + * otherwise it will return whatever is rejected. + * + * @param source The Object offering the item + * @param offer The ItemStack being offered + * @return Unused or unwanted portions of offer + */ + public ItemStack offerItem(Object source, ItemStack offer); + + /** + * Requests an ItemStack from the object implementing this interface. + * It is up to the object implementing this interface to determine which + * ItemStack to return, or none at all. + * + * @param source The Object submitting the request + * @return An ItemStack to fulfill the request or null if refused. + */ + public ItemStack requestItem(Object source); + + /** + * Requests an ItemStack from the object implementing this interface + * that matches the request parameter. + * It is up to the object implementing this interface to + * determine which ItemStack to return, or none at all. + * However, if the return value is not null + * it should fulfill the following condition:
+ * InventoryTools.isItemEqual(it.requestItem(this,request), request) == true + * + * @param source The Object submitting the request + * @param request The type of item requested + * @return An ItemStack to fulfill the request or null if refused. + */ + public ItemStack requestItem(Object source, ItemStack request); + + /** + * Requests an ItemStack from the object implementing this interface + * that matches the request parameter. + * It is up to the object implementing this interface to + * determine which ItemStack to return, or none at all. + * However, if the return value is not null + * it should fulfill the following condition:
+ * EnumItemType.isItemType(it.requestItem(this,request), request) == true + * + * @param source The Object submitting the request + * @param request The type of item requested + * @return An ItemStack to fulfill the request or null if refused. + */ + public ItemStack requestItem(Object source, EnumItemType request); +} diff --git a/src/common/railcraft/common/api/carts/ILinkableCart.java b/src/common/railcraft/common/api/carts/ILinkableCart.java new file mode 100644 index 000000000..d87386d9d --- /dev/null +++ b/src/common/railcraft/common/api/carts/ILinkableCart.java @@ -0,0 +1,77 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.EntityMinecart; + +/** + * This interface should be implemented by any minecart that wishes + * to change the default linkage behavior. + * It is NOT required to be able to link a cart, + * it merely gives you more control over the process. + * @author CovertJaguar + */ +public interface ILinkableCart +{ + + /** + * To disable linking altogether, return false here. + * @return True if this cart is linkable. + */ + public boolean isLinkable(); + + /** + * Check called when attempting to link carts. + * @param cart The cart that we are attempting to link with. + * @return True if we can link with this cart. + */ + public boolean canLinkWithCart(EntityMinecart cart); + + /** + * Returns true if this cart has two links + * or false if it can only link with one cart. + * @return True if two links + */ + public boolean hasTwoLinks(); + + /** + * Gets the distance at which this cart can be linked. + * This is called on both carts and added together to determine + * how close two carts need to be for a successful link. + * Default = LinkageManager.LINKAGE_DISTANCE + * @param cart The cart that you are attempting to link with. + * @return The linkage distance + */ + public float getLinkageDistance(EntityMinecart cart); + + /** + * Gets the optimal distance between linked carts. + * This is called on both carts and added together to determine + * the optimal rest distance between linked carts. + * The LinkageManager will attempt to maintain this distance + * between linked carts at all times. + * Default = LinkageManager.OPTIMAL_DISTANCE + * @param cart The cart that you are linked with. + * @return The optimal rest distance + */ + public float getOptimalDistance(EntityMinecart cart); + + /** + * Return false if linked carts have no effect on the velocity of this cart. + * Use carefully, if you link two carts that can't be adjusted, + * it will behave as if they are not linked. + * @param cart The cart doing the adjusting. + * @return Whether the cart can have its velocity adjusted. + */ + public boolean canBeAdjusted(EntityMinecart cart); + + /** + * Called upon successful link creation. + * @param cart The cart we linked with. + */ + public void onLinkCreated(EntityMinecart cart); + + /** + * Called when a link is broken (usually). + * @param cart The cart we were linked with. + */ + public void onLinkBroken(EntityMinecart cart); +} diff --git a/src/common/railcraft/common/api/carts/ILinkageManager.java b/src/common/railcraft/common/api/carts/ILinkageManager.java new file mode 100644 index 000000000..e3080968f --- /dev/null +++ b/src/common/railcraft/common/api/carts/ILinkageManager.java @@ -0,0 +1,102 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.EntityMinecart; + +/** + * The LinkageManager contains all the functions needed to link and interact + * with linked carts. + * + * To obtain an instance of this interface, call CartTools.getLinkageManager(). + * + * Each cart can up to two links. They are called Link A and Link B. + * Some carts will have only Link A, for example the Tunnel Bore. + * + * @author CovertJaguar + * @see CartTools, ILinkableCart + */ +public interface ILinkageManager +{ + + /** + * The default max distance at which carts can be linked, divided by 2. + */ + public static final float LINKAGE_DISTANCE = 1.25f; + /** + * The default distance at which linked carts are maintained, divided by 2. + */ + public static final float OPTIMAL_DISTANCE = 0.78f; + + /** + * Creates a link between two carts, + * but only if there is nothing preventing such a link. + * + * @param cart1 + * @param cart2 + * @return True if the link succeeded. + */ + public boolean createLink(EntityMinecart cart1, EntityMinecart cart2); + + /** + * Returns the cart linked to Link A or null if nothing is currently + * occupying Link A. + * + * @param cart The cart for which to get the link + * @return The linked cart or null + */ + public EntityMinecart getLinkedCartA(EntityMinecart cart); + + /** + * Returns the cart linked to Link B or null if nothing is currently + * occupying Link B. + * + * @param cart The cart for which to get the link + * @return The linked cart or null + */ + public EntityMinecart getLinkedCartB(EntityMinecart cart); + + /** + * Returns true if the two carts are linked to each other. + * + * @param cart1 + * @param cart2 + * @return True if linked + */ + public boolean areLinked(EntityMinecart cart1, EntityMinecart cart2); + + /** + * Breaks a link between two carts, if any link exists. + * + * @param cart1 + * @param cart2 + */ + public void breakLink(EntityMinecart cart1, EntityMinecart cart2); + + /** + * Breaks all links the cart has. + * + * @param cart + */ + public void breakLinks(EntityMinecart cart); + + /** + * Break only link A. + * + * @param cart + */ + public void breakLinkA(EntityMinecart cart); + + /** + * Break only link B. + * + * @param cart + */ + public void breakLinkB(EntityMinecart cart); + + /** + * Counts how many carts are in the train. + * + * @param cart Any cart in the train + * @return The number of carts in the train + */ + public int countCartsInTrain(EntityMinecart cart); +} diff --git a/src/common/railcraft/common/api/carts/ILiquidTransfer.java b/src/common/railcraft/common/api/carts/ILiquidTransfer.java new file mode 100644 index 000000000..8d72e7348 --- /dev/null +++ b/src/common/railcraft/common/api/carts/ILiquidTransfer.java @@ -0,0 +1,53 @@ +package railcraft.common.api.carts; + +import buildcraft.api.liquids.LiquidStack; + +/** + * This interface allows carts to transfer liquid between each other + * as well as adding a couple other functions related to liquids. + * + * @author CovertJaguar + */ +public interface ILiquidTransfer +{ + + /** + * Offers liquid to this object. + * + * Is not used by the Liquid Loader to load carts, + * the traditional ILiquidContainer is used for that. + * + * @param source The Object offering the liquid, used to prevent request loops in trains + * @param quantity The quantity offered + * @param id The liquid id offered + * @return the liquid used + */ + public int offerLiquid(Object source, LiquidStack offer); + + /** + * Requests liquid from this object. + * + * Is not used by the Liquid Unloader to drain carts, + * the traditional ILiquidContainer is used for that. + * + * @param source The Object requesting the liquid, used to prevent request loops in trains + * @param quantity The quantity requested + * @param id The liquid type requested + * @return the liquid provided + */ + public int requestLiquid(Object source, LiquidStack request); + + /** + * Set by the Liquid Loader while filling, + * primarily used for rendering a visible + * change while being filled. + * @param filling + */ + public void setFilling(boolean filling); + + /** + * + * @return true if being filled + */ + public boolean isFilling(); +} diff --git a/src/common/railcraft/common/api/carts/IMinecart.java b/src/common/railcraft/common/api/carts/IMinecart.java new file mode 100644 index 000000000..7707a20e7 --- /dev/null +++ b/src/common/railcraft/common/api/carts/IMinecart.java @@ -0,0 +1,52 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.ItemStack; + +/** + * Some helper functions to make interacting with carts simpler. + * + * This interface is implemented by CartBase. + * + * @author CovertJaguar + * @see CartBase + */ +public interface IMinecart +{ + + /** + * Returns true if the Minecart matches the item provided. + * Generally just stack.isItemEqual(cart.getCartItem()), + * but some carts may need more control (the Tank Cart for example). + * + * @param stack the Filter + * @param cart the Cart + * @return true if the item matches the cart + */ + public boolean doesCartMatchFilter(ItemStack stack, EntityMinecart cart); + + /** + * Unlike EntityMinecart.getMaxSpeedRail(), + * this function is independent of the actual max speed of the cart. + * + * It should represent the max possible speed at this point in time + * before any modifiers due to linked carts, etc are applied. + * + * This is really only used for Train speed calculations. + * Which ever cart in the train returns the lowest value here will be the max speed of the entire train. + * + * @return + */ + public float getCartMaxSpeed(); + + /** + * Sets the max speed of a train. + * + * This should be used to limit the return value for EntityMinecart.getMaxSpeedRail(). + * + * @param speed + * @see CartBase + */ + public void setTrainSpeed(float speed); + +} diff --git a/src/common/railcraft/common/api/carts/TransferCartBase.java b/src/common/railcraft/common/api/carts/TransferCartBase.java new file mode 100644 index 000000000..d623308eb --- /dev/null +++ b/src/common/railcraft/common/api/carts/TransferCartBase.java @@ -0,0 +1,252 @@ +package railcraft.common.api.carts; + +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; +import railcraft.common.api.core.items.EnumItemType; + +/** + * Abstract minecart class that implements the IItemTransfer + * interface for convenience and as example for others who wish + * to create carts that implements IItemTransfer. + * This particular implementation assumes a simple inventory + * and will attempt to pass along offers and requests to linked carts + * if it cannot fulfill them itself. + *
+ *
+ * Classes that extend this class:
+ * EntityCartChest
+ * EntityCartAnchor
+ * + * @author CovertJaguar + */ +public abstract class TransferCartBase extends CartBase implements IItemTransfer +{ + + /** + * If passThrough == true, this cart will only pass requests along, it wont attempt to fulfill them. + */ + protected boolean passThrough = false; + + public TransferCartBase(World world) + { + super(world); + } + + @Override + public ItemStack offerItem(Object source, ItemStack offer) + { + if(!passThrough && getSizeInventory() > 0) { + offer = moveItemStack(offer, this); + if(offer == null) { + return null; + } + } + + ILinkageManager lm = CartTools.getLinkageManager(worldObj); + + EntityMinecart linkedCart = lm.getLinkedCartA(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + offer = ((IItemTransfer)linkedCart).offerItem(this, offer); + } + + if(offer == null) { + return null; + } + + linkedCart = lm.getLinkedCartB(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + offer = ((IItemTransfer)linkedCart).offerItem(this, offer); + } + + return offer; + } + + @Override + public ItemStack requestItem(Object source) + { + ItemStack result = null; + if(!passThrough && getSizeInventory() > 0) { + result = removeOneItem(this); + if(result != null) { + return result; + } + } + + ILinkageManager lm = CartTools.getLinkageManager(worldObj); + + EntityMinecart linkedCart = lm.getLinkedCartA(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this); + } + + if(result != null) { + return result; + } + + linkedCart = lm.getLinkedCartB(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this); + } + + return result; + } + + @Override + public ItemStack requestItem(Object source, ItemStack request) + { + ItemStack result = null; + if(!passThrough && getSizeInventory() > 0) { + result = removeOneItem(this, request); + if(result != null) { + return result; + } + } + + ILinkageManager lm = CartTools.getLinkageManager(worldObj); + + EntityMinecart linkedCart = lm.getLinkedCartA(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this, request); + } + + if(result != null) { + return result; + } + + linkedCart = lm.getLinkedCartB(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this, request); + } + + return result; + } + + @Override + public ItemStack requestItem(Object source, EnumItemType request) + { + ItemStack result = null; + if(!passThrough && getSizeInventory() > 0) { + result = removeOneItem(this, request); + if(result != null) { + return result; + } + } + + ILinkageManager lm = CartTools.getLinkageManager(worldObj); + + EntityMinecart linkedCart = lm.getLinkedCartA(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this, request); + } + + if(result != null) { + return result; + } + + linkedCart = lm.getLinkedCartB(this); + if(linkedCart != source && linkedCart instanceof IItemTransfer) { + result = ((IItemTransfer)linkedCart).requestItem(this, request); + } + + return result; + } + + /** + * Removes and returns a single item from the inventory. + * @param inv The inventory + * @return An ItemStack + */ + protected final ItemStack removeOneItem(IInventory inv) + { + for(int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack slot = inv.getStackInSlot(i); + if(slot != null) { + return inv.decrStackSize(i, 1); + } + } + return null; + } + + /** + * Removes and returns a single item from the inventory that matches the filter. + * @param inv The inventory + * @param filter ItemStack to match against + * @return An ItemStack + */ + protected final ItemStack removeOneItem(IInventory inv, ItemStack filter) + { + for(int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack slot = inv.getStackInSlot(i); + if(slot != null && filter != null && slot.isItemEqual(filter)) { + return inv.decrStackSize(i, 1); + } + } + return null; + } + + /** + * Removes and returns a single item from the inventory that matches the filter. + * @param inv The inventory + * @param filter EnumItemType to match against + * @return An ItemStack + */ + protected final ItemStack removeOneItem(IInventory inv, EnumItemType filter) + { + for(int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack slot = inv.getStackInSlot(i); + if(slot != null && filter.isItemType(slot)) { + return inv.decrStackSize(i, 1); + } + } + return null; + } + + protected final ItemStack moveItemStack(ItemStack stack, IInventory dest) + { + if(stack == null) { + return null; + } + stack = stack.copy(); + if(dest == null) { + return stack; + } + boolean movedItem = false; + do { + movedItem = false; + ItemStack destStack = null; + for(int ii = 0; ii < dest.getSizeInventory(); ii++) { + destStack = dest.getStackInSlot(ii); + if(destStack != null && destStack.isItemEqual(stack)) { + int maxStack = Math.min(destStack.getMaxStackSize(), dest.getInventoryStackLimit()); + int room = maxStack - destStack.stackSize; + if(room > 0) { + int move = Math.min(room, stack.stackSize); + destStack.stackSize += move; + stack.stackSize -= move; + if(stack.stackSize <= 0) { + return null; + } + movedItem = true; + } + } + } + if(!movedItem) { + for(int ii = 0; ii < dest.getSizeInventory(); ii++) { + destStack = dest.getStackInSlot(ii); + if(destStack == null) { + if(stack.stackSize > dest.getInventoryStackLimit()) { + dest.setInventorySlotContents(ii, stack.splitStack(dest.getInventoryStackLimit())); + } else { + dest.setInventorySlotContents(ii, stack); + return null; + } + movedItem = true; + } + } + } + } while(movedItem); + return stack; + } +} diff --git a/src/common/railcraft/common/api/carts/bore/IBoreHead.java b/src/common/railcraft/common/api/carts/bore/IBoreHead.java new file mode 100644 index 000000000..3d5410394 --- /dev/null +++ b/src/common/railcraft/common/api/carts/bore/IBoreHead.java @@ -0,0 +1,37 @@ +package railcraft.common.api.carts.bore; + +/** + * This interface it used to define an item that can + * be used as a bore head for the Tunnel Bore. + * @author CovertJaguar + */ +public interface IBoreHead +{ + + /** + * Return the texture file used for this bore head. + * @return The texture file path + */ + public String getBoreTexture(); + + /** + * Return the harvest level of this bore head. + * + * This value is compared against the tool classes + * "pickaxe", "axe", and "shovel" to determine if the + * block is harvestable by the bore head. + * + * @return The harvest level + */ + public int getHarvestLevel(); + + /** + * Return the dig speed modifier of this bore head. + * + * This value controls how much faster or slow this bore head + * mines each layer compared to the default time. + * + * @return The dig speed modifier + */ + public float getDigModifier(); +} diff --git a/src/common/railcraft/common/api/carts/bore/IMineable.java b/src/common/railcraft/common/api/carts/bore/IMineable.java new file mode 100644 index 000000000..185d0b65d --- /dev/null +++ b/src/common/railcraft/common/api/carts/bore/IMineable.java @@ -0,0 +1,36 @@ +package railcraft.common.api.carts.bore; + +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; + +/** + * This interface can be implemented by a block class to control whether a block can be + * mined by the bore without having to force the user to edit the configuration file. + * + * If the block is found to implement this class, any setting in the configuration + * is ignored for that block. + * + * Generally, the reason blocks are not minable by default is to prevent you + * from intentionally or accidentally boring through your base. + * + * @author CovertJaguar + */ +public interface IMineable +{ + + /** + * Called when the Bore attempts to mine the block. If it returns false, + * the Bore will halt operation. + * + * @param world The World + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @param bore The Bore entity + * @param head The BoreHead, item implements IBoreHead. + * @return true if mineable + * @see IBoreHead + */ + public boolean canMineBlock(World world, int i, int j, int k, EntityMinecart bore, ItemStack head); +} diff --git a/src/common/railcraft/common/api/core/INetworkedObject.java b/src/common/railcraft/common/api/core/INetworkedObject.java new file mode 100644 index 000000000..c09438608 --- /dev/null +++ b/src/common/railcraft/common/api/core/INetworkedObject.java @@ -0,0 +1,16 @@ +package railcraft.common.api.core; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import net.minecraft.src.World; + +public interface INetworkedObject +{ + + public World getWorld(); + + public void writePacketData(DataOutputStream data) throws IOException; + + public void readPacketData(DataInputStream data) throws IOException; +} diff --git a/src/common/railcraft/common/api/core/IPostConnection.java b/src/common/railcraft/common/api/core/IPostConnection.java new file mode 100644 index 000000000..12a13c4e2 --- /dev/null +++ b/src/common/railcraft/common/api/core/IPostConnection.java @@ -0,0 +1,27 @@ +package railcraft.common.api.core; + +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; + +/** + * If you want your block to connect (or not connect) to posts, + * implement this interface. + * + * The result takes priority over any other rules. + * + * @author CovertJaguar + */ +public interface IPostConnection +{ + + /** + * Return true if the block at this location should connect to a post. + * @param world The World + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @param side Side to connect to + * @return true if connect + */ + public boolean connectsAt(World world, int i, int j, int k, ForgeDirection side); +} diff --git a/src/common/railcraft/common/api/core/WorldCoordinate.java b/src/common/railcraft/common/api/core/WorldCoordinate.java new file mode 100644 index 000000000..3037e8009 --- /dev/null +++ b/src/common/railcraft/common/api/core/WorldCoordinate.java @@ -0,0 +1,78 @@ +package railcraft.common.api.core; + +/** + * This immutable class represents a point in the Minecraft world, + * while taking into account the possibility of coordinates in different dimensions. + * @author CovertJaguar + */ +public class WorldCoordinate +{ + + /** + * The dimension + */ + public final int dimension; + /** + * x-Coord + */ + public final int x; + /** + * y-Coord + */ + public final int y; + /** + * z-Coord + */ + public final int z; + + /** + * Creates a new WorldCoordinate + * @param dimension + * @param i + * @param j + * @param k + */ + public WorldCoordinate(int dimension, int i, int j, int k) + { + this.dimension = dimension; + x = i; + y = j; + z = k; + } + + @Override + public boolean equals(Object obj) + { + if(obj == null) { + return false; + } + if(getClass() != obj.getClass()) { + return false; + } + final WorldCoordinate other = (WorldCoordinate)obj; + if(this.dimension != other.dimension) { + return false; + } + if(this.x != other.x) { + return false; + } + if(this.y != other.y) { + return false; + } + if(this.z != other.z) { + return false; + } + return true; + } + + @Override + public int hashCode() + { + int hash = 3; + hash = 13 * hash + this.dimension; + hash = 13 * hash + this.x; + hash = 13 * hash + this.y; + hash = 13 * hash + this.z; + return hash; + } +} diff --git a/src/common/railcraft/common/api/core/items/BallastRegistry.java b/src/common/railcraft/common/api/core/items/BallastRegistry.java new file mode 100644 index 000000000..dcc724f1a --- /dev/null +++ b/src/common/railcraft/common/api/core/items/BallastRegistry.java @@ -0,0 +1,93 @@ +package railcraft.common.api.core.items; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import net.minecraft.src.Block; +import net.minecraft.src.ItemBlock; +import net.minecraft.src.ItemStack; + +/** + * Register an item here to designate it as a possible + * ballast that can be used in the Bore. + * + * It is expected that ballast is affected by gravity. + * + * @author CovertJaguar + */ +public abstract class BallastRegistry +{ + + private static Set ballastRegistry = new HashSet(); + + private static class ItemWrapper + { + + public int itemID; + public int itemDamage; + public ItemStack stack; + + public ItemWrapper(ItemStack stack) + { + itemID = stack.itemID; + itemDamage = stack.getItemDamage(); + this.stack = stack; + } + + @Override + public boolean equals(Object obj) + { + if(obj == null) { + return false; + } + if(getClass() != obj.getClass()) { + return false; + } + final ItemWrapper other = (ItemWrapper)obj; + if(this.itemID != other.itemID) { + return false; + } + if(this.itemDamage != other.itemDamage) { + return false; + } + return true; + } + + @Override + public int hashCode() + { + int hash = 3; + hash = 47 * hash + this.itemID; + hash = 47 * hash + this.itemDamage; + return hash; + } + } + + static { + registerBallast(new ItemStack(Block.gravel)); + } + + public static void registerBallast(ItemStack ballast) + { + if(ballast.getItem() instanceof ItemBlock) { + ballastRegistry.add(new ItemWrapper(ballast)); + } else { + throw new RuntimeException("Attempted to register an invalid ballast, must be an ItemBlock item."); + } + } + + public static boolean isItemBallast(ItemStack ballast) + { + return ballastRegistry.contains(new ItemWrapper(ballast)); + } + + public static List getRegisteredBallasts() + { + List list = new ArrayList(); + for(ItemWrapper item : ballastRegistry) { + list.add(item.stack); + } + return list; + } +} diff --git a/src/common/railcraft/common/api/core/items/EnumItemType.java b/src/common/railcraft/common/api/core/items/EnumItemType.java new file mode 100644 index 000000000..850ff8230 --- /dev/null +++ b/src/common/railcraft/common/api/core/items/EnumItemType.java @@ -0,0 +1,47 @@ +package railcraft.common.api.core.items; + +import net.minecraft.src.BlockRail; +import net.minecraft.src.Item; +import net.minecraft.src.ItemBlock; +import net.minecraft.src.ItemFood; +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntityFurnace; +import net.minecraftforge.common.MinecartRegistry; + +/** + * This interface is used with several of the functions in IItemTransfer + * to provide a convenient means of dealing with entire classes of items without + * having to specify each item individually. + * @author CovertJaguar + */ +public enum EnumItemType +{ + + FUEL, RAIL, MINECART, BALLAST, FOOD; + + public static boolean isItemType(ItemStack stack, EnumItemType filter) + { + return filter.isItemType(stack); + } + + public boolean isItemType(ItemStack stack) + { + if(stack == null) { + return false; + } + switch (this) { + case FUEL: + return TileEntityFurnace.getItemBurnTime(stack) > 0; + case RAIL: + return stack.getItem() instanceof ITrackItem || (stack.getItem() instanceof ItemBlock && BlockRail.isRailBlock(stack.itemID)); + case MINECART: + return MinecartRegistry.getCartClassForItem(stack) != null || stack.getItem() instanceof IMinecartItem; + case BALLAST: + return BallastRegistry.isItemBallast(stack); + case FOOD: + return stack.getItem() instanceof ItemFood || stack.itemID == Item.wheat.shiftedIndex; + default: + return false; + } + } +} diff --git a/src/common/railcraft/common/api/core/items/ICrowbar.java b/src/common/railcraft/common/api/core/items/ICrowbar.java new file mode 100644 index 000000000..3a058b289 --- /dev/null +++ b/src/common/railcraft/common/api/core/items/ICrowbar.java @@ -0,0 +1,14 @@ +package railcraft.common.api.core.items; + +/** + * Any item that performs the same function as a crowbar should implement this interface. + * Making a new crowbar item is as simple as implementing this empty interface. + * Doing so will make all the blocks, tracks, and entities aware of that the item + * should be treated identically to a crowbar. + * + * @author CovertJaguar + */ +public interface ICrowbar +{ + +} diff --git a/src/common/railcraft/common/api/core/items/IMinecartItem.java b/src/common/railcraft/common/api/core/items/IMinecartItem.java new file mode 100644 index 000000000..22d513b8d --- /dev/null +++ b/src/common/railcraft/common/api/core/items/IMinecartItem.java @@ -0,0 +1,39 @@ +package railcraft.common.api.core.items; + +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; + +/** + * This interface should be implemented by any cart item, + * but it is generally optional. + * + * @author CovertJaguar + */ +public interface IMinecartItem +{ + + /** + * Controls whether this cart item can be placed by the Cart and Train Dispensers. + * + * Generally, you can ignore the placeCart() function if this returns false. + * + * @return true if it can be placed, false otherwise + */ + public boolean canBePlacedByNonPlayer(ItemStack cart); + + /** + * Places a cart at the specified location. + * + * Implementing this function is optional. + * + * @param owner the name of the player placing the cart or "[MyMod]" with the brackets + * @param cart An ItemStack that contains the cart + * @param world The World + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @return the cart placed or null if failed + */ + public EntityMinecart placeCart(String owner, ItemStack cart, World world, int i, int j, int k); +} diff --git a/src/common/railcraft/common/api/core/items/ITrackItem.java b/src/common/railcraft/common/api/core/items/ITrackItem.java new file mode 100644 index 000000000..1c4cd72f0 --- /dev/null +++ b/src/common/railcraft/common/api/core/items/ITrackItem.java @@ -0,0 +1,46 @@ +package railcraft.common.api.core.items; + +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; + +/** + * Should be implemented by any rail item class that wishes to have + * it's rails placed by for example the Tunnel Bore or Track Relayer. + * + * If you defined your rails with a TrackSpec, you don't need to worry about this. + * + * @author CovertJaguar + */ +public interface ITrackItem +{ + + /** + * Attempts to place a track. + * + * @param world The World object + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @return true if successful + */ + public boolean placeTrack(ItemStack stack, World world, int i, int j, int k); + + /** + * Return the block id of a placed track. + * + * @return the blockId + */ + public int getPlacedBlockId(); + + /** + * Return true if the given tile entity corresponds to this Track item. + * + * If the track has no tile entity, return true on null. + * + * @param stack + * @param tile + * @return + */ + public boolean isPlacedTileEntity(ItemStack stack, TileEntity tile); +} diff --git a/src/common/railcraft/common/api/core/items/ItemRegistry.java b/src/common/railcraft/common/api/core/items/ItemRegistry.java new file mode 100644 index 000000000..3760fad30 --- /dev/null +++ b/src/common/railcraft/common/api/core/items/ItemRegistry.java @@ -0,0 +1,93 @@ +package railcraft.common.api.core.items; + +import java.util.Map; +import java.util.TreeMap; +import net.minecraft.src.ItemStack; + +/** + * This class contains a registry of all currently active Railcraft items. + * Which items are registered depends on the user's settings in "railcraft.cfg", + * so the available items may vary from one installation to the next. + * + * Initialization of the registry will occur during the BaseMod.load() + * function. It is strongly recommended you wait until the BaseMod.modsLoaded() + * function to reference the registry. + * + * @author CovertJaguar + */ +public final class ItemRegistry +{ + + private static final Map registry = new TreeMap(); + + private ItemRegistry() + { + } + + /** + * This function will return an ItemStack containing the item that + * corresponds to the provided tag. + * + * Generally item tags will correspond to the tags used in "railcraft.cfg", + * but there will be some exceptions. + * + * This function can and will return null for just about every item + * if the item is disabled via the configuration files. + * You must test the return value for safety. + * + * For list of available tags see the printItemTags() function. + * + * @param tag The item tag + * @param qty The stackSize of the returned item + * @return The ItemStack or null if no item exists for that tag + */ + public static ItemStack getItem(String tag, int qty) + { + ItemStack stack = registry.get(tag); + if(stack != null) { + stack = stack.copy(); + stack.stackSize = qty; + } + return stack; + } + + /** + * Registers a new item with the Registry. + * + * This should generally only be called by Railcraft itself + * while the mod is initializing during the mod_Railcraft.load() call. + * + * @param tag The tag name + * @param item The item + */ + public static void registerItem(String tag, ItemStack item) + { + registry.put(tag, item); + } + + /** + * This function will print a list of all currently registered items + * to the console. + * + * Use this for development purposes. + */ + public static void printItemTags() + { + System.out.println(); + System.out.println("Printing all registered Railcraft items:"); + for(String tag : registry.keySet()) { + System.out.println(tag); + } + System.out.println(); + } + + /** + * Returns the entire mapping of items. + * + * @return + */ + public static Map getItems() + { + return registry; + } +} diff --git a/src/common/railcraft/common/api/crafting/IBlastFurnaceCraftingManager.java b/src/common/railcraft/common/api/crafting/IBlastFurnaceCraftingManager.java new file mode 100644 index 000000000..e92381c36 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/IBlastFurnaceCraftingManager.java @@ -0,0 +1,25 @@ +package railcraft.common.api.crafting; + +import java.util.List; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface IBlastFurnaceCraftingManager +{ + + void addRecipe(int inputId, int inputDamage, int cookTime, ItemStack output); + + void addRecipe(int inputId, int cookTime, ItemStack output); + + List getFuels(); + + IBlastFurnaceRecipe getRecipe(int inputId, int inputDamage); + + IBlastFurnaceRecipe getRecipe(ItemStack stack); + + List getRecipes(); + +} diff --git a/src/common/railcraft/common/api/crafting/IBlastFurnaceRecipe.java b/src/common/railcraft/common/api/crafting/IBlastFurnaceRecipe.java new file mode 100644 index 000000000..6c6a71818 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/IBlastFurnaceRecipe.java @@ -0,0 +1,21 @@ +package railcraft.common.api.crafting; + +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface IBlastFurnaceRecipe +{ + + public int getCookTime(); + + public ItemStack getInput(); + + public ItemStack getOutput(); + + int getOutputStackSize(); + + boolean isRoomForOutput(ItemStack out); +} diff --git a/src/common/railcraft/common/api/crafting/ICokeOvenCraftingManager.java b/src/common/railcraft/common/api/crafting/ICokeOvenCraftingManager.java new file mode 100644 index 000000000..a6e5b73f3 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/ICokeOvenCraftingManager.java @@ -0,0 +1,26 @@ +package railcraft.common.api.crafting; + +import buildcraft.api.liquids.LiquidStack; +import java.util.List; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface ICokeOvenCraftingManager +{ + + void addRecipe(ItemStack input, ItemStack output, LiquidStack liquidOutput, int cookTime); + + void addRecipe(int inputId, int inputDamage, ItemStack output, LiquidStack liquidOutput, int cookTime); + + void addRecipe(int inputId, ItemStack output, LiquidStack liquidOutput, int cookTime); + + ICokeOvenRecipe getRecipe(ItemStack stack); + + ICokeOvenRecipe getRecipe(int inputId, int inputDamage); + + List getRecipes(); + +} diff --git a/src/common/railcraft/common/api/crafting/ICokeOvenRecipe.java b/src/common/railcraft/common/api/crafting/ICokeOvenRecipe.java new file mode 100644 index 000000000..f2e9e29f5 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/ICokeOvenRecipe.java @@ -0,0 +1,20 @@ +package railcraft.common.api.crafting; + +import buildcraft.api.liquids.LiquidStack; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface ICokeOvenRecipe +{ + + public int getCookTime(); + + public ItemStack getInput(); + + public LiquidStack getLiquidOutput(); + + public ItemStack getOutput(); +} diff --git a/src/common/railcraft/common/api/crafting/IRockCrusherCraftingManager.java b/src/common/railcraft/common/api/crafting/IRockCrusherCraftingManager.java new file mode 100644 index 000000000..52dd8839d --- /dev/null +++ b/src/common/railcraft/common/api/crafting/IRockCrusherCraftingManager.java @@ -0,0 +1,35 @@ +package railcraft.common.api.crafting; + +import java.util.HashMap; +import java.util.List; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface IRockCrusherCraftingManager +{ + + /** + * + * @param inputId + * @param inputDamage metadata or -1 for wildcard + * @param output A map of outputs and chances. If more than 9 types of items, there will be unexpected behavior. + */ + void addRecipe(int inputId, int inputDamage, HashMap output); + + /** + * + * @param input + * @param output A map of outputs and chances. If more than 9 types of items, there will be unexpected behavior. + */ + void addRecipe(ItemStack input, HashMap output); + + IRockCrusherRecipe getRecipe(ItemStack input); + + IRockCrusherRecipe getRecipe(int inputId, int inputDamage); + + List getRecipes(); + +} diff --git a/src/common/railcraft/common/api/crafting/IRockCrusherRecipe.java b/src/common/railcraft/common/api/crafting/IRockCrusherRecipe.java new file mode 100644 index 000000000..75b2d8114 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/IRockCrusherRecipe.java @@ -0,0 +1,37 @@ +package railcraft.common.api.crafting; + +import java.util.List; +import java.util.Map; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface IRockCrusherRecipe +{ + + public ItemStack getInput(); + + /** + * Returns a map containing each output entry and its chance of being included. + * + * @return + */ + public Map getOutputs(); + + /** + * Returns a list of all possible outputs. + * This is basically a condensed version of getOutputs().keySet(). + * + * @return + */ + public List getPossibleOuput(); + + /** + * Returns a list of outputs after it has passed through the randomizer. + * + * @return + */ + public List getRandomizedOuput(); +} diff --git a/src/common/railcraft/common/api/crafting/IRollingMachineCraftingManager.java b/src/common/railcraft/common/api/crafting/IRollingMachineCraftingManager.java new file mode 100644 index 000000000..6b9ee7f66 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/IRollingMachineCraftingManager.java @@ -0,0 +1,23 @@ +package railcraft.common.api.crafting; + +import java.util.List; +import net.minecraft.src.IRecipe; +import net.minecraft.src.InventoryCrafting; +import net.minecraft.src.ItemStack; + +/** + * + * @author CovertJaguar + */ +public interface IRollingMachineCraftingManager +{ + + void addRecipe(ItemStack output, Object[] components); + + void addShapelessRecipe(ItemStack output, Object[] compenents); + + ItemStack findMatchingRecipe(InventoryCrafting inventorycrafting); + + List getRecipeList(); + +} diff --git a/src/common/railcraft/common/api/crafting/RailcraftCraftingManager.java b/src/common/railcraft/common/api/crafting/RailcraftCraftingManager.java new file mode 100644 index 000000000..27608b221 --- /dev/null +++ b/src/common/railcraft/common/api/crafting/RailcraftCraftingManager.java @@ -0,0 +1,16 @@ +package railcraft.common.api.crafting; + +/** + * These variables are defined during the pre-init phase. + * Do not attempt to access them during pre-init. + * + * @author CovertJaguar + */ +public abstract class RailcraftCraftingManager +{ + + public static ICokeOvenCraftingManager cokeOven; + public static IBlastFurnaceCraftingManager blastFurnace; + public static IRockCrusherCraftingManager rockCrusher; + public static IRollingMachineCraftingManager rollingMachine; +} diff --git a/src/common/railcraft/common/api/signals/EnumSignalAspect.java b/src/common/railcraft/common/api/signals/EnumSignalAspect.java new file mode 100644 index 000000000..8a71e40df --- /dev/null +++ b/src/common/railcraft/common/api/signals/EnumSignalAspect.java @@ -0,0 +1,155 @@ +package railcraft.common.api.signals; + +/** + * Represents a Signal state. + * @author CovertJaguar + */ +public enum EnumSignalAspect +{ + + /** + * The All Clear. + */ + GREEN(0), + /** + * Typically means pairing in progress. + */ + BLINK_YELLOW(1), + /** + * Caution, cart heading away. + */ + YELLOW(1), + /** + * Maintenance warning, the signal is malfunctioning. + */ + BLINK_RED(2), + /** + * Stop! + */ + RED(2), + /** + * Can't happen, really it can't (or shouldn't). + * Only used when rendering blink states (for the texture offset). + */ + OFF(3); + private final byte id; + private final int textureOffset; + private static byte nextId = 0; + private static boolean blinkState; + + private EnumSignalAspect(int textureOffset) + { + this.textureOffset = textureOffset; + id = getNextId(); + } + + /** + * Returns the aspect id, used mainly for saving and network communication. + * @return id + */ + public byte getId() + { + return id; + } + + /** + * Returns the texture offset for this specific aspect. + * @return offset + */ + public int getTextureOffset() + { + return textureOffset; + } + + /** + * Returns true if the aspect is one of the blink states. + * @return true if blinks + */ + public boolean isBlinkAspect() + { + if(this == BLINK_YELLOW || this == BLINK_RED) { + return true; + } + return false; + } + + /** + * Return true if the light is currently off. + * @return true if the light is currently off. + */ + public static boolean isBlinkOn() + { + return blinkState; + } + + /** + * Don't call this, its used to change blink states by Railcraft. + */ + public static void invertBlinkState() + { + blinkState = !blinkState; + } + + /** + * Takes an id and returns an Aspect. + * @param id + * @return + */ + public static EnumSignalAspect fromId(int id) + { + for(EnumSignalAspect a : EnumSignalAspect.values()) { + if(a.getId() == id) { + return a; + } + } + return RED; + } + + /** + * Tests two Aspects and determines which is more restrictive. + * The concept of "most restrictive" refers to which aspect enforces the + * most limitations of movement to a train. + * + * In Railcraft the primary use is in Signal Box logic. + * + * @param first + * @param second + * @return The most restrictive Aspect + */ + public static EnumSignalAspect mostRestrictive(EnumSignalAspect first, EnumSignalAspect second) + { + if(first == null && second != null) { + return second; + } else if(first != null && second == null) { + return first; + } else if(first == null && second == null) { + return RED; + } + if(first == OFF || second == OFF) { + return RED; + } + if(first.getId() > second.getId()) { + return first; + } + return second; + } + + private static byte getNextId() + { + byte i = nextId; + nextId++; + return i; + } + + @Override + public String toString() + { + String[] sa = name().split("_"); + String out = ""; + for(String s : sa) { + out = out + s.substring(0, 1) + s.substring(1).toLowerCase() + " "; + } + out = out.trim(); + return out; + } +} diff --git a/src/common/railcraft/common/api/signals/IBlockSignal.java b/src/common/railcraft/common/api/signals/IBlockSignal.java new file mode 100644 index 000000000..a115423c8 --- /dev/null +++ b/src/common/railcraft/common/api/signals/IBlockSignal.java @@ -0,0 +1,47 @@ +package railcraft.common.api.signals; + +/** + * This is not documented and needs some reworking to simplify usage. + * @author CovertJaguar + */ +public interface IBlockSignal +{ + + public void startSignalBlockPairing(); + + public void endSignalBlockPairing(); + + public boolean locateRail(); + + public boolean attemptToPair(IBlockSignal other); + + public void clearSignalBlockPairing(String reason, Object... args); + + public boolean isSignalBlockBeingPaired(); + + public boolean isSignalBlockPaired(); + + public IBlockSignal getSignalBlockPair(); + + public int getSignalBlockPairX(); + + public int getSignalBlockPairY(); + + public int getSignalBlockPairZ(); + + public int getRailX(); + + public int getRailY(); + + public int getRailZ(); + + public int getX(); + + public int getY(); + + public int getZ(); + + public int getDimension(); + + public String getDescription(); +} diff --git a/src/common/railcraft/common/api/signals/ISignalController.java b/src/common/railcraft/common/api/signals/ISignalController.java new file mode 100644 index 000000000..a3160d7ab --- /dev/null +++ b/src/common/railcraft/common/api/signals/ISignalController.java @@ -0,0 +1,45 @@ +package railcraft.common.api.signals; + +import net.minecraft.src.World; + +/** + * This is not documented and needs some reworking to simplify usage. + * @author CovertJaguar + */ +public interface ISignalController +{ + + public EnumSignalAspect getSignalAspect(); + + public boolean attemptToPairWithReceiver(ISignalReceiver receiver); + + public void startReceiverPairing(); + + public void endReceiverPairing(); + + public void clearPairedReceiver(); + + public boolean isPairedWithReceiver(); + + public ISignalReceiver getReceiver(); + + public int getReceiverX(); + + public int getReceiverY(); + + public int getReceiverZ(); + + public int getX(); + + public int getY(); + + public int getZ(); + + public int getDimension(); + + public World getWorld(); + + public String getDescription(); + + public boolean isInvalid(); +} diff --git a/src/common/railcraft/common/api/signals/ISignalReceiver.java b/src/common/railcraft/common/api/signals/ISignalReceiver.java new file mode 100644 index 000000000..00de2b0cb --- /dev/null +++ b/src/common/railcraft/common/api/signals/ISignalReceiver.java @@ -0,0 +1,43 @@ +package railcraft.common.api.signals; + +import net.minecraft.src.World; + +/** + * This is not documented and needs some reworking to simplify usage. + * @author CovertJaguar + */ +public interface ISignalReceiver +{ + + public boolean doesActionOnAspect(EnumSignalAspect aspect); + + public void doActionOnAspect(EnumSignalAspect aspect, boolean trigger); + + public boolean attemptToPairWithController(ISignalController controller); + + public void clearPairedController(); + + public boolean isPairedWithController(); + + public ISignalController getController(); + + public int getControllerX(); + + public int getControllerY(); + + public int getControllerZ(); + + public int getX(); + + public int getY(); + + public int getZ(); + + public int getDimension(); + + public World getWorld(); + + public boolean isInvalid(); + + public String getDescription(); +} diff --git a/src/common/railcraft/common/api/signals/SignalTools.java b/src/common/railcraft/common/api/signals/SignalTools.java new file mode 100644 index 000000000..2c2b272c6 --- /dev/null +++ b/src/common/railcraft/common/api/signals/SignalTools.java @@ -0,0 +1,159 @@ +package railcraft.common.api.signals; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemStack; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import railcraft.common.api.tracks.RailTools; +import railcraft.common.api.core.WorldCoordinate; + +/** + * This is not documented and needs some reworking to simplify usage. + * @author CovertJaguar + */ +public abstract class SignalTools +{ + + private static Map signalBlockPairingMap = new HashMap(); + private static Map controllerReceiverPairingMap = new HashMap(); + + public static boolean isSignalBlockSectionValid(World world, IBlockSignal first, IBlockSignal second) { + return RailTools.areDistantRailsConnectedAlongAxis(world, first.getRailX(), first.getRailY(), first.getRailZ(), second.getRailX(), second.getRailY(), second.getRailZ()); + } + + public static boolean isControllerInRangeOfReceiver(ISignalController c, ISignalReceiver r, int range) { + int distX = c.getX() - r.getX(); + int distY = c.getY() - r.getY(); + int distZ = c.getZ() - r.getZ(); + int distance = (int)Math.sqrt(distX * distX + distY * distY + distZ * distZ); + return distance <= range; + } + + public static void startSignalBlockPairing(EntityPlayer player, ItemStack device, IBlockSignal first) { + endSignalBlockPairing(player, device); + int id = new Random().nextInt(Short.MAX_VALUE); + device.setItemDamage(id); + first.startSignalBlockPairing(); + signalBlockPairingMap.put(new PairingKey(player.username, device.getItemDamage()), new WorldCoordinate(first.getDimension(), first.getX(), first.getY(), first.getZ())); + } + + public static WorldCoordinate getSignalBlockPair(EntityPlayer player, ItemStack device) { + return signalBlockPairingMap.get(new PairingKey(player.username, device.getItemDamage())); + } + + public static void endSignalBlockPairing(EntityPlayer player, ItemStack device) { + WorldCoordinate pos = signalBlockPairingMap.remove(new PairingKey(player.username, device.getItemDamage())); + if(pos != null) { + TileEntity t = player.worldObj.getBlockTileEntity(pos.x, pos.y, pos.z); + if(t instanceof IBlockSignal) { + ((IBlockSignal)t).endSignalBlockPairing(); + } + } + } + + public static void startControllerReceiverPairing(EntityPlayer player, ItemStack device, ISignalController controller) { + endControllerReceiverPairing(player, device); + int id = new Random().nextInt(Short.MAX_VALUE); + device.setItemDamage(id); + controller.startReceiverPairing(); + controllerReceiverPairingMap.put(new PairingKey(player.username, device.getItemDamage()), new WorldCoordinate(controller.getDimension(), controller.getX(), controller.getY(), controller.getZ())); + } + + public static WorldCoordinate getSavedController(EntityPlayer player, ItemStack device) { + return controllerReceiverPairingMap.get(new PairingKey(player.username, device.getItemDamage())); + } + + public static void endControllerReceiverPairing(EntityPlayer player, ItemStack device) { + WorldCoordinate pos = controllerReceiverPairingMap.remove(new PairingKey(player.username, device.getItemDamage())); + if(pos != null) { + TileEntity t = player.worldObj.getBlockTileEntity(pos.x, pos.y, pos.z); + if(t instanceof ISignalController) { + ((ISignalController)t).endReceiverPairing(); + } + } + } + + public static ISignalReceiver getReceiverFor(ISignalController con) { + World world = con.getWorld(); + if(world == null || con.getReceiverY() < 0) { + return null; + } + int i = con.getReceiverX(); + int j = con.getReceiverY(); + int k = con.getReceiverZ(); + if(!world.blockExists(i, j, k)) { + return null; + } + TileEntity pair = world.getBlockTileEntity(i, j, k); + if(pair instanceof ISignalReceiver) { + return (ISignalReceiver)pair; + } else { + con.clearPairedReceiver(); + } + return null; + } + + public static ISignalController getControllerFor(ISignalReceiver rec) { + if(rec.getControllerY() < 0) { + return null; + } + World world = rec.getWorld(); + if(world == null) { + return null; + } + int i = rec.getControllerX(); + int j = rec.getControllerY(); + int k = rec.getControllerZ(); + if(!world.blockExists(i, j, k)) { + return null; + } + TileEntity pair = world.getBlockTileEntity(i, j, k); + if(pair instanceof ISignalController) { + return (ISignalController)pair; + } else { + rec.clearPairedController(); + } + return null; + } + + private static class PairingKey + { + + protected String username; + protected int id; + + public PairingKey(String username, int id) { + this.username = username; + this.id = id; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 59 * hash + (this.username != null ? this.username.hashCode() : 0); + hash = 59 * hash + this.id; + return hash; + } + + @Override + public boolean equals(Object obj) { + if(obj == null) { + return false; + } + if(getClass() != obj.getClass()) { + return false; + } + final PairingKey other = (PairingKey)obj; + if((this.username == null) ? (other.username != null) : !this.username.equals(other.username)) { + return false; + } + if(this.id != other.id) { + return false; + } + return true; + } + } +} diff --git a/src/common/railcraft/common/api/tracks/ITrackCustomPlaced.java b/src/common/railcraft/common/api/tracks/ITrackCustomPlaced.java new file mode 100644 index 000000000..0354d1a6e --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackCustomPlaced.java @@ -0,0 +1,29 @@ +package railcraft.common.api.tracks; + +import net.minecraft.src.World; + +/** + * Have your ITrackInstance implement this to override normal track placement. + * + * Used by tracks such as the Suspended Track. + * + * @author CovertJaguar + */ +public interface ITrackCustomPlaced extends ITrackInstance +{ + + /** + * Used to override normal track placement. + * + * Used by tracks such as the Suspended Track. + * + * Warning: This is called before the TileEntity is set. + * + * @param world The World + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @return true if the rail can placed at the specified location, false to prevent placement + */ + public boolean canPlaceRailAt(World world, int i, int j, int k); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackCustomShape.java b/src/common/railcraft/common/api/tracks/ITrackCustomShape.java new file mode 100644 index 000000000..35fd7e43a --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackCustomShape.java @@ -0,0 +1,24 @@ +package railcraft.common.api.tracks; + +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.MovingObjectPosition; +import net.minecraft.src.Vec3; + +/** + * Used by rails that modify the bounding boxes. + * + * For example, the Gated Rails. + * + * Not very useful since there is no system in place to insert custom render code. + * + * @author CovertJaguar + */ +public interface ITrackCustomShape extends ITrackInstance +{ + + public AxisAlignedBB getCollisionBoundingBoxFromPool(); + + public AxisAlignedBB getSelectedBoundingBoxFromPool(); + + public MovingObjectPosition collisionRayTrace(Vec3 vec3d, Vec3 vec3d1); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackEmitter.java b/src/common/railcraft/common/api/tracks/ITrackEmitter.java new file mode 100644 index 000000000..bec74732a --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackEmitter.java @@ -0,0 +1,22 @@ +package railcraft.common.api.tracks; + +/** + * Tracks that can emit a redstone signal should implement + * this interface. + * + * For example a detector track. + * + * A track cannot implement both ITrackPowered and ITrackEmitter. + * + * @author CovertJaguar + */ +public interface ITrackEmitter extends ITrackInstance +{ + + /** + * Return true if the track is producing a redstone signal. + * + * @return true if powered + */ + public boolean isTrackPowering(); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackInstance.java b/src/common/railcraft/common/api/tracks/ITrackInstance.java new file mode 100644 index 000000000..460959fa6 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackInstance.java @@ -0,0 +1,123 @@ +package railcraft.common.api.tracks; + +import net.minecraft.src.Entity; +import net.minecraft.src.EntityLiving; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import railcraft.common.api.core.INetworkedObject; + +/** + * This interface defines a track. + * + * Basically all block and tile entity functions for Tracks are delegated to an + * ITrackInstance. + * + * Instead of implementing this interface directly, you should probably + * extend TrackInstanceBase. It will simplify your life. + * + * All packet manipulation is handled by Railcraft's code, + * you just need to implement the functions in INetworkedObject + * to pass data from the server to the client. + * + * @author CovertJaguar + * @see TrackInstanceBase + */ +public interface ITrackInstance extends INetworkedObject +{ + + public TrackSpec getTrackSpec(); + + /** + * Return the rail's metadata (without the power bit if the rail uses one). + * Can be used to make the cart think the rail something other than it is, + * for example when making diamond junctions or switches. + * + * Valid rail metadata is defined as follows: + * 0x0: flat track going North-South + * 0x1: flat track going West-East + * 0x2: track ascending to the East + * 0x3: track ascending to the West + * 0x4: track ascending to the North + * 0x5: track ascending to the South + * 0x6: WestNorth corner (connecting East and South) + * 0x7: EastNorth corner (connecting West and South) + * 0x8: EastSouth corner (connecting West and North) + * 0x9: WestSouth corner (connecting East and North) + * + * @param cart The cart asking for the metadata, null if it is not called by EntityMinecart. + * @return The metadata. + */ + public int getBasicRailMetadata(EntityMinecart cart); + + /** + * This function is called by any minecart that passes over this rail. + * It is called once per update tick that the minecart is on the rail. + * @param cart The cart on the rail. + */ + public void onMinecartPass(EntityMinecart cart); + + /** + * Return the block texture to be used. + * + * @return + */ + public int getTextureIndex(); + + public void writeToNBT(NBTTagCompound data); + + public void readFromNBT(NBTTagCompound data); + + /** + * Return true if this track requires update ticks. + * @return + */ + public boolean canUpdate(); + + public void updateEntity(); + + public boolean blockActivated(EntityPlayer player); + + public void onBlockPlaced(int side); + + public void onBlockPlacedBy(EntityLiving entity); + + public void onNeighborBlockChange(int id); + + /** + * Internal function that sets the Track's TileEntity so it can + * be referenced for position information, etc... + * @param tile + */ + public void setTile(TileEntity tile); + + public int getX(); + + public int getY(); + + public int getZ(); + + public float getExplosionResistance(double srcX, double srcY, double srcZ, Entity exploder); + + /** + * Return true if the rail can make corners. + * Used by placement logic. + * @return true if the rail can make corners. + */ + public boolean isFlexibleRail(); + + /** + * Returns true if the rail can make up and down slopes. + * Used by placement logic. + * @return true if the rail can make slopes. + */ + public boolean canMakeSlopes(); + + /** + * Returns the max speed of the rail. + * @param cart The cart on the rail, may be null. + * @return The max speed of the current rail. + */ + public float getRailMaxSpeed(EntityMinecart cart); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackLockdown.java b/src/common/railcraft/common/api/tracks/ITrackLockdown.java new file mode 100644 index 000000000..c9c287b45 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackLockdown.java @@ -0,0 +1,18 @@ +package railcraft.common.api.tracks; + +import net.minecraft.src.EntityMinecart; + +/** + * Any rail tile entity that can completely halt + * all cart movement should implement this interface. + * (Used in collision handling) + * + * @author CovertJaguar + */ +public interface ITrackLockdown extends ITrackInstance +{ + + public boolean isCartLockedDown(EntityMinecart cart); + + public void releaseCart(); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackPowered.java b/src/common/railcraft/common/api/tracks/ITrackPowered.java new file mode 100644 index 000000000..66a9c434e --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackPowered.java @@ -0,0 +1,24 @@ +package railcraft.common.api.tracks; + +/** + * Implementing this interface will allow your track to be + * powered via Redstone. + * + * And so long as you inherit from TrackInstanceBase, all the code for updating + * the power state is already in place (including propagation). + * + * @author CovertJaguar + */ +public interface ITrackPowered extends ITrackInstance +{ + + public boolean isPowered(); + + public void setPowered(boolean powered); + + /** + * The distance that a redstone signal will be passed along from track to track. + * @return int + */ + public int getPowerPropagation(); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackReversable.java b/src/common/railcraft/common/api/tracks/ITrackReversable.java new file mode 100644 index 000000000..c44bff8de --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackReversable.java @@ -0,0 +1,17 @@ +package railcraft.common.api.tracks; + +/** + * Implementing this interface will allow your track to be direction specific. + * + * And so long as you inherit from TrackInstanceBase it will automatically be + * reversable via the Crowbar. + * + * @author CovertJaguar + */ +public interface ITrackReversable extends ITrackInstance +{ + + public boolean isReversed(); + + public void setReversed(boolean reversed); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackSwitch.java b/src/common/railcraft/common/api/tracks/ITrackSwitch.java new file mode 100644 index 000000000..735bd8cf8 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackSwitch.java @@ -0,0 +1,21 @@ +package railcraft.common.api.tracks; + +public interface ITrackSwitch extends ITrackInstance +{ + + enum ArrowDirection + { + + NORTH, SOUTH, EAST, WEST, NORTH_SOUTH, EAST_WEST + }; + + public boolean isSwitched(); + + public void setSwitched(boolean switched); + + public boolean isMirrored(); + + public ArrowDirection getRedSignDirection(); + + public ArrowDirection getWhiteSignDirection(); +} diff --git a/src/common/railcraft/common/api/tracks/ITrackTile.java b/src/common/railcraft/common/api/tracks/ITrackTile.java new file mode 100644 index 000000000..54140bc98 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/ITrackTile.java @@ -0,0 +1,13 @@ +package railcraft.common.api.tracks; + +/** + * Don't use this, its an interface that allows other API code + * access to internal functions of the code. + * + * @author CovertJaguar + */ +public interface ITrackTile +{ + + public ITrackInstance getTrackInstance(); +} diff --git a/src/common/railcraft/common/api/tracks/RailTools.java b/src/common/railcraft/common/api/tracks/RailTools.java new file mode 100644 index 000000000..393530202 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/RailTools.java @@ -0,0 +1,175 @@ +package railcraft.common.api.tracks; + +import railcraft.common.api.core.items.ITrackItem; +import net.minecraft.src.Block; +import net.minecraft.src.BlockRail; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.ItemBlock; +import net.minecraft.src.ItemStack; +import net.minecraft.src.MathHelper; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; + +/** + * A number of utility functions related to rails. + * @author CovertJaguar + */ +public abstract class RailTools +{ + + /** + * Attempts to place a rail of the type provided. + * There is no need to verify that the ItemStack contains a valid rail + * prior to calling this function. + * + * The function takes care of that and will return false if the ItemStack + * is not a valid ITrackItem or an ItemBlock who's id + * will return true when passed to BlockRail.isRailBlock(itemID). + * + * That means this function can place any Railcraft or vanilla rail + * and has at least a decent chance of being able to place + * most third party rails. + * + * @param stack The ItemStack containing the rail + * @param world The World object + * @param i x-Coord + * @param j y-Coord + * @param k z-Coord + * @return true if successful + * @see ITrackItem + */ + public static boolean placeRailAt(ItemStack stack, World world, int i, int j, int k) + { + if(stack == null) { + return false; + } + if(stack.getItem() instanceof ITrackItem) { + return ((ITrackItem)stack.getItem()).placeTrack(stack.copy(), world, i, j, k); + } + if(stack.getItem() instanceof ItemBlock && stack.itemID < Block.blocksList.length && BlockRail.isRailBlock(stack.itemID)) { + boolean success = world.setBlockWithNotify(i, j, k, stack.itemID); + if(success) { + world.playSoundEffect((float)i + 0.5F, (float)j + 0.5F, (float)k + 0.5F, Block.rail.stepSound.getStepSound(), (Block.rail.stepSound.getVolume() + 1.0F) / 2.0F, Block.rail.stepSound.getPitch() * 0.8F); + } + return success; + } + return false; + } + + /** + * Returns true if the ItemStack contains a valid Railcraft Track item. + * + * Will return false is passed a vanilla rail. + * + * @param stack The ItemStack to test + * @return true if rail + * @see ITrackItem + */ + public static boolean isTrackItem(ItemStack stack) + { + return stack != null && stack.getItem() instanceof ITrackItem; + } + + /** + * Checks to see if a cart is being held by a ITrackLockdown. + * @param cart The cart to check + * @return True if being held + */ + public static boolean isCartLockedDown(EntityMinecart cart) + { + int x = MathHelper.floor_double(cart.posX); + int y = MathHelper.floor_double(cart.posY); + int z = MathHelper.floor_double(cart.posZ); + + if(BlockRail.isRailBlockAt(cart.worldObj, x, y - 1, z)) { + y--; + } + + TileEntity tile = cart.worldObj.getBlockTileEntity(x, y, z); + if(tile instanceof ITrackTile) { + ITrackInstance track = ((ITrackTile)tile).getTrackInstance(); + return track instanceof ITrackLockdown && ((ITrackLockdown)track).isCartLockedDown(cart); + } + return false; + } + + /** + * Verifies that two rails are connected to each other + * along a straight line with no gaps or wanderings. + * @param world The World object + * @param i1 x-Coord of Rail #1 + * @param j1 y-Coord of Rail #1 + * @param k1 z-Coord of Rail #1 + * @param i2 x-Coord of Rail #2 + * @param j2 y-Coord of Rail #2 + * @param k2 z-Coord of Rail #2 + * @return true if they are connected + */ + public static boolean areDistantRailsConnectedAlongAxis(World world, int i1, int j1, int k1, int i2, int j2, int k2) + { + if(j1 < 0 || j2 < 0) { + return false; + } + if(i1 != i2 && k1 != k2) { + return false; + } + if(i1 != i2) { + int min = 0; + int max = 0; + int jj = 0; + if(i1 < i2) { + min = i1; + max = i2; + jj = j1; + } else { + min = i2; + max = i1; + jj = j2; + } + for(int ii = min; ii <= max; ii++) { + if(world.blockExists(ii, jj, k1)) { + if(BlockRail.isRailBlockAt(world, ii, jj, k1)) { + continue; + } else if(BlockRail.isRailBlockAt(world, ii, jj - 1, k1)) { + jj--; + continue; + } else if(BlockRail.isRailBlockAt(world, ii, jj + 1, k1)) { + jj++; + continue; + } else { + return false; + } + } + } + } else if(k1 != k2) { + int min = 0; + int max = 0; + int jj = 0; + if(k1 < k2) { + min = k1; + max = k2; + jj = j1; + } else { + min = k2; + max = k1; + jj = j2; + } + for(int kk = min; kk <= max; kk++) { + if(world.blockExists(i1, jj, kk)) { + if(BlockRail.isRailBlockAt(world, i1, jj, kk)) { + continue; + } else if(BlockRail.isRailBlockAt(world, i1, jj - 1, kk)) { + jj--; + continue; + } else if(BlockRail.isRailBlockAt(world, i1, jj + 1, kk)) { + jj++; + continue; + } else { + return false; + } + } + } + } + return true; + } +} diff --git a/src/common/railcraft/common/api/tracks/TrackInstanceBase.java b/src/common/railcraft/common/api/tracks/TrackInstanceBase.java new file mode 100644 index 000000000..35d04573e --- /dev/null +++ b/src/common/railcraft/common/api/tracks/TrackInstanceBase.java @@ -0,0 +1,385 @@ +package railcraft.common.api.tracks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import net.minecraft.src.Block; +import net.minecraft.src.BlockRail; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityLiving; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemStack; +import net.minecraft.src.MathHelper; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.RailLogic; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; +import railcraft.common.api.core.items.ICrowbar; + +/** + * All ITrackInstances should extend this class. It contains a number of + * default functions and standard behavior for Tracks that should + * greatly simplify implementing new Tracks when using this API. + * + * @author CovertJaguar + * @see ITrackInstance + * @see TrackRegistry + * @see TrackSpec + */ +public abstract class TrackInstanceBase implements ITrackInstance +{ + + private Block block; + public TileEntity tileEntity; + + private Block getBlock() + { + if(block == null) { + int id = getWorld().getBlockId(getX(), getY(), getZ()); + block = Block.blocksList[id]; + } + return block; + } + + @Override + public void setTile(TileEntity tile) + { + tileEntity = tile; + } + + @Override + public int getBasicRailMetadata(EntityMinecart cart) + { + return tileEntity.getBlockMetadata(); + } + + @Override + public void onMinecartPass(EntityMinecart cart) + { + } + + @Override + public boolean blockActivated(EntityPlayer player) + { + if(this instanceof ITrackReversable) { + ItemStack current = player.getCurrentEquippedItem(); + if(current != null && current.getItem() instanceof ICrowbar) { + ITrackReversable track = (ITrackReversable)this; + track.setReversed(!track.isReversed()); + markBlockNeedsUpdate(); + if(current.isItemStackDamageable()) { + current.damageItem(1, player); + } + return true; + } + } + return false; + } + + @Override + public void onBlockPlaced(int side) + { + switchTrack(true); + testPower(); + markBlockNeedsUpdate(); + } + + @Override + public void onBlockPlacedBy(EntityLiving entityliving) + { + if(entityliving == null) { + return; + } + if(this instanceof ITrackReversable) { + int dir = MathHelper.floor_double((double)((entityliving.rotationYaw * 4F) / 360F) + 0.5D) & 3; + ((ITrackReversable)this).setReversed(dir == 0 || dir == 1); + } + markBlockNeedsUpdate(); + } + + public void markBlockNeedsUpdate() + { + getWorld().markBlockNeedsUpdate(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord); + } + + protected boolean isRailValid(World world, int i, int j, int k, int meta) + { + boolean valid = true; + if(!world.isBlockSolidOnSide(i, j - 1, k, ForgeDirection.UP)) { + valid = false; + } + if(meta == 2 && !world.isBlockSolidOnSide(i + 1, j, k, ForgeDirection.UP)) { + valid = false; + } else if(meta == 3 && !world.isBlockSolidOnSide(i - 1, j, k, ForgeDirection.UP)) { + valid = false; + } else if(meta == 4 && !world.isBlockSolidOnSide(i, j, k - 1, ForgeDirection.UP)) { + valid = false; + } else if(meta == 5 && !world.isBlockSolidOnSide(i, j, k + 1, ForgeDirection.UP)) { + valid = false; + } + return valid; + } + + @Override + public void onNeighborBlockChange(int id) + { + int meta = tileEntity.getBlockMetadata(); + boolean valid = isRailValid(getWorld(), tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, meta); + if(!valid) { + Block blockTrack = getBlock(); + blockTrack.dropBlockAsItem(getWorld(), tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, 0, 0); + getWorld().setBlockWithNotify(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, 0); + return; + } + + BlockRail blockTrack = (BlockRail)getBlock(); + if(id > 0 && Block.blocksList[id].canProvidePower() && isFlexibleRail() && RailLogic.getAdjacentTracks(new RailLogic(blockTrack, getWorld(), tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord)) == 3) { + switchTrack(false); + } + testPower(); + } + + protected void switchTrack(boolean flag) + { + int i = tileEntity.xCoord; + int j = tileEntity.yCoord; + int k = tileEntity.zCoord; + BlockRail blockTrack = (BlockRail)getBlock(); + (new RailLogic(blockTrack, getWorld(), i, j, k)).refreshTrackShape(getWorld().isBlockIndirectlyGettingPowered(i, j, k), flag); + } + + protected void testPower() + { + if(!(this instanceof ITrackPowered)) { + return; + } + int i = tileEntity.xCoord; + int j = tileEntity.yCoord; + int k = tileEntity.zCoord; + ITrackPowered r = (ITrackPowered)this; + int meta = tileEntity.getBlockMetadata(); + boolean powered = getWorld().isBlockIndirectlyGettingPowered(i, j, k) || getWorld().isBlockIndirectlyGettingPowered(i, j + 1, k) || testPowerPropagation(getWorld(), i, j, k, getTrackSpec(), meta, r.getPowerPropagation()); + if(powered != r.isPowered()) { + r.setPowered(powered); + Block blockTrack = getBlock(); + getWorld().notifyBlocksOfNeighborChange(i, j, k, blockTrack.blockID); + getWorld().notifyBlocksOfNeighborChange(i, j - 1, k, blockTrack.blockID); + if(meta == 2 || meta == 3 || meta == 4 || meta == 5) { + getWorld().notifyBlocksOfNeighborChange(i, j + 1, k, blockTrack.blockID); + } + markBlockNeedsUpdate(); + // System.out.println("Setting power [" + i + ", " + j + ", " + k + "]"); + } + } + + protected boolean testPowerPropagation(World world, int i, int j, int k, TrackSpec spec, int meta, int maxDist) + { + return isConnectedRailPowered(world, i, j, k, spec, meta, true, 0, maxDist) || isConnectedRailPowered(world, i, j, k, spec, meta, false, 0, maxDist); + } + + protected boolean isConnectedRailPowered(World world, int i, int j, int k, TrackSpec spec, int meta, boolean dir, int dist, int maxDist) + { + if(dist >= maxDist) { + return false; + } + boolean powered = true; + switch (meta) { + case 0: // '\0' + if(dir) { + k++; + } else { + k--; + } + break; + + case 1: // '\001' + if(dir) { + i--; + } else { + i++; + } + break; + + case 2: // '\002' + if(dir) { + i--; + } else { + i++; + j++; + powered = false; + } + meta = 1; + break; + + case 3: // '\003' + if(dir) { + i--; + j++; + powered = false; + } else { + i++; + } + meta = 1; + break; + + case 4: // '\004' + if(dir) { + k++; + } else { + k--; + j++; + powered = false; + } + meta = 0; + break; + + case 5: // '\005' + if(dir) { + k++; + j++; + powered = false; + } else { + k--; + } + meta = 0; + break; + } + if(testPowered(world, i, j, k, spec, dir, dist, maxDist, meta)) { + return true; + } + return powered && testPowered(world, i, j - 1, k, spec, dir, dist, maxDist, meta); + } + + protected boolean testPowered(World world, int i, int j, int k, TrackSpec spec, boolean dir, int dist, int maxDist, int orientation) + { + // System.out.println("Testing Power at <" + i + ", " + j + ", " + k + ">"); + int id = world.getBlockId(i, j, k); + Block blockTrack = getBlock(); + if(id == blockTrack.blockID) { + int meta = world.getBlockMetadata(i, j, k); + TileEntity tile = world.getBlockTileEntity(i, j, k); + if(tile instanceof ITrackTile) { + ITrackInstance track = ((ITrackTile)tile).getTrackInstance(); + if(!(track instanceof ITrackPowered) || track.getTrackSpec() != spec) { + return false; + } + if(orientation == 1 && (meta == 0 || meta == 4 || meta == 5)) { + return false; + } + if(orientation == 0 && (meta == 1 || meta == 2 || meta == 3)) { + return false; + } + if(((ITrackPowered)track).isPowered()) { + if(world.isBlockIndirectlyGettingPowered(i, j, k) || world.isBlockIndirectlyGettingPowered(i, j + 1, k)) { + return true; + } else { + return isConnectedRailPowered(world, i, j, k, spec, meta, dir, dist + 1, maxDist); + } + } + } + } + return false; + } + + @Override + public int getTextureIndex() + { + return getTrackSpec().getTextureIndex(); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + } + + @Override + public boolean canUpdate() + { + return false; + } + + @Override + public void updateEntity() + { + } + + @Override + public float getExplosionResistance(double srcX, double srcY, double srcZ, Entity exploder) + { + return 3.5f; + } + + @Override + public void writePacketData(DataOutputStream data) throws IOException + { + } + + @Override + public void readPacketData(DataInputStream data) throws IOException + { + } + + @Override + public World getWorld() + { + return tileEntity.worldObj; + } + + @Override + public int getX() + { + return tileEntity.xCoord; + } + + @Override + public int getY() + { + return tileEntity.yCoord; + } + + @Override + public int getZ() + { + return tileEntity.zCoord; + } + + /** + * Return true if the rail can make corners. + * Used by placement logic. + * @return true if the rail can make corners. + */ + @Override + public boolean isFlexibleRail() + { + return false; + } + + /** + * Returns true if the rail can make up and down slopes. + * Used by placement logic. + * @return true if the rail can make slopes. + */ + @Override + public boolean canMakeSlopes() + { + return true; + } + + /** + * Returns the max speed of the rail. + * @param cart The cart on the rail, may be null. + * @return The max speed of the current rail. + */ + @Override + public float getRailMaxSpeed(EntityMinecart cart) + { + return 0.4f; + } +} diff --git a/src/common/railcraft/common/api/tracks/TrackRegistry.java b/src/common/railcraft/common/api/tracks/TrackRegistry.java new file mode 100644 index 000000000..017dd31f6 --- /dev/null +++ b/src/common/railcraft/common/api/tracks/TrackRegistry.java @@ -0,0 +1,62 @@ +package railcraft.common.api.tracks; + +import cpw.mods.fml.common.FMLCommonHandler; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; + +/** + * The TrackRegistry is part of a system that allows 3rd party addons to simply, + * quickly, and easily define new Tracks with unique behaviors without requiring + * that any additional block ids be used. + * + * All the tracks in RailcraftProxy are implemented using this system 100% + * (except for Gated Tracks and Switch Tracks which have some custom render code). + * + * To define a new track, you need to define a TrackSpec and create a ITrackInstance. + * + * The TrackSpec contains basic constant information about the Track, while the TrackInstace + * controls how an individual Track block interact with the world. + * + * @author CovertJaguar + * @see TrackSpec + * @see ITrackInstance + * @see TrackInstanceBase + */ +public class TrackRegistry +{ + + private static Map trackSpecs = new HashMap(); + + public static void registerTrackSpec(TrackSpec trackSpec) + { + if(trackSpecs.put(trackSpec.getTrackId(), trackSpec) != null) { + throw new RuntimeException("TrackId conflict detected, please adjust your config or contact the author of the " + trackSpec.getTrackTag()); + } + } + + /** + * Returns a cached copy of a TrackSpec object. + * + * @param trackId + * @return + */ + public static TrackSpec getTrackSpec(int trackId) + { + TrackSpec spec = trackSpecs.get((short)trackId); + if(spec == null) { + FMLCommonHandler.instance().getFMLLogger().log(Level.WARNING, "[Railcraft] Unknown Track Spec ID({0}), reverting to normal track", trackId); + spec = trackSpecs.get(-1); + } + return spec; + } + + /** + * Returns all Registered TrackSpecs. + * @return list of TrackSpecs + */ + public static Map getTrackSpecs() + { + return trackSpecs; + } +} diff --git a/src/common/railcraft/common/api/tracks/TrackSpec.java b/src/common/railcraft/common/api/tracks/TrackSpec.java new file mode 100644 index 000000000..68608a63a --- /dev/null +++ b/src/common/railcraft/common/api/tracks/TrackSpec.java @@ -0,0 +1,86 @@ +package railcraft.common.api.tracks; + +import net.minecraft.src.ItemStack; +import railcraft.common.api.core.items.ItemRegistry; + +/** + * Each type of Track has a single instance of TrackSpec + * that corresponds with it. + * + * Each Track block in the world has a ITrackInstance that + * corresponds with it. + * + * Take note of the difference (similar to block classes and tile entities classes). + * + * TrackSpecs must be registered with the TrackRegistry. + * + * Track Items can be acquired with the ItemRegistry. + * + * @see TrackRegistry + * @see ITrackInstance + * + * @author CovertJaguar + */ +public final class TrackSpec +{ + + public static int blockID = 0; + private final String tag; + private final String textureFile; + private final short trackId; + private final int textureId; + private final Class instanceClass; + + /** + * Defines a new track spec. + * + * @param trackId A unique identifier for the track type. 0-512 are reserved for Railcraft. Capped at Short.MAX_VALUE + * @param tag A unique internal string identifier (ex. "track.speed.transition") + * @param textureFile See ITextureProvider + * @param textureId The texture index used by the track's item + * @param instanceClass The ITrackInstance class that corresponds to this TrackSpec + * @see ITextureProvider + */ + public TrackSpec(short trackId, String tag, String textureFile, int textureId, Class instanceClass) { + this.trackId = trackId; + this.tag = tag; + this.textureFile = textureFile; + this.textureId = textureId; + this.instanceClass = instanceClass; + } + + public String getTrackTag() { + return tag; + } + + public short getTrackId() { + return trackId; + } + + public ItemStack getItem() { + return getItem(1); + } + + public ItemStack getItem(int qty) { + if(blockID <= 0) { + return null; + } + return new ItemStack(blockID, qty, getTrackId()); + } + + public ITrackInstance createInstanceFromSpec() { + try { + return (ITrackInstance)instanceClass.newInstance(); + } catch (Exception ex) { + throw new RuntimeException("Improper Track Instance Constructor"); + } + } + + public String getTextureFile() { + return textureFile; + } + + public int getTextureIndex() { + return textureId; + } +} diff --git a/src/common/universalelectricity/BasicComponents.java b/src/common/universalelectricity/BasicComponents.java new file mode 100644 index 000000000..14a0e220d --- /dev/null +++ b/src/common/universalelectricity/BasicComponents.java @@ -0,0 +1,60 @@ +package universalelectricity; + +import net.minecraft.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import universalelectricity.ore.OreGenBase; +import universalelectricity.prefab.ItemElectric; + +/** + * The main class for managing Basic Component items and blocks. Reference objects from this class to add them to your + * recipes and such. + * @author Calclavia + */ + +public class BasicComponents +{ + public static final String FILE_PATH = "/basiccomponents/textures/"; + public static final String BLOCK_TEXTURE_FILE = FILE_PATH + "blocks.png"; + public static final String ITEM_TEXTURE_FILE = FILE_PATH + "items.png"; + + /** + * Try not reference to these variable in pre-initialization as they might be null! + */ + public static int BLOCK_ID_PREFIX = 3970; + + //Metadata ore block that contains copper + public static Block blockBasicOre; + public static Block blockCopperWire; + public static Block oilMoving; + public static Block oilStill; + public static Block blockMachine; + + public static final int ITEM_ID_PREFIX = 13970; + public static ItemElectric itemBattery; + public static Item itemWrench; + public static Item itemCopperIngot; + public static Item itemTinIngot; + public static Item itemSteelIngot; + public static Item itemSteelDust; + public static Item itemCircuit; + public static Item itemBronzeIngot; + public static Item itemBronzeDust; + public static Item itemSteelPlate; + public static Item itemBronzePlate; + public static Item itemMotor; + public static Item itemOilBucket; + public static Item itemCopperPlate; + public static Item itemTinPlate; + + /** + * Some neat references to help you out. + */ + public static ItemStack coalGenerator; + public static ItemStack batteryBox; + public static ItemStack electricFurnace; + + + public static OreGenBase copperOreGeneration; + public static OreGenBase tinOreGeneration; +} diff --git a/src/common/universalelectricity/Ticker.java b/src/common/universalelectricity/Ticker.java new file mode 100644 index 000000000..d67e457aa --- /dev/null +++ b/src/common/universalelectricity/Ticker.java @@ -0,0 +1,49 @@ +package universalelectricity; + +import java.util.EnumSet; + +import universalelectricity.electricity.ElectricityManager; +import cpw.mods.fml.common.ITickHandler; +import cpw.mods.fml.common.TickType; + +public class Ticker implements ITickHandler +{ + public static long inGameTicks = 0; + + @Override + public void tickStart(EnumSet type, Object... tickData) + { + if(ElectricityManager.instance != null) + { + ElectricityManager.instance.tickStart(type, tickData); + } + } + + @Override + public void tickEnd(EnumSet type, Object... tickData) + { + if(ElectricityManager.instance != null) + { + ElectricityManager.instance.tickEnd(type, tickData); + } + + inGameTicks ++; + + if(inGameTicks >= Long.MAX_VALUE) + { + inGameTicks = 0; + } + } + + @Override + public EnumSet ticks() + { + return EnumSet.of(TickType.SERVER, TickType.CLIENT); + } + + @Override + public String getLabel() + { + return "Electricity Manager"; + } +} diff --git a/src/common/universalelectricity/UEConfig.java b/src/common/universalelectricity/UEConfig.java new file mode 100644 index 000000000..3d57a2a1a --- /dev/null +++ b/src/common/universalelectricity/UEConfig.java @@ -0,0 +1,56 @@ +package universalelectricity; + +import net.minecraftforge.common.Configuration; + +public class UEConfig +{ + public static int getConfigData(Configuration configuration, String name, int defaultInt) + { + configuration.load(); + int returnInt = defaultInt; + returnInt = Integer.parseInt(configuration.get(name, Configuration.CATEGORY_GENERAL, defaultInt).value); + configuration.save(); + return returnInt; + } + + public static boolean getConfigData(Configuration configuration, String name, boolean defaultBoolean) + { + configuration.load(); + boolean returnBoolean = defaultBoolean; + returnBoolean = Boolean.parseBoolean(configuration.get(name, Configuration.CATEGORY_GENERAL, defaultBoolean).value); + configuration.save(); + return returnBoolean; + } + + public static int getBlockConfigID(Configuration configuration, String name, int defaultID) + { + configuration.load(); + int id = defaultID; + + id = Integer.parseInt(configuration.getBlock(name, defaultID).value); + + if (id <= 136) + { + return defaultID; + } + + configuration.save(); + return id; + } + + public static int getItemConfigID(Configuration configuration, String name, int defaultID) + { + configuration.load(); + int id = defaultID; + + id = Integer.parseInt(configuration.getItem(name, Configuration.CATEGORY_ITEM, defaultID).value); + + if (id < 256) + { + return defaultID; + } + + configuration.save(); + return id; + } +} diff --git a/src/common/universalelectricity/UniversalElectricity.java b/src/common/universalelectricity/UniversalElectricity.java new file mode 100644 index 000000000..7bdcb46b9 --- /dev/null +++ b/src/common/universalelectricity/UniversalElectricity.java @@ -0,0 +1,90 @@ +package universalelectricity; + +import java.io.File; + +import net.minecraft.src.MapColor; +import net.minecraft.src.Material; +import net.minecraftforge.common.Configuration; +import net.minecraftforge.common.ForgeVersion; +import cpw.mods.fml.common.Loader; + +public class UniversalElectricity +{ + public static final int MAJOR_VERSION = 0; + public static final int MINOR_VERSION = 9; + public static final int REVISION_VERSION = 1; + + public static final String VERSION = MAJOR_VERSION+"."+MINOR_VERSION+"."+REVISION_VERSION; + + public static final Configuration CONFIGURATION = new Configuration(new File(Loader.instance().getConfigDir(), "UniversalElectricity/UniversalElectricity.cfg")); + + //One IC2 EU is 0.012 Watt Hours. EU to Watt Hour + public static final float IC2_RATIO = (float)UEConfig.getConfigData(CONFIGURATION, "IC2 to UE Conversion Ratio", (int)(0.0045f*100000))/(float)100000; + + //One MJ is 13 Watt Hours. MJ to Watt Hour + public static final float BC3_RATIO = (float)UEConfig.getConfigData(CONFIGURATION, "BC3 to UE Conversion Ratio", (int)(0.05f*100000))/(float)100000;; + + public static final float Wh_IC2_RATIO = 1/IC2_RATIO; + + public static final float Wh_BC_RATIO = 1/BC3_RATIO; + + /** + * Use this material for all your machine blocks. It can be breakable by hand. + */ + public static final Material machine = new Material(MapColor.ironColor); + + public static void versionLock(int major, int minor, int revision, boolean strict) + { + if(MAJOR_VERSION != major) + { + throw new RuntimeException("Universal Electricity wrong version! Require v"+major+"."+minor+"."+revision); + } + + if(MINOR_VERSION < minor) + { + throw new RuntimeException("Universal Electricity minor version is too old! Require v"+major+"."+minor+"."+revision); + } + + if(REVISION_VERSION < revision) + { + if(strict) + { + throw new RuntimeException("Universal Electricity is too old! Require v"+major+"."+minor+"."+revision); + } + else + { + System.out.println("Universal Electricity is not the specified version. Odd things might happen. Require "+major+"."+minor+"."+revision); + } + } + } + + public static void forgeLock(int major, int minor, int revision, boolean strict) + { + if(ForgeVersion.getMajorVersion() != major) + { + throw new RuntimeException("Universal Electricity: Wrong Minecraft Forge version! Require "+major+"."+minor+"."+revision); + } + + if(ForgeVersion.getMinorVersion() < minor) + { + throw new RuntimeException("Universal Electricity: Minecraft Forge minor version is too old! Require "+major+"."+minor+"."+revision); + } + + if(ForgeVersion.getRevisionVersion() < revision) + { + if(strict) + { + throw new RuntimeException("Universal Electricity: Minecraft Forge revision version is too old! Require "+major+"."+minor+"."+revision); + } + else + { + System.out.println("Universal Electricity Warning: Minecraft Forge is not the specified version. Odd things might happen. Require "+major+"."+minor+"."+revision); + } + } + } + + public static void forgeLock(int major, int minor, int revision) + { + forgeLock(major, minor, revision, false); + } +} diff --git a/src/common/universalelectricity/electricity/ElectricInfo.java b/src/common/universalelectricity/electricity/ElectricInfo.java new file mode 100644 index 000000000..fc323558e --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricInfo.java @@ -0,0 +1,217 @@ +package universalelectricity.electricity; + + +/** + * A better way to storage information on electricity + * @author Calclavia + */ + +public class ElectricInfo +{ + public static enum ElectricUnit + { + AMPERE("Amp", "I"), + AMP_HOUR("Amp Hour", "Ah"), + VOLTAGE("Volt", "V"), + WATT("Watt", "W"), + WATT_HOUR("Watt Hour", "Wh"), + RESISTANCE("Ohm", "R"), + CONDUCTANCE("Siemens", "S"); + + public String name; + public String symbol; + + private ElectricUnit(String name, String symbol) + { + this.name = name; + this.symbol = symbol; + } + + public String getPlural() + { + return this.name+"s"; + } + } + + public static enum MeasurementUnit + { + MICRO("Micro", "mi", 0.000001), + MILLI("Milli", "m", 0.001), + KILO("Kilo", "k", 1000), + MEGA("Mega", "M", 1000000); + + public String name; + public String symbol; + public double process; + + private MeasurementUnit(String name, String symbol, double process) + { + this.name = name; + this.symbol = symbol; + this.process = process; + } + + public String getName(boolean isSymbol) + { + if(isSymbol) + { + return symbol; + } + else + { + return name; + } + } + + public double process(double value) + { + return value/this.process; + } + } + + public static double getAmps(double watts, double voltage) + { + return watts/voltage; + } + + public static double getAmps(double ampHours) + { + return ampHours*3600; + } + + public static double getAmpsFromWattHours(double wattHours, double voltage) + { + return getWatts(wattHours)/voltage; + } + + public static double getWattHoursFromAmpHours(double ampHours, double voltage) + { + return ampHours*voltage; + } + + public static double getAmpHours(double amps) + { + return amps/3600; + } + + public static double getWatts(double amps, double voltage) + { + return amps*voltage; + } + + public static double getWatts(double wattHours) + { + return wattHours*3600; + } + + public static double getWattHours(double watts) + { + return watts/3600; + } + + public static double getWattHours(double amps, double voltage) + { + return getWattHours(getWatts(amps, voltage)); + } + + public static double getResistance(double amps, double voltage) + { + return voltage/amps; + } + + public static double getConductance(double amps, double voltage) + { + return amps/voltage; + } + + /** + * Displays the unit as text. Works only for positive numbers. + */ + public static String getDisplay(double value, ElectricUnit unit, int significantFigures, boolean isShort) + { + String unitName = unit.name; + + if(isShort) + { + unitName = unit.symbol; + } + else if(value > 1) + { + unitName = unit.getPlural(); + } + + if(value == 0) + { + return value + " " + unitName; + } + + if(value <= MeasurementUnit.MILLI.process) + { + return roundDecimals(MeasurementUnit.MICRO.process(value), significantFigures) + " " + MeasurementUnit.MICRO.getName(isShort)+unitName; + } + + if(value < 1) + { + return roundDecimals(MeasurementUnit.MILLI.process(value), significantFigures) + " " + MeasurementUnit.MILLI.getName(isShort)+unitName; + } + + if(value > MeasurementUnit.KILO.process) + { + return roundDecimals(MeasurementUnit.KILO.process(value), significantFigures) + " " + MeasurementUnit.KILO.getName(isShort)+unitName; + } + + if(value > MeasurementUnit.MEGA.process) + { + return roundDecimals(MeasurementUnit.MEGA.process(value), significantFigures) + " " + MeasurementUnit.MEGA.getName(isShort)+unitName; + } + + return roundDecimals(value, significantFigures) + " " + unitName; + } + + public static String getDisplayShort(double value, ElectricUnit unit) + { + return getDisplay(value, unit, 2, true); + } + + public static String getDisplay(double value, ElectricUnit unit) + { + return getDisplay(value, unit, 2, false); + } + + public static String getDisplaySimple(double value, ElectricUnit unit, int significantFigures) + { + if(value > 1) + { + if(significantFigures < 1) + { + return (int)value + " " + unit.getPlural(); + } + + return roundDecimals(value, significantFigures) + " " + unit.getPlural(); + } + + if(significantFigures < 1) + { + return (int)value + " " + unit.name; + } + + return roundDecimals(value, significantFigures) + " " + unit.name; + } + + + /** + * Rounds a number to a specific number place places + * @param The number + * @return The rounded number + */ + public static double roundDecimals(double d, int significantFigures) + { + int j = (int)(d * Math.pow(10, significantFigures)); + return j / (double)Math.pow(10, significantFigures); + } + + public static double roundDecimals(double d) + { + return roundDecimals(d, 2); + } +} diff --git a/src/common/universalelectricity/electricity/ElectricityManager.java b/src/common/universalelectricity/electricity/ElectricityManager.java new file mode 100644 index 000000000..4aee52a57 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityManager.java @@ -0,0 +1,362 @@ +package universalelectricity.electricity; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.Ticker; +import universalelectricity.implement.IConductor; +import universalelectricity.implement.IElectricityReceiver; +import universalelectricity.prefab.TileEntityConductor; +import universalelectricity.prefab.Vector3; +import cpw.mods.fml.common.TickType; + +/** + * This class is used to manage electricity transferring and flow. It is also used to call updates on UE tile entities. + * + * Electricity Manager is made for each world so it doesn't conflict with electricity devices in different dimensions. + * @author Calclavia + * + */ +public class ElectricityManager +{ + /** + * ElectricityManager exists on both client and server side. + * Rely on the server side one as it is more accurate! Client side only simulates. + */ + public static ElectricityManager instance; + + private List electricityReceivers = new ArrayList(); + private List electricConductors = new ArrayList(); + + private List electricityTransferQueue = new ArrayList(); + private List electricityNetworks = new ArrayList(); + private int maxConnectionID = 0; + + public ElectricityManager() + { + System.out.println("Universal Electricity's Electricity Manager Initiated."); + } + + /** + * Registers an electricity consumer for it to receive electricity. + * Call it in your consumer's tile entity constructor like this: + * ElectricityManager.registerConsumer(this); + * @param newUnit - The consumer to be registered. + */ + public void registerElectricUnit(IElectricityReceiver newUnit) + { + if (!this.electricityReceivers.contains(newUnit)) + { + this.electricityReceivers.add(newUnit); + } + } + + /** + * Registers a UE conductor + * @param conductor - The conductor tile entity + * @return - The ID of the connection line that is assigned to this conductor + */ + public void registerConductor(TileEntityConductor newConductor) + { + cleanUpConnections(); + this.electricityNetworks.add(new ElectricityNetwork(getMaxConnectionID(), newConductor)); + + if (!this.electricConductors.contains(newConductor)) + { + this.electricConductors.add(newConductor); + } + } + + /** + * Merges two connection lines together into one. + * @param ID1 - ID of connection line + * @param ID2 - ID of connection line + */ + public void mergeConnection(int ID1, int ID2) + { + if(ID1 != ID2) + { + ElectricityNetwork connection1 = getConnectionByID(ID1); + ElectricityNetwork connection2 = getConnectionByID(ID2); + + if(connection1 != null && connection2 != null) + { + connection1.conductors.addAll(connection2.conductors); + connection1.setID(ID1); + this.electricityNetworks.remove(connection2); + } + else + { + System.err.println("Failed to merge Universal Electricity wire connections!"); + } + } + } + + /** + * Separate one connection line into two different ones between two conductors. + * This function does this by resetting all wires in the connection line and + * making them each reconnect. + * @param conductorA - existing conductor + * @param conductorB - broken/invalid conductor + */ + public void splitConnection(IConductor conductorA, IConductor conductorB) + { + ElectricityNetwork connection = getConnectionByID(conductorA.getConnectionID()); + connection.cleanUpArray(); + + for(IConductor conductor : connection.conductors) + { + conductor.reset(); + } + + for(IConductor conductor : connection.conductors) + { + for (byte i = 0; i < 6; i++) + { + conductor.updateConnectionWithoutSplit(Vector3.getConnectorFromSide(conductor.getWorld(), new Vector3(((TileEntity)conductor).xCoord, ((TileEntity)conductor).yCoord, ((TileEntity)conductor).zCoord), ForgeDirection.getOrientation(i)), ForgeDirection.getOrientation(i)); + } + } + } + + /** + * Gets a electricity wire connection line by it's connection ID + * @param ID + * @return + */ + public ElectricityNetwork getConnectionByID(int ID) + { + cleanUpConnections(); + + for (int i = 0; i < this.electricityNetworks.size(); i++) + { + if (this.electricityNetworks.get(i).getID() == ID) + { + return this.electricityNetworks.get(i); + } + } + + return null; + } + + /** + * Clean up and remove useless connections + */ + public void cleanUpConnections() + { + for (int i = 0; i < this.electricityNetworks.size(); i++) + { + this.electricityNetworks.get(i).cleanUpArray(); + + if (this.electricityNetworks.get(i).conductors.size() == 0) + { + this.electricityNetworks.remove(i); + } + } + } + + /** + * Get the highest connection ID. Use this to assign new wire connection lines + * @return + */ + public int getMaxConnectionID() + { + this.maxConnectionID ++; + return this.maxConnectionID; + } + + /** + * Produces electricity into a specific wire which will be distributed across the electricity network. + * @param sender - The machine sending the electricity. + * @param targetConductor - The conductor receiving the electricity (or connected to the machine). + * @param amps - The amount of amps this machine is sending. + * @param voltage 0 The amount of volts this machine is sending. + */ + public void produceElectricity(TileEntity sender, IConductor targetConductor, double amps, double voltage) + { + if(targetConductor != null && amps > 0 && voltage > 0) + { + //Find a path between this conductor and all connected units and try to send the electricity to them directly + ElectricityNetwork electricityNetwork = this.getConnectionByID(targetConductor.getConnectionID()); + + if(electricityNetwork != null) + { + List allElectricUnitsInLine = electricityNetwork.getConnectedReceivers(); + double leftOverAmps = amps; + + for (IConductor conductor : electricityNetwork.conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + IElectricityReceiver receiver = (IElectricityReceiver)tileEntity; + + if (Math.ceil(receiver.wattRequest()) > 0 && receiver.canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + double transferAmps = Math.max(0, Math.min(leftOverAmps, Math.min(amps / allElectricUnitsInLine.size(), ElectricInfo.getAmps(Math.ceil(receiver.wattRequest()), receiver.getVoltage()) ))); + leftOverAmps -= transferAmps; + + //Calculate electricity loss + double distance = Vector3.distance(Vector3.get(sender), Vector3.get((TileEntity)receiver)); + double ampsReceived = transferAmps - (transferAmps * transferAmps * targetConductor.getResistance() * distance)/voltage; + double voltsReceived = voltage - (transferAmps * targetConductor.getResistance() * distance); + + this.electricityTransferQueue.add(new ElectricityTransferData(sender, receiver, electricityNetwork, ForgeDirection.getOrientation(i).getOpposite(), ampsReceived, voltsReceived)); + } + } + } + } + } + } + } + } + + /** + * Checks if the current connection line needs electricity + * @return - The amount of watts this connection line needs + */ + public double getElectricityRequired(int ID) + { + ElectricityNetwork connection = this.getConnectionByID(ID); + double need = 0; + + if (connection != null) + { + for (IConductor conductor : connection.conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + IElectricityReceiver electricUnit = (IElectricityReceiver)tileEntity; + + if (electricUnit.canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + need += Math.ceil(electricUnit.wattRequest()); + } + } + } + } + } + } + + return need; + } + + /** + * This function is called to refresh all conductors in UE + */ + public void refreshConductors() + { + for(int j = 0; j < this.electricConductors.size(); j ++) + { + IConductor conductor = this.electricConductors.get(j); + conductor.refreshConnectedBlocks(); + } + } + + /** + * Clean up and remove useless connections + */ + public void cleanUpElectricityReceivers() + { + try + { + for (int i = 0; i < this.electricityReceivers.size(); i++) + { + IElectricityReceiver electricUnit = electricityReceivers.get(i); + + //Cleanup useless units + if (electricUnit == null) + { + electricityReceivers.remove(electricUnit); + } + else if (((TileEntity)electricUnit).isInvalid()) + { + electricityReceivers.remove(electricUnit); + } + } + } + catch(Exception e) + { + System.err.println("Failed to clean up electricity receivers."); + e.printStackTrace(); + } + } + + public void tickStart(EnumSet type, Object... tickData) + { + try + { + HashMap conductorAmpData = new HashMap(); + + for (int i = 0; i < electricityTransferQueue.size(); i ++) + { + if(electricityTransferQueue.get(i) != null) + { + if(electricityTransferQueue.get(i).isValid()) + { + double amps = electricityTransferQueue.get(i).amps; + + if(conductorAmpData.containsKey(electricityTransferQueue.get(i).network)) + { + amps += (Double)conductorAmpData.get(electricityTransferQueue.get(i).network); + } + + conductorAmpData.put(electricityTransferQueue.get(i).network, amps); + electricityTransferQueue.get(i).receiver.onReceive(electricityTransferQueue.get(i).sender, electricityTransferQueue.get(i).amps, electricityTransferQueue.get(i).voltage, electricityTransferQueue.get(i).side); + } + } + + electricityTransferQueue.remove(i); + } + + Iterator it = conductorAmpData.entrySet().iterator(); + + while (it.hasNext()) + { + Map.Entry pairs = (Map.Entry)it.next(); + + if(pairs.getKey() != null && pairs.getValue() != null) + { + if(pairs.getKey() instanceof ElectricityNetwork && pairs.getValue() instanceof Double) + { + if(((Double)pairs.getValue()) > ((ElectricityNetwork)pairs.getKey()).getLowestAmpConductor()) + { + ((ElectricityNetwork)pairs.getKey()).meltDown(); + } + } + } + + it.remove(); + } + } + catch(Exception e) + { + System.err.println("Failed to transfer electricity to receivers."); + e.printStackTrace(); + } + } + + public void tickEnd(EnumSet type, Object... tickData) + { + if(Ticker.inGameTicks == 0) + { + this.refreshConductors(); + } + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/electricity/ElectricityNetwork.java b/src/common/universalelectricity/electricity/ElectricityNetwork.java new file mode 100644 index 000000000..440510aa4 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityNetwork.java @@ -0,0 +1,118 @@ +package universalelectricity.electricity; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IConductor; +import universalelectricity.implement.IElectricityReceiver; + +public class ElectricityNetwork +{ + private int ID; + public List conductors = new ArrayList(); + + public ElectricityNetwork(int ID, IConductor conductor) + { + this.ID = ID; + this.addConductor(conductor); + } + + public void addConductor(IConductor newConductor) + { + this.cleanUpArray(); + + if (!conductors.contains(newConductor)) + { + conductors.add(newConductor); + newConductor.setConnectionID(this.ID); + } + } + + /** + * Get only the electric units that can receive electricity from the given side. + */ + public List getConnectedReceivers() + { + this.cleanUpArray(); + List returnArray = new ArrayList(); + + for (IConductor conductor : conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + if (!returnArray.contains((IElectricityReceiver)tileEntity) && ((IElectricityReceiver)tileEntity).canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + returnArray.add((IElectricityReceiver)tileEntity); + } + } + } + } + } + + return returnArray; + } + + public void cleanUpArray() + { + for (int i = 0; i < conductors.size(); i++) + { + if (conductors.get(i) == null) + { + conductors.remove(i); + } + else if (((TileEntity)conductors.get(i)).isInvalid()) + { + conductors.remove(i); + } + } + } + + public void setID(int ID) + { + this.ID = ID; + this.cleanUpArray(); + + for (IConductor conductor : this.conductors) + { + conductor.setConnectionID(this.ID); + } + } + + public int getID() + { + return this.ID; + } + + public void meltDown() + { + this.cleanUpArray(); + + for (int i = 0; i < conductors.size(); i++) + { + conductors.get(i).onConductorMelt(); + } + } + + public double getLowestAmpConductor() + { + double lowestAmp = 0; + + for(IConductor conductor : conductors) + { + if(lowestAmp == 0 || conductor.getMaxAmps() < lowestAmp) + { + lowestAmp = conductor.getMaxAmps(); + } + } + + return lowestAmp; + } +} diff --git a/src/common/universalelectricity/electricity/ElectricityTransferData.java b/src/common/universalelectricity/electricity/ElectricityTransferData.java new file mode 100644 index 000000000..c512ee3ef --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityTransferData.java @@ -0,0 +1,42 @@ +package universalelectricity.electricity; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IElectricityReceiver; + +public class ElectricityTransferData +{ + public TileEntity sender; + public IElectricityReceiver receiver; + public ElectricityNetwork network; + public double amps; + public double voltage; + public ForgeDirection side; + + /** + * @param sender - Tile that's sending electricity. + * @param receiver - Receiver that's receiving electricity + * @param conductor - Conductor that is conducting the electricity + * @param side - + * @param amps + * @param voltage + */ + public ElectricityTransferData(TileEntity sender, IElectricityReceiver receiver, ElectricityNetwork network, ForgeDirection side, double amps, double voltage) + { + this.sender = sender; + this.receiver = receiver; + this.network = network; + this.side = side; + this.amps = amps; + this.voltage = voltage; + } + + public boolean isValid() + { + return this.sender != null && + this.receiver != null && + this.network != null && + this.amps > 0 && + this.voltage > 0; + } +} diff --git a/src/common/universalelectricity/implement/IConductor.java b/src/common/universalelectricity/implement/IConductor.java new file mode 100644 index 000000000..e5119077a --- /dev/null +++ b/src/common/universalelectricity/implement/IConductor.java @@ -0,0 +1,56 @@ +package universalelectricity.implement; + +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; + +/** + * Must be applied to all tile entities that are conductors. + * @author Calclavia + * + */ +public interface IConductor extends IConnector +{ + /** + * The ID of the connection this conductor is in. + */ + public int getConnectionID(); + + public void setConnectionID(int ID); + + /** + * The UE tile entities that this conductor is connected to. + * @return + */ + public TileEntity[] getConnectedBlocks(); + + /** + * Gets the resistance of the conductor. Used to calculate energy loss. + * A higher resistance means a higher energy loss. + * @return The amount of Ohm's of resistance. + */ + public double getResistance(); + + /** + * The maximum amount of amps this conductor can handle before melting down. This is calculating + * PER TICK! + * @return The amount of amps in volts + */ + public double getMaxAmps(); + + /** + * Called when the electricity passing through exceeds the maximum voltage. + */ + public void onConductorMelt(); + + /** + * Resets the conductor and recalculate connection IDs again + */ + public void reset(); + + public World getWorld(); + + public void updateConnectionWithoutSplit(TileEntity connectorFromSide, ForgeDirection orientation); + + public void refreshConnectedBlocks(); +} diff --git a/src/common/universalelectricity/implement/IConnector.java b/src/common/universalelectricity/implement/IConnector.java new file mode 100644 index 000000000..fc8fac629 --- /dev/null +++ b/src/common/universalelectricity/implement/IConnector.java @@ -0,0 +1,18 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * Applied to tile entities that can connect to UE wires. + * @author Calclavia + * + */ +public interface IConnector +{ + /** + * Can this tile entity visually connect to a wire on this specific side? + * @param side. 0-5 byte + * @return - True if so. + */ + public boolean canConnect(ForgeDirection side); +} diff --git a/src/common/universalelectricity/implement/IDisableable.java b/src/common/universalelectricity/implement/IDisableable.java new file mode 100644 index 000000000..16bc71610 --- /dev/null +++ b/src/common/universalelectricity/implement/IDisableable.java @@ -0,0 +1,21 @@ +package universalelectricity.implement; + +/** + * This class should be applied to all tile entities (mainly machines) that can be disabled (by things like EMP, short circuit etc.). + * @author Calclavia + * + */ +public interface IDisableable +{ + /** + * This is called when the tile entity is to be disabled. + * @param duration - The duration of the disable in ticks. + */ + public void onDisable(int duration); + + /** + * Called to see if this tile entity is disabled. + * @return True if the tile entity is disabled. + */ + public boolean isDisabled(); +} diff --git a/src/common/universalelectricity/implement/IElectricityProducer.java b/src/common/universalelectricity/implement/IElectricityProducer.java new file mode 100644 index 000000000..71c16bedd --- /dev/null +++ b/src/common/universalelectricity/implement/IElectricityProducer.java @@ -0,0 +1,17 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * Applied to tile entities that can produce electricity + * @author Calclavia + */ +public interface IElectricityProducer extends IConnector, IDisableable, IVoltage +{ + /** + * Can this machine visually connect to a wire on this specific side? + * @param side. 0-5 byte + * @return - True if so. + */ + public boolean canConnect(ForgeDirection side); +} diff --git a/src/common/universalelectricity/implement/IElectricityReceiver.java b/src/common/universalelectricity/implement/IElectricityReceiver.java new file mode 100644 index 000000000..623f5bd62 --- /dev/null +++ b/src/common/universalelectricity/implement/IElectricityReceiver.java @@ -0,0 +1,39 @@ +package universalelectricity.implement; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; + + +/** + * The IMachine interface is an interface that must be applied to all tile entities that can input or output electricity. + * @author Calclavia + * + */ +public interface IElectricityReceiver extends IDisableable, IConnector, IVoltage +{ + /** + * Called every tick on this machine. + * + * @param amps - Amount of amps this electric unit is receiving. + * @param voltage - The voltage of the electricity sent. If more than one + * packet is being sent to you in this update, the highest voltage will + * override. + * @param side - The side of the block in which the electricity is coming from. + */ + public void onReceive(TileEntity sender, double amps, double voltage, ForgeDirection side); + + /** + * How many watts does this electrical unit need per tick? + * Recommend for you to return the max electricity storage of this machine (if there is one). + * + * Set this to 0 if your electric unit can not receive electricity. + */ + public double wattRequest(); + + /** + * Can this unit receive electricity from this specific side + * @param side. 0-5 byte + * @return - True if so. + */ + public boolean canReceiveFromSide(ForgeDirection side); +} \ No newline at end of file diff --git a/src/common/universalelectricity/implement/IElectricityStorage.java b/src/common/universalelectricity/implement/IElectricityStorage.java new file mode 100644 index 000000000..6fd4b6c87 --- /dev/null +++ b/src/common/universalelectricity/implement/IElectricityStorage.java @@ -0,0 +1,24 @@ +package universalelectricity.implement; + +/** + * This interface is to be applied to all tile entities which stores electricity + * within them. + * @author Calclavia + */ +public interface IElectricityStorage +{ + /** + * Returns the amount of watt hours this unit has stored. + */ + public double getWattHours(Object... data); + + /** + * Sets the amount of watt hours this unit has stored. + */ + public void setWattHours(double wattHours, Object... data); + + /** + * Gets the maximum amount of watt hours this unit can store. + */ + public double getMaxWattHours(); +} diff --git a/src/common/universalelectricity/implement/IItemElectric.java b/src/common/universalelectricity/implement/IItemElectric.java new file mode 100644 index 000000000..04bc801a6 --- /dev/null +++ b/src/common/universalelectricity/implement/IItemElectric.java @@ -0,0 +1,16 @@ +package universalelectricity.implement; + +import net.minecraft.src.ItemStack; + +public interface IItemElectric extends IElectricityStorage, IVoltage +{ + public double onReceiveElectricity(double wattHourReceive, ItemStack itemStack); + + public double onUseElectricity(double wattHourRequest, ItemStack itemStack); + + public boolean canReceiveElectricity(); + + public boolean canProduceElectricity(); + + public double getTransferRate(); +} diff --git a/src/common/universalelectricity/implement/IRedstoneProvider.java b/src/common/universalelectricity/implement/IRedstoneProvider.java new file mode 100644 index 000000000..9a272d2a2 --- /dev/null +++ b/src/common/universalelectricity/implement/IRedstoneProvider.java @@ -0,0 +1,13 @@ +package universalelectricity.implement; + +/** + * This should be applied on tile entities that can provide redstone power + * @author Henry + * + */ +public interface IRedstoneProvider +{ + public boolean isPoweringTo(byte side); + + public boolean isIndirectlyPoweringTo(byte side); +} diff --git a/src/common/universalelectricity/implement/IRedstoneReceptor.java b/src/common/universalelectricity/implement/IRedstoneReceptor.java new file mode 100644 index 000000000..425546ad2 --- /dev/null +++ b/src/common/universalelectricity/implement/IRedstoneReceptor.java @@ -0,0 +1,21 @@ +package universalelectricity.implement; + +/** + * OPTIONAL + * This interface should be applied onto all tile entities that needs to receive redstone power. + * Look at TileEntityBatteryBox for reference. + * @author Calclavia + * + */ +public interface IRedstoneReceptor +{ + /** + * Called when the block is powered on by redstone + */ + public void onPowerOn(); + + /** + * Called when the block is powered off by redstone + */ + public void onPowerOff(); +} diff --git a/src/common/universalelectricity/implement/IRotatable.java b/src/common/universalelectricity/implement/IRotatable.java new file mode 100644 index 000000000..ab42dd413 --- /dev/null +++ b/src/common/universalelectricity/implement/IRotatable.java @@ -0,0 +1,28 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * OPTIONAL + * This interface should be applied onto all tile entities that are rotatable. This interface however is optional + * and you do not need it for your add-on to function. It just makes things easier for you to code. + * @author Calclavia + * + */ + +public interface IRotatable +{ + /** + * Gets the facing direction of the tile entity. Always returns the front side of the tile entity. + * @return The facing side from 0-5 The full list of which side the number represents + * is in the UniversalElectricity class. + */ + public ForgeDirection getDirection(); + + /** + * Sets the facing direction of the tile entity. + * @param facingDirection - A direction from 0-5. The full list of which side the number represents + * is in the UniversalElectricity class. + */ + public void setDirection(ForgeDirection facingDirection); +} diff --git a/src/common/universalelectricity/implement/ITier.java b/src/common/universalelectricity/implement/ITier.java new file mode 100644 index 000000000..ab5487eaa --- /dev/null +++ b/src/common/universalelectricity/implement/ITier.java @@ -0,0 +1,21 @@ +package universalelectricity.implement; + +/** + * This interface should be applied to all things that has a tier/level + * @author Calclavia + * + */ +public interface ITier +{ + /** + * Gets the tier of this object + * @return - The tier + */ + public int getTier(); + + /** + * Sets the tier of the object + * @param tier - The tier to be set + */ + public void setTier(int tier); +} diff --git a/src/common/universalelectricity/implement/IVoltage.java b/src/common/universalelectricity/implement/IVoltage.java new file mode 100644 index 000000000..3902d544f --- /dev/null +++ b/src/common/universalelectricity/implement/IVoltage.java @@ -0,0 +1,11 @@ +package universalelectricity.implement; + +public interface IVoltage +{ + /** + * Gets the voltage of the electricity consumer. Used in a conductor to find the potential difference. + * If the voltage is too high, things might explode. + * @return The amount of volts. E.g 120v or 240v + */ + public double getVoltage(); +} diff --git a/src/common/universalelectricity/implement/UEDamageSource.java b/src/common/universalelectricity/implement/UEDamageSource.java new file mode 100644 index 000000000..f3c583b05 --- /dev/null +++ b/src/common/universalelectricity/implement/UEDamageSource.java @@ -0,0 +1,65 @@ +package universalelectricity.implement; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.DamageSource; +import cpw.mods.fml.common.registry.LanguageRegistry; + +public class UEDamageSource extends DamageSource +{ + public static final List damageSources = new ArrayList(); + + /** + * Use this damage source for all types of electrical attacks. + */ + public static final UEDamageSource electrocution = (UEDamageSource)new UEDamageSource("electrocution", "%1$s got electrocuted!").setDamageBypassesArmor(); + + public String deathMessage; + + public UEDamageSource(String damageType) + { + super(damageType); + damageSources.add(this); + } + + public UEDamageSource(String damageType, String deathMessage) + { + this(damageType); + this.setDeathMessage(deathMessage); + } + + public UEDamageSource setDeathMessage(String deathMessage) + { + this.deathMessage = deathMessage; + return this; + } + + public static void registerDeathMesages() + { + for(UEDamageSource damageSource : damageSources) + { + damageSource.registerDeathMessage(); + } + } + + public DamageSource setDamageBypassesArmor() + { + return super.setDamageBypassesArmor(); + } + + public DamageSource setDamageAllowedInCreativeMode() + { + return super.setDamageAllowedInCreativeMode(); + } + + public DamageSource setFireDamage() + { + return super.setFireDamage(); + } + + public void registerDeathMessage() + { + LanguageRegistry.instance().addStringLocalization("death."+this.damageType, this.deathMessage); + } +} diff --git a/src/common/universalelectricity/network/ConnectionHandler.java b/src/common/universalelectricity/network/ConnectionHandler.java new file mode 100644 index 000000000..b53da5463 --- /dev/null +++ b/src/common/universalelectricity/network/ConnectionHandler.java @@ -0,0 +1,88 @@ +package universalelectricity.network; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.src.NetHandler; +import net.minecraft.src.NetLoginHandler; +import net.minecraft.src.NetworkManager; +import net.minecraft.src.Packet1Login; +import universalelectricity.electricity.ElectricityManager; +import cpw.mods.fml.common.network.IConnectionHandler; +import cpw.mods.fml.common.network.Player; + +public class ConnectionHandler implements IConnectionHandler +{ + private static final List simpleConnectionHandlers = new ArrayList(); + + public static enum ConnectionType + { + LOGIN_SERVER, LOGIN_CLIENT, RECEIVED, OPEN_REMOTE, OPEN_LOCAL, CLOSED + } + + /** + * Registers a simple connection handler + * @param tileEntity + */ + public static void registerConnectionHandler(ISimpleConnectionHandler tileEntity) + { + simpleConnectionHandlers.add(tileEntity); + } + + @Override + public void playerLoggedIn(Player player, NetHandler netHandler, NetworkManager manager) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.LOGIN_SERVER, player, netHandler, manager); + } + } + + @Override + public void clientLoggedIn(NetHandler clientHandler, NetworkManager manager, Packet1Login login) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.LOGIN_CLIENT, clientHandler, manager, login); + } + } + + @Override + public String connectionReceived(NetLoginHandler netHandler, NetworkManager manager) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.RECEIVED, netHandler, manager); + } + + return null; + } + + @Override + public void connectionOpened(NetHandler netClientHandler, String server, int port, NetworkManager manager) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.OPEN_REMOTE, netClientHandler, server, port, manager); + } + } + + @Override + public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, NetworkManager manager) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.OPEN_LOCAL, netClientHandler, server, manager); + } + } + + @Override + public void connectionClosed(NetworkManager manager) + { + for(ISimpleConnectionHandler handler : simpleConnectionHandlers) + { + handler.handelConnection(ConnectionType.CLOSED, manager); + } + } +} diff --git a/src/common/universalelectricity/network/IPacketReceiver.java b/src/common/universalelectricity/network/IPacketReceiver.java new file mode 100644 index 000000000..6a8564a3c --- /dev/null +++ b/src/common/universalelectricity/network/IPacketReceiver.java @@ -0,0 +1,15 @@ +package universalelectricity.network; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.NetworkManager; +import net.minecraft.src.Packet250CustomPayload; + +import com.google.common.io.ByteArrayDataInput; + +public interface IPacketReceiver +{ + /** + * Sends some data to the tile entity. + */ + public void handlePacketData(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream); +} diff --git a/src/common/universalelectricity/network/ISimpleConnectionHandler.java b/src/common/universalelectricity/network/ISimpleConnectionHandler.java new file mode 100644 index 000000000..28586ed6c --- /dev/null +++ b/src/common/universalelectricity/network/ISimpleConnectionHandler.java @@ -0,0 +1,12 @@ +package universalelectricity.network; + +import universalelectricity.network.ConnectionHandler.ConnectionType; + +public interface ISimpleConnectionHandler +{ + /** + * Called when a player logs in. Use this to reset some tile entities variables if you need to. + * @param player + */ + public void handelConnection(ConnectionType type, Object... data); +} diff --git a/src/common/universalelectricity/network/PacketManager.java b/src/common/universalelectricity/network/PacketManager.java new file mode 100644 index 000000000..e7cee2651 --- /dev/null +++ b/src/common/universalelectricity/network/PacketManager.java @@ -0,0 +1,264 @@ +package universalelectricity.network; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.NetworkManager; +import net.minecraft.src.Packet; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.prefab.Vector3; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.IPacketHandler; +import cpw.mods.fml.common.network.PacketDispatcher; +import cpw.mods.fml.common.network.Player; + +/** + * This class is used for sending and receiving packets between the server + * and the client. You can directly use this by registering this packet manager + * with NetworkMod. Example: + * @NetworkMod(channels = { "BasicComponents" }, clientSideRequired = true, serverSideRequired = false, packetHandler = PacketManager.class) + * + * Check out {@link #BasicComponents} for better reference. + * + * @author Calclavia + */ +public class PacketManager implements IPacketHandler, IPacketReceiver +{ + public enum PacketType + { + UNSPECIFIED, TILEENTITY; + + public static PacketType get(int id) + { + if (id >= 0 && id < PacketType.values().length) + { + return PacketType.values()[id]; + } + return UNSPECIFIED; + } + } + + public static Packet getPacketWithID(String channelName, int id, Object... sendData) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream(bytes); + + try + { + data.writeInt(id); + + data = encodeDataStream(data, sendData); + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = channelName; + packet.data = bytes.toByteArray(); + packet.length = packet.data.length; + + return packet; + } + catch (IOException e) + { + System.out.println("Failed to create packet."); + e.printStackTrace(); + } + + return null; + } + + public static Packet getPacket(String channelName, Object... sendData) + { + return getPacketWithID(channelName, PacketType.UNSPECIFIED.ordinal(), sendData); + } + + /** + * Gets a packet for the tile entity. + * @return + */ + public static Packet getPacket(String channelName, TileEntity sender, Object... sendData) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream(bytes); + + try + { + data.writeInt(PacketType.TILEENTITY.ordinal()); + + data.writeInt(sender.xCoord); + data.writeInt(sender.yCoord); + data.writeInt(sender.zCoord); + data = encodeDataStream(data, sendData); + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = channelName; + packet.data = bytes.toByteArray(); + packet.length = packet.data.length; + + return packet; + } + catch (IOException e) + { + System.out.println("Failed to create packet."); + e.printStackTrace(); + } + + return null; + } + + /** + * Sends packets to clients around a specific coordinate. A wrapper using Vector3. + * See {@PacketDispatcher} for detailed information. + */ + public static void sendPacketToClients(Packet packet, World worldObj, Vector3 position, double range) + { + try + { + PacketDispatcher.sendPacketToAllAround(position.x, position.y, position.z, range, worldObj.provider.dimensionId, packet); + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + /** + * Sends a packet to all the clients on this server. + */ + public static void sendPacketToClients(Packet packet, World worldObj) + { + try + { + PacketDispatcher.sendPacketToAllInDimension(packet, worldObj.provider.dimensionId); + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + public static void sendPacketToClients(Packet packet) + { + try + { + if(FMLCommonHandler.instance().getMinecraftServerInstance() != null) + { + FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet); + } + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + public static DataOutputStream encodeDataStream(DataOutputStream data, Object... sendData) + { + try + { + for(Object dataValue : sendData) + { + if(dataValue instanceof Integer) + { + data.writeInt((Integer)dataValue); + } + else if(dataValue instanceof Float) + { + data.writeFloat((Float)dataValue); + } + else if(dataValue instanceof Double) + { + data.writeDouble((Double)dataValue); + } + else if(dataValue instanceof Byte) + { + data.writeByte((Byte)dataValue); + } + else if(dataValue instanceof Boolean) + { + data.writeBoolean((Boolean)dataValue); + } + else if(dataValue instanceof String) + { + data.writeUTF((String)dataValue); + } + else if(dataValue instanceof Short) + { + data.writeShort((Short)dataValue); + } + else if(dataValue instanceof Long) + { + data.writeLong((Long)dataValue); + } + } + + return data; + + } + catch (IOException e) + { + System.out.println("Packet data encoding failed."); + e.printStackTrace(); + } + + return data; + } + + @Override + public void onPacketData(NetworkManager network, Packet250CustomPayload packet, Player player) + { + try + { + ByteArrayDataInput data = ByteStreams.newDataInput(packet.data); + + int packetTypeID = data.readInt(); + + PacketType packetType = PacketType.get(packetTypeID); + + if(packetType == PacketType.TILEENTITY) + { + int x = data.readInt(); + int y = data.readInt(); + int z = data.readInt(); + + World world = ((EntityPlayer)player).worldObj; + + if(world != null) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if(tileEntity != null) + { + if(tileEntity instanceof IPacketReceiver) + { + ((IPacketReceiver)tileEntity).handlePacketData(network, packetTypeID, packet, ((EntityPlayer)player), data); + } + } + } + } + else + { + this.handlePacketData(network, packetTypeID, packet, ((EntityPlayer)player), data); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + @Override + public void handlePacketData(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + + } +} diff --git a/src/common/universalelectricity/network/UECommand.java b/src/common/universalelectricity/network/UECommand.java new file mode 100644 index 000000000..4e63aeabc --- /dev/null +++ b/src/common/universalelectricity/network/UECommand.java @@ -0,0 +1,49 @@ +package universalelectricity.network; + +import java.util.Arrays; +import java.util.List; + +import net.minecraft.src.CommandBase; +import net.minecraft.src.ICommand; +import net.minecraft.src.ICommandSender; +import net.minecraft.src.WrongUsageException; +import universalelectricity.UniversalElectricity; + +public class UECommand extends CommandBase +{ + @Override + public int compareTo(Object arg0) + { + return this.getCommandName().compareTo(((ICommand)arg0).getCommandName()); + } + + @Override + public String getCommandName() + { + return "universalelectricity"; + } + + @Override + public String getCommandUsage(ICommandSender sender) + { + return "/" + this.getCommandName(); + } + + @Override + public List getCommandAliases() + { + return Arrays.asList(new String[]{"ue"}); + } + + @Override + public void processCommand(ICommandSender sender, String[] arguments) + { + if(arguments.length <= 0) + { + sender.sendChatToPlayer(String.format("You are using Universal Electricity v" + UniversalElectricity.VERSION)); + return; + } + + throw new WrongUsageException(this.getCommandUsage(sender)); + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/ore/OreGenBase.java b/src/common/universalelectricity/ore/OreGenBase.java new file mode 100644 index 000000000..1391a7105 --- /dev/null +++ b/src/common/universalelectricity/ore/OreGenBase.java @@ -0,0 +1,94 @@ +package universalelectricity.ore; + +import java.util.Random; + +import net.minecraft.src.Block; +import net.minecraft.src.IChunkProvider; +import net.minecraft.src.ItemStack; +import net.minecraft.src.World; +import net.minecraftforge.common.Configuration; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.oredict.OreDictionary; +import universalelectricity.UniversalElectricity; + +/** + * This class is used for storing ore generation data. If you are too + * lazy to generate your own ores, you can do {@link #OreGenerator.ORES_TO_GENERATE.add()} + * to add your ore to the list of ores to generate. + * @author Calclavia + * + */ +public abstract class OreGenBase +{ + public String name; + + public String oreDictionaryName; + + public boolean shouldGenerate; + + public int blockIndexTexture; + + public ItemStack oreStack; + + public int oreID; + + public int oreMeta; + + /** + * What harvest level does this machine need to be acquired? + */ + public int harvestLevel; + + /** + * The predefined tool classes are "pickaxe", "shovel", "axe". You can add others for custom tools. + */ + public String harvestTool; + + /** + * @param name - The name of the ore for display + * @param textureFile - The 16x16 png texture of your ore to override + * @param minGenerateLevel - The highest generation level of your ore + * @param maxGenerateLevel - The lowest generation level of your ore + * @param amountPerChunk - The amount of ores to generate per chunk + * @param amountPerBranch - The amount of ores to generate in a clutter. E.g coal generates with a lot of other coal next to it. How much do you want? + */ + public OreGenBase(String name, String oreDiectionaryName, ItemStack stack, String harvestTool, int harvestLevel) + { + this.name = name; + this.shouldGenerate = false; + this.harvestTool = harvestTool; + this.harvestLevel = harvestLevel; + this.oreDictionaryName = oreDiectionaryName; + this.oreStack = stack; + this.oreID = stack.itemID; + this.oreMeta = stack.getItemDamage(); + + OreDictionary.registerOre(oreDictionaryName, stack); + MinecraftForge.setBlockHarvestLevel(Block.blocksList[stack.itemID], stack.getItemDamage(), harvestTool, harvestLevel); + } + + public OreGenBase enable() + { + this.shouldGenerate = shouldGenerateOre(name); + return this; + } + + //You may inherit from this class and change this function if you want a custom texture render for your ore. + public int getBlockTextureFromSide(int side) + { + return this.blockIndexTexture; + } + + //Checks the config file and see if Universal Electricity should generate this ore + private static boolean shouldGenerateOre(String oreName) + { + UniversalElectricity.CONFIGURATION.load(); + boolean shouldGenerate = Boolean.parseBoolean(UniversalElectricity.CONFIGURATION.getOrCreateBooleanProperty("Generate_" + oreName.replace(" ", "_"), Configuration.CATEGORY_GENERAL, true).value); + UniversalElectricity.CONFIGURATION.save(); + return shouldGenerate; + } + + public abstract void generate(World world, Random random, int varX, int varZ); + + public abstract boolean isOreGeneratedInWorld(World world, IChunkProvider chunkGenerator); +} diff --git a/src/common/universalelectricity/ore/OreGenReplace.java b/src/common/universalelectricity/ore/OreGenReplace.java new file mode 100644 index 000000000..cddc12b07 --- /dev/null +++ b/src/common/universalelectricity/ore/OreGenReplace.java @@ -0,0 +1,128 @@ +package universalelectricity.ore; + +import java.util.Random; + +import net.minecraft.src.ChunkProviderEnd; +import net.minecraft.src.ChunkProviderGenerate; +import net.minecraft.src.ChunkProviderHell; +import net.minecraft.src.IChunkProvider; +import net.minecraft.src.ItemStack; +import net.minecraft.src.MathHelper; +import net.minecraft.src.World; + +/** + * This class is used for storing ore generation data. If you are too + * lazy to generate your own ores, you can do {@link #OreGenerator.ORES_TO_GENERATE.add()} + * to add your ore to the list of ores to generate. + * @author Calclavia + * + */ +public class OreGenReplace extends OreGenBase +{ + + public int minGenerateLevel; + public int maxGenerateLevel; + public int amountPerChunk; + public int amountPerBranch; + public int replaceID; + + public boolean generateSurface; + public boolean generateNether; + public boolean generateEnd; + + /** + * @param name - The name of the ore for display + * @param textureFile - The 16x16 png texture of your ore to override + * @param minGenerateLevel - The highest generation level of your ore + * @param maxGenerateLevel - The lowest generation level of your ore + * @param amountPerChunk - The amount of ores to generate per chunk + * @param amountPerBranch - The amount of ores to generate in a clutter. E.g coal generates with a lot of other coal next to it. How much do you want? + */ + public OreGenReplace(String name, String oreDiectionaryName, ItemStack stack, int replaceID, int minGenerateLevel, int maxGenerateLevel, int amountPerChunk, int amountPerBranch, String harvestTool, int harvestLevel) + { + super(name, oreDiectionaryName, stack, harvestTool, harvestLevel); + this.minGenerateLevel = minGenerateLevel; + this.maxGenerateLevel = maxGenerateLevel; + this.amountPerChunk = amountPerChunk; + this.amountPerBranch = amountPerBranch; + this.replaceID = replaceID; + } + + public void generate(World world, Random random, int varX, int varZ) + { + + for (int i = 0; i < this.amountPerChunk; i++) + { + int x = varX + random.nextInt(16); + int z = varZ + random.nextInt(16); + int y = random.nextInt(this.maxGenerateLevel-this.minGenerateLevel) + this.minGenerateLevel; + generateReplace(world, random, x, y, z); + } + } + + + public boolean generateReplace(World par1World, Random par2Random, int par3, int par4, int par5) + { + float var6 = par2Random.nextFloat() * (float)Math.PI; + double var7 = (double)((float)(par3 + 8) + MathHelper.sin(var6) * (float)this.amountPerBranch / 8.0F); + double var9 = (double)((float)(par3 + 8) - MathHelper.sin(var6) * (float)this.amountPerBranch / 8.0F); + double var11 = (double)((float)(par5 + 8) + MathHelper.cos(var6) * (float)this.amountPerBranch / 8.0F); + double var13 = (double)((float)(par5 + 8) - MathHelper.cos(var6) * (float)this.amountPerBranch / 8.0F); + double var15 = (double)(par4 + par2Random.nextInt(3) - 2); + double var17 = (double)(par4 + par2Random.nextInt(3) - 2); + + for (int var19 = 0; var19 <= this.amountPerBranch; ++var19) + { + double var20 = var7 + (var9 - var7) * (double)var19 / (double)this.amountPerBranch; + double var22 = var15 + (var17 - var15) * (double)var19 / (double)this.amountPerBranch; + double var24 = var11 + (var13 - var11) * (double)var19 / (double)this.amountPerBranch; + double var26 = par2Random.nextDouble() * (double)this.amountPerBranch / 16.0D; + double var28 = (double)(MathHelper.sin((float)var19 * (float)Math.PI / (float)this.amountPerBranch) + 1.0F) * var26 + 1.0D; + double var30 = (double)(MathHelper.sin((float)var19 * (float)Math.PI / (float)this.amountPerBranch) + 1.0F) * var26 + 1.0D; + int var32 = MathHelper.floor_double(var20 - var28 / 2.0D); + int var33 = MathHelper.floor_double(var22 - var30 / 2.0D); + int var34 = MathHelper.floor_double(var24 - var28 / 2.0D); + int var35 = MathHelper.floor_double(var20 + var28 / 2.0D); + int var36 = MathHelper.floor_double(var22 + var30 / 2.0D); + int var37 = MathHelper.floor_double(var24 + var28 / 2.0D); + + for (int var38 = var32; var38 <= var35; ++var38) + { + double var39 = ((double)var38 + 0.5D - var20) / (var28 / 2.0D); + + if (var39 * var39 < 1.0D) + { + for (int var41 = var33; var41 <= var36; ++var41) + { + double var42 = ((double)var41 + 0.5D - var22) / (var30 / 2.0D); + + if (var39 * var39 + var42 * var42 < 1.0D) + { + for (int var44 = var34; var44 <= var37; ++var44) + { + double var45 = ((double)var44 + 0.5D - var24) / (var28 / 2.0D); + + int block = par1World.getBlockId(var38, var41, var44); + if (var39 * var39 + var42 * var42 + var45 * var45 < 1.0D && (this.replaceID == 0 || block==this.replaceID)) + { + par1World.setBlockAndMetadata(var38, var41, var44, this.oreID, this.oreMeta); + } + } + } + } + } + } + } + + return true; + } + + @Override + public boolean isOreGeneratedInWorld(World world, IChunkProvider chunkGenerator) + { + return ((this.generateSurface && chunkGenerator instanceof ChunkProviderGenerate) || + (this.generateNether && chunkGenerator instanceof ChunkProviderHell) || + (this.generateEnd && chunkGenerator instanceof ChunkProviderEnd) + ); + } +} diff --git a/src/common/universalelectricity/ore/OreGenReplaceStone.java b/src/common/universalelectricity/ore/OreGenReplaceStone.java new file mode 100644 index 000000000..094574265 --- /dev/null +++ b/src/common/universalelectricity/ore/OreGenReplaceStone.java @@ -0,0 +1,18 @@ +package universalelectricity.ore; + +import net.minecraft.src.ItemStack; + +public class OreGenReplaceStone extends OreGenReplace +{ + public OreGenReplaceStone(String name, String oreDiectionaryName, ItemStack stack, int replaceID, int minGenerateLevel, int maxGenerateLevel, int amountPerChunk, int amountPerBranch, String harvestTool, int harvestLevel) + { + super(name, oreDiectionaryName, stack, 1, minGenerateLevel, maxGenerateLevel, amountPerChunk, amountPerBranch, harvestTool, harvestLevel); + this.generateSurface = true; + } + + //A simplified version of the constructor + public OreGenReplaceStone(String name, String oreDiectionaryName, ItemStack stack, int replaceID, int maxGenerateLevel, int amountPerChunk, int amountPerBranch) + { + this(name, oreDiectionaryName, stack, 0, replaceID, maxGenerateLevel, amountPerChunk, amountPerBranch, "pickaxe", 1); + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/ore/OreGenerator.java b/src/common/universalelectricity/ore/OreGenerator.java new file mode 100644 index 000000000..54a958fc7 --- /dev/null +++ b/src/common/universalelectricity/ore/OreGenerator.java @@ -0,0 +1,68 @@ +package universalelectricity.ore; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import net.minecraft.src.IChunkProvider; +import net.minecraft.src.World; +import cpw.mods.fml.common.IWorldGenerator; + +public class OreGenerator implements IWorldGenerator +{ + /** + * Add your ore data to this list of ores for it to automatically generate! No hassle indeed! + */ + private static final List ORES_TO_GENERATE = new ArrayList(); + + /** + * Adds an ore to the ore generate list. Do this in pre-init. + */ + public static void addOre(OreGenBase data) + { + ORES_TO_GENERATE.add(data); + } + + /** + * Checks to see if this ore + * @param oreName + * @return + */ + public static boolean oreExists(String oreName) + { + for(OreGenBase ore: ORES_TO_GENERATE) + { + if(ore.oreDictionaryName == oreName) + { + return true; + } + } + + return false; + } + + /** + * Removes an ore to the ore generate list. Do this in init. + */ + public static void removeOre(OreGenBase data) + { + ORES_TO_GENERATE.remove(data); + } + + @Override + public void generate(Random rand, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) + { + chunkX = chunkX << 4; + chunkZ = chunkZ << 4; + + //Checks to make sure this is the normal world + for(OreGenBase oreData : ORES_TO_GENERATE) + { + if(oreData.shouldGenerate && oreData.isOreGeneratedInWorld(world, chunkGenerator)) + { + oreData.generate(world, rand, chunkX, chunkZ); + } + + } + } +} diff --git a/src/common/universalelectricity/prefab/AdvancedTile.java b/src/common/universalelectricity/prefab/AdvancedTile.java new file mode 100644 index 000000000..93a8ab17b --- /dev/null +++ b/src/common/universalelectricity/prefab/AdvancedTile.java @@ -0,0 +1,57 @@ +package universalelectricity.prefab; + +import net.minecraft.src.Block; +import net.minecraft.src.TileEntity; + +/** + * A TileEntity with some pre-added functionalities. + * @author Calclavia + * + */ +public abstract class AdvancedTile extends TileEntity +{ + protected long ticks = 0; + + @Override + public void updateEntity() + { + if(this.ticks == 0) + { + this.initiate(); + } + + if(this.ticks >= Long.MAX_VALUE) + { + this.ticks = 0; + } + + this.ticks ++; + } + + /** + * Called on the TileEntity's first tick. + */ + protected void initiate() { } + + @Override + public int getBlockMetadata() + { + if (this.blockMetadata == -1) + { + this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); + } + + return this.blockMetadata; + } + + @Override + public Block getBlockType() + { + if (this.blockType == null) + { + this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)]; + } + + return this.blockType; + } +} diff --git a/src/common/universalelectricity/prefab/BlockConductor.java b/src/common/universalelectricity/prefab/BlockConductor.java new file mode 100644 index 000000000..b8951d182 --- /dev/null +++ b/src/common/universalelectricity/prefab/BlockConductor.java @@ -0,0 +1,50 @@ +package universalelectricity.prefab; + +import net.minecraft.src.BlockContainer; +import net.minecraft.src.Material; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; + +public abstract class BlockConductor extends BlockContainer +{ + public BlockConductor(int id, Material material) + { + super(id, material); + } + + /** + * Called whenever the block is added into the world. Args: world, x, y, z + */ + @Override + public void onBlockAdded(World world, int x, int y, int z) + { + super.onBlockAdded(world, x, y, z); + this.updateConductorTileEntity(world, x, y, z); + } + + /** + * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are + * their own) Args: x, y, z, neighbor blockID + */ + @Override + public void onNeighborBlockChange(World world, int x, int y, int z, int blockID) + { + this.updateConductorTileEntity(world, x, y, z); + world.markBlockNeedsUpdate(x, y, z); + } + + public static void updateConductorTileEntity(World world, int x, int y, int z) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if (tileEntity != null) + { + for (byte i = 0; i < 6; i++) + { + TileEntityConductor conductorTileEntity = (TileEntityConductor)tileEntity; + conductorTileEntity.updateConnection(Vector3.getConnectorFromSide(world, new Vector3(x, y, z), ForgeDirection.getOrientation(i)), ForgeDirection.getOrientation(i)); + } + } + } +} diff --git a/src/common/universalelectricity/prefab/BlockMachine.java b/src/common/universalelectricity/prefab/BlockMachine.java new file mode 100644 index 000000000..a6f09e996 --- /dev/null +++ b/src/common/universalelectricity/prefab/BlockMachine.java @@ -0,0 +1,221 @@ +package universalelectricity.prefab; + +import java.util.Random; + +import net.minecraft.src.BlockContainer; +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.Material; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.implement.IItemElectric; +import buildcraft.api.tools.IToolWrench; + +/** + * A block you may extend from to create your machine blocks! You do not have to extend from this block if + * you do not want to. It's optional but it comes with some useful functions that will make coding easier + * for you. + */ +public abstract class BlockMachine extends BlockContainer +{ + public BlockMachine(String name, int id, Material material) + { + super(id, material); + this.setBlockName(name); + this.setHardness(0.5F); + } + + public BlockMachine(String name, int id, Material material, CreativeTabs creativeTab) + { + this(name, id, material); + this.setCreativeTab(creativeTab); + } + + @Override + protected int damageDropped(int metadata) + { + return metadata; + } + + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } + + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + + /** + * DO NOT OVERRIDE THIS FUNCTION! + * Called when the block is right clicked by the player. This modified version detects + * electric items and wrench actions on your machine block. Do not override this function. + * Use machineActivated instead! (It does the same thing) + */ + @Override + public boolean onBlockActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) + { + int metadata = par1World.getBlockMetadata(x, y, z); + + /** + * Check if the player is holding a wrench or an electric item. If so, do not open the GUI. + */ + if (par5EntityPlayer.inventory.getCurrentItem() != null) + { + if (par5EntityPlayer.inventory.getCurrentItem().getItem() instanceof IToolWrench) + { + if(par5EntityPlayer.isSneaking()) + { + par1World.notifyBlocksOfNeighborChange(x, y, z, this.blockID); + return this.onSneakUseWrench(par1World, x, y, z, par5EntityPlayer); + } + else + { + par1World.notifyBlocksOfNeighborChange(x, y, z, this.blockID); + return this.onUseWrench(par1World, x, y, z, par5EntityPlayer); + } + } + else if (par5EntityPlayer.inventory.getCurrentItem().getItem() instanceof IItemElectric) + { + if(this.onUseElectricItem(par1World, x, y, z, par5EntityPlayer)) + { + return true; + } + } + } + + if(par5EntityPlayer.isSneaking()) + { + return this.onSneakMachineActivated(par1World, x, y, z, par5EntityPlayer); + } + else + { + return this.onMachineActivated(par1World, x, y, z, par5EntityPlayer); + } + } + + /** + * Called when the machine is right clicked by the player + * @return True if something happens + */ + public boolean onMachineActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when the machine is right clicked by the player while sneaking (shift clicking) + * @return True if something happens + */ + public boolean onSneakMachineActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses an electric item on the machine + * @return True if some happens + */ + public boolean onUseElectricItem(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses a wrench on the machine + * @return True if some happens + */ + public boolean onUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses a wrench on the machine while sneaking + * @return True if some happens + */ + public boolean onSneakUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return this.onUseWrench(par1World, x, y, z, par5EntityPlayer); + } + + /** + * Returns the TileEntity used by this block. + * You should use the metadata sensitive version of this to get the maximum optimization! + */ + @Override + public TileEntity createNewTileEntity(World var1) + { + return null; + } + + /** + * Override this if you don't need it. This will eject all items out + * of this machine if it has an inventory + */ + @Override + public void breakBlock(World par1World, int x, int y, int z, int par5, int par6) + { + TileEntity tileEntity = par1World.getBlockTileEntity(x, y, z); + + if(tileEntity != null) + { + if(tileEntity instanceof IInventory) + { + IInventory inventory = (IInventory)tileEntity; + + for (int var6 = 0; var6 < inventory.getSizeInventory(); ++var6) + { + ItemStack var7 = inventory.getStackInSlot(var6); + + if (var7 != null) + { + Random random = new Random(); + float var8 = random.nextFloat() * 0.8F + 0.1F; + float var9 = random.nextFloat() * 0.8F + 0.1F; + float var10 = random.nextFloat() * 0.8F + 0.1F; + + while (var7.stackSize > 0) + { + int var11 = random.nextInt(21) + 10; + + if (var11 > var7.stackSize) + { + var11 = var7.stackSize; + } + + var7.stackSize -= var11; + EntityItem var12 = new EntityItem(par1World, (x + var8), (y + var9), (z + var10), new ItemStack(var7.itemID, var11, var7.getItemDamage())); + + if (var7.hasTagCompound()) + { + var12.item.setTagCompound((NBTTagCompound)var7.getTagCompound().copy()); + } + + float var13 = 0.05F; + var12.motionX = ((float)random.nextGaussian() * var13); + var12.motionY = ((float)random.nextGaussian() * var13 + 0.2F); + var12.motionZ = ((float)random.nextGaussian() * var13); + par1World.spawnEntityInWorld(var12); + } + } + } + } + } + + super.breakBlock(par1World, x, y, z, par5, par6); + } +} diff --git a/src/common/universalelectricity/prefab/CommonProxy.java b/src/common/universalelectricity/prefab/CommonProxy.java new file mode 100644 index 000000000..f8202f001 --- /dev/null +++ b/src/common/universalelectricity/prefab/CommonProxy.java @@ -0,0 +1,25 @@ +package universalelectricity.prefab; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.World; +import cpw.mods.fml.common.network.IGuiHandler; + +/** + * A class used to easily manuver between client and server. + * + */ +public abstract class CommonProxy implements IGuiHandler +{ + public void preInit() { } + + public void init() { } + + public void postInit() { } + + @Override + public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } + + @Override + public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } + +} diff --git a/src/common/universalelectricity/prefab/ItemElectric.java b/src/common/universalelectricity/prefab/ItemElectric.java new file mode 100644 index 000000000..86aa84692 --- /dev/null +++ b/src/common/universalelectricity/prefab/ItemElectric.java @@ -0,0 +1,219 @@ +package universalelectricity.prefab; + +import java.util.List; + +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.NBTTagFloat; +import net.minecraft.src.World; +import universalelectricity.electricity.ElectricInfo; +import universalelectricity.electricity.ElectricInfo.ElectricUnit; +import universalelectricity.implement.IItemElectric; + +/** + * REQUIRED + * Extend from this class if your item requires electricity or to be charged. + * @author Calclavia + * + */ +public abstract class ItemElectric extends Item implements IItemElectric +{ + public ItemElectric(int id, CreativeTabs tabs) + { + super(id); + this.setMaxStackSize(1); + this.setMaxDamage((int)this.getMaxWattHours()); + this.setNoRepair(); + this.setCreativeTab(tabs); + } + + public ItemElectric(int id) + { + this(id, CreativeTabs.tabTools); + } + + /** + * Allows items to add custom lines of information to the mouseover description. If you want to add more + * information to your item, you can super.addInformation() to keep the electiricty info in the item info bar. + */ + @Override + public void addInformation(ItemStack par1ItemStack, List par2List) + { + String color = ""; + double watts = this.getWattHours(par1ItemStack); + + if (watts <= this.getMaxWattHours() / 3) + { + color = "\u00a74"; + } + else if (watts > this.getMaxWattHours() * 2 / 3) + { + color = "\u00a72"; + } + else + { + color = "\u00a76"; + } + + par2List.add(color + ElectricInfo.getDisplay(ElectricInfo.getWattHours(watts), ElectricUnit.WATT_HOUR) + " - " + Math.round((watts / this.getMaxWattHours()) * 100) + "%"); + } + + /** + * Make sure you super this method! + */ + @Override + public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5) + { + //Makes sure the damage is set correctly for this electric item! + ItemElectric item = ((ItemElectric)par1ItemStack.getItem()); + item.setWattHours(item.getWattHours(par1ItemStack), par1ItemStack); + } + + /** + * Makes sure the item is uncharged when it is crafted and not charged. + * Change this if you do not want this to happen! + */ + @Override + public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) + { + par1ItemStack = this.getUnchargedItemStack(); + } + + /** + * Called when this item is being "recharged" or receiving electricity. + * @param wattHourReceive - The amount of watt hours this item is receiving. + * @param itemStack - The ItemStack of this item + * @return Return the rejected electricity from this item + */ + public double onReceiveElectricity(double wattHourReceive, ItemStack itemStack) + { + double rejectedElectricity = Math.max((this.getWattHours(itemStack) + wattHourReceive) - this.getMaxWattHours(), 0); + this.setWattHours(this.getWattHours(itemStack) + wattHourReceive - rejectedElectricity, itemStack); + return rejectedElectricity; + } + + /** + * Called when this item's electricity is being used. + * @param wattHourRequest - The amount of electricity requested from this item + * @param itemStack - The ItemStack of this item + * @return The electricity that is given to the requester + */ + public double onUseElectricity(double wattHourRequest, ItemStack itemStack) + { + double electricityToUse = Math.min(this.getWattHours(itemStack), wattHourRequest); + this.setWattHours(this.getWattHours(itemStack) - electricityToUse, itemStack); + return electricityToUse; + } + + /** + * @return Returns true or false if this consumer can receive electricity at this given tick or moment. + */ + public boolean canReceiveElectricity() + { + return true; + } + + /** + * Can this item give out electricity when placed in an tile entity? Electric items like batteries + * should be able to produce electricity (if they are rechargable). + * @return - True or False. + */ + public boolean canProduceElectricity() + { + return false; + } + + /** + * This function sets the electriicty. Do not directly call this function. + * Try to use onReceiveElectricity or onUseElectricity instead. + * @param wattHours - The amount of electricity in joules + */ + @Override + public void setWattHours(double wattHours, Object... data) + { + if(data[0] instanceof ItemStack) + { + ItemStack itemStack = (ItemStack)data[0]; + + //Saves the frequency in the itemstack + if (itemStack.stackTagCompound == null) + { + itemStack.setTagCompound(new NBTTagCompound()); + } + + double electricityStored = Math.max(Math.min(wattHours, this.getMaxWattHours()), 0); + itemStack.stackTagCompound.setDouble("electricity", electricityStored); + itemStack.setItemDamage((int)(getMaxWattHours() - electricityStored)); + } + } + + /** + * This function is called to get the electricity stored in this item + * @return - The amount of electricity stored in watts + */ + @Override + public double getWattHours(Object... data) + { + if(data[0] instanceof ItemStack) + { + ItemStack itemStack = (ItemStack)data[0]; + + if(itemStack.stackTagCompound == null) + { + return 0; + } + double electricityStored=0; + if (itemStack.stackTagCompound.getTag("electricity") instanceof NBTTagFloat){ + electricityStored = itemStack.stackTagCompound.getFloat("electricity"); + }else{ + electricityStored = itemStack.stackTagCompound.getDouble("electricity"); + } + itemStack.setItemDamage((int)(getMaxWattHours() - electricityStored)); + return electricityStored; + } + + return -1; + } + + /** + * This function is called to get the maximum transfer rate this electric item can receive per tick + * @return - The amount of electricity maximum capacity + */ + public abstract double getTransferRate(); + + /** + * Gets the voltage of this item + * @return The Voltage of this item + */ + public abstract double getVoltage(); + + /** + * Returns an uncharged version of the electric item. Use this if you want + * the crafting recipe to use a charged version of the electric item + * instead of an empty version of the electric item + * @return The ItemStack of a fully charged electric item + */ + public ItemStack getUnchargedItemStack() + { + ItemStack chargedItem = new ItemStack(this); + chargedItem.setItemDamage((int) this.getMaxWattHours()); + return chargedItem; + } + + @Override + public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + //Add an uncharged version of the electric item + ItemStack unchargedItem = new ItemStack(this, 1); + unchargedItem.setItemDamage((int) this.getMaxWattHours()); + par3List.add(unchargedItem); + //Add an electric item to the creative list that is fully charged + ItemStack chargedItem = new ItemStack(this, 1); + this.setWattHours(((IItemElectric)chargedItem.getItem()).getMaxWattHours(), chargedItem); + par3List.add(chargedItem); + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityConductor.java b/src/common/universalelectricity/prefab/TileEntityConductor.java new file mode 100644 index 000000000..23a935da4 --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityConductor.java @@ -0,0 +1,175 @@ +package universalelectricity.prefab; + +import net.minecraft.src.Block; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.NetworkManager; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.electricity.ElectricityManager; +import universalelectricity.implement.IConductor; +import universalelectricity.implement.IConnector; +import universalelectricity.network.IPacketReceiver; +import universalelectricity.network.PacketManager; + +import com.google.common.io.ByteArrayDataInput; + +/** + * This tile entity prefabricated for all conductors. + * @author Calclavia + * + */ +public abstract class TileEntityConductor extends AdvancedTile implements IConductor, IPacketReceiver +{ + private int connectionID = 0; + + /** + * Stores information on the blocks that this conductor is connected to + */ + public TileEntity[] connectedBlocks = {null, null, null, null, null, null}; + + public TileEntityConductor() + { + this.reset(); + } + + @Override + public int getConnectionID() + { + return this.connectionID; + } + + @Override + public void setConnectionID(int ID) + { + this.connectionID = ID; + } + + @Override + public TileEntity[] getConnectedBlocks() + { + return connectedBlocks; + } + + @Override + public void initiate() + { + this.refreshConnectedBlocks(); + } + + /** + * Adds a connection between this conductor and a UE unit + * @param tileEntity - Must be either a producer, consumer or a conductor + * @param side - side in which the connection is coming from + */ + public void updateConnection(TileEntity tileEntity, ForgeDirection side) + { + if(tileEntity != null) + { + if(tileEntity instanceof IConnector) + { + this.connectedBlocks[side.ordinal()] = tileEntity; + + if (tileEntity.getClass() == this.getClass()) + { + ElectricityManager.instance.mergeConnection(this.connectionID, ((TileEntityConductor)tileEntity).connectionID); + } + + return; + } + } + + if (this.connectedBlocks[side.ordinal()] != null) + { + if (this.connectedBlocks[side.ordinal()] instanceof IConductor) + { + ElectricityManager.instance.splitConnection(this, (IConductor)this.getConnectedBlocks()[side.ordinal()]); + } + } + + this.connectedBlocks[side.ordinal()] = null; + } + + @Override + public void updateConnectionWithoutSplit(TileEntity tileEntity, ForgeDirection side) + { + if(tileEntity != null) + { + if(tileEntity instanceof IConnector) + { + this.connectedBlocks[side.ordinal()] = tileEntity; + + if (tileEntity.getClass() == this.getClass()) + { + ElectricityManager.instance.mergeConnection(this.connectionID, ((TileEntityConductor)tileEntity).connectionID); + } + + return; + } + } + + this.connectedBlocks[side.ordinal()] = null; + } + + @Override + public void handlePacketData(NetworkManager network, int type, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + if(this.worldObj.isRemote) + { + this.refreshConnectedBlocks(); + } + } + + /** + * Determines if this TileEntity requires update calls. + * @return True if you want updateEntity() to be called, false if not + */ + @Override + public boolean canUpdate() + { + return false; + } + + @Override + public void reset() + { + this.connectionID = 0; + + if(ElectricityManager.instance != null) + { + ElectricityManager.instance.registerConductor(this); + } + } + + @Override + public void refreshConnectedBlocks() + { + if (this.worldObj != null) + { + BlockConductor.updateConductorTileEntity(this.worldObj, this.xCoord, this.yCoord, this.zCoord); + } + } + + @Override + public World getWorld() + { + return this.worldObj; + } + + @Override + public boolean canConnect(ForgeDirection side) + { + return true; + } + + public Block getBlockType() + { + if (this.blockType == null) + { + this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)]; + } + + return this.blockType; + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityDisableable.java b/src/common/universalelectricity/prefab/TileEntityDisableable.java new file mode 100644 index 000000000..3d6c4ceac --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityDisableable.java @@ -0,0 +1,45 @@ +package universalelectricity.prefab; + +import universalelectricity.implement.IDisableable; + +/** + * An easier way to implement the methods from IElectricityDisableable with default values set. + * @author Calclavia + */ +public abstract class TileEntityDisableable extends AdvancedTile implements IDisableable +{ + protected int disabledTicks = 0; + + @Override + public void updateEntity() + { + super.updateEntity(); + + if(this.disabledTicks > 0) + { + this.disabledTicks --; + this.whileDisable(); + return; + } + } + + /** + * Called every tick while this tile entity is disabled. + */ + protected void whileDisable() + { + + } + + @Override + public void onDisable(int duration) + { + this.disabledTicks = duration; + } + + @Override + public boolean isDisabled() + { + return this.disabledTicks > 0; + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java b/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java new file mode 100644 index 000000000..bf213fbe0 --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java @@ -0,0 +1,35 @@ +package universalelectricity.prefab; + +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.electricity.ElectricityManager; +import universalelectricity.implement.IElectricityReceiver; + +/** + * An easier way to implement the methods from IElectricityReceiver with default values set. + * @author Calclavia + */ +public abstract class TileEntityElectricityReceiver extends TileEntityDisableable implements IElectricityReceiver +{ + public TileEntityElectricityReceiver() + { + ElectricityManager.instance.registerElectricUnit(this); + } + + @Override + public void updateEntity() + { + super.updateEntity(); + } + + @Override + public boolean canConnect(ForgeDirection side) + { + return this.canReceiveFromSide(side); + } + + @Override + public double getVoltage() + { + return 120; + } +} diff --git a/src/common/universalelectricity/prefab/Vector2.java b/src/common/universalelectricity/prefab/Vector2.java new file mode 100644 index 000000000..18e6b178f --- /dev/null +++ b/src/common/universalelectricity/prefab/Vector2.java @@ -0,0 +1,106 @@ +package universalelectricity.prefab; + +import net.minecraft.src.MathHelper; + +/** + * Vector2 Class is used for defining objects in a 2D space. Vector2 makes it easier to handle the coordinates of objects. Instead of + * fumbling with x and y variables, all x and y variables are stored in one class. Vector3.x, Vector3.y. + * + * Constructor: int x, int y + * Constructor: () - default would set x, y to 0. + * @author Calclavia + */ + +public class Vector2 implements Cloneable +{ + public double x; + public double y; + + public Vector2() + { + this(0, 0); + } + + public Vector2(int x, int y) + { + this.x = x; + this.y = y; + } + + public Vector2(double x, double y) + { + this.x = x; + this.y = y; + } + + //Returns the values as an int + public int intX() + { + return (int)Math.floor(this.x); + } + public int intY() + { + return (int)Math.floor(this.y); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public Vector2 clone() + { + return new Vector2(this.x, this.y); + } + + + public static boolean isPointInRegion(Vector2 point, Vector2 minPoint, Vector2 maxPoint) + { + return (point.x > minPoint.x && point.x < maxPoint.x) && (point.y > minPoint.y && point.y < maxPoint.y); + } + + public static double distance(Vector2 par1, Vector2 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4); + } + + public static double slope(Vector2 par1, Vector2 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + return var4 / var2; + } + + public void add(Vector2 par1) + { + this.x += par1.x; + this.y += par1.y; + } + + public void add(double par1) + { + this.x += par1; + this.y += par1; + } + + public Vector2 round() + { + return new Vector2(Math.round(this.x), Math.round(this.y)); + } + + public Vector2 floor() + { + return new Vector2(Math.floor(this.x), Math.floor(this.y)); + } + + public String output() + { + return "Vector2: " + this.x + "," + this.y; + } + + public void printVector() + { + System.out.println(output()); + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/prefab/Vector3.java b/src/common/universalelectricity/prefab/Vector3.java new file mode 100644 index 000000000..60ece17c9 --- /dev/null +++ b/src/common/universalelectricity/prefab/Vector3.java @@ -0,0 +1,421 @@ +package universalelectricity.prefab; + +import net.minecraft.src.ChunkCoordinates; +import net.minecraft.src.Entity; +import net.minecraft.src.MathHelper; +import net.minecraft.src.MovingObjectPosition; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import net.minecraft.src.Vec3; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IConnector; + +/** + * Vector3 Class is used for defining objects in a 3D space. Vector3 makes it easier to handle the coordinates of objects. Instead of + * fumbling with x, y and z variables, all x, y and z variables are stored in one class. Vector3.x, Vector3.y, Vector3.z. + * @author Calclavia + */ + +public class Vector3 extends Vector2 implements Cloneable +{ + public double z; + + public static final Vector3[] side = {new Vector3(0, -1, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1), new Vector3(0, 0, 1), new Vector3(-1, 0, 0), new Vector3(1, 0, 0)}; + + public Vector3() + { + this(0, 0, 0); + } + + public Vector3(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Returns the coordinates as integers + */ + public int intX() + { + return (int)Math.floor(this.x); + } + public int intY() + { + return (int)Math.floor(this.y); + } + public int intZ() + { + return (int)Math.floor(this.z); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public Vector3 clone() + { + return new Vector3(this.x, this.y, this.z); + } + + /** + * Converts a TileEntity's position into Vector3 + */ + public static Vector3 get(Entity par1) + { + return new Vector3(par1.posX, par1.posY, par1.posZ); + } + + /** + * Converts an entity's position into Vector3 + */ + public static Vector3 get(TileEntity par1) + { + return new Vector3(par1.xCoord, par1.yCoord, par1.zCoord); + } + + /** + * Converts from Vec3 into a Vector3 + */ + public static Vector3 get(Vec3 par1) + { + return new Vector3(par1.xCoord, par1.yCoord, par1.zCoord); + } + + /** + * Converts a MovingObjectPosition to Vector3 + */ + public static Vector3 get(MovingObjectPosition par1) + { + return new Vector3(par1.blockX, par1.blockY, par1.blockZ); + } + + /** + * Converts a MovingObjectPosition to Vector3 + */ + public static Vector3 get(ChunkCoordinates par1) + { + return new Vector3(par1.posX, par1.posY, par1.posZ); + } + + public int getBlockID(World world) + { + return world.getBlockId(this.intX(), this.intY(), this.intZ()); + } + + public int getBlockMetadata(World world) + { + return world.getBlockMetadata(this.intX(), this.intY(), this.intZ()); + } + + public TileEntity getTileEntity(World world) + { + return world.getBlockTileEntity(this.intX(), this.intY(), this.intZ()); + } + + public void setBlock(World world, int id, int metadata) + { + world.setBlockAndMetadata(this.intX(), this.intY(), this.intZ(), id, metadata); + } + + public void setBlock(World world, int id) + { + world.setBlock(this.intX(), this.intY(), this.intZ(), id); + } + + public void setBlockWithNotify(World world, int id, int metadata) + { + world.setBlockAndMetadataWithNotify(this.intX(), this.intY(), this.intZ(), id, metadata); + } + + public void setBlockWithNotify(World world, int id) + { + world.setBlockWithNotify(this.intX(), this.intY(), this.intZ(), id); + } + + /** + * Converts this Vector3 into a Vector2 by dropping the Y axis. + */ + public Vector2 toVector2() + { + return new Vector2(this.x, this.z); + } + + /** + * Converts this vector three into a Minecraft Vec3 object + */ + public Vec3 toVec3() + { + return Vec3.createVectorHelper(this.x, this.y, this.z); + } + + /** + * Checks if a Vector3 point is located inside a region + */ + public static boolean isPointInRegion(Vector3 point, Vector3 minPoint, Vector3 maxPoint) + { + return (point.x > minPoint.x && point.x < maxPoint.x) && (point.y > minPoint.y && point.y < maxPoint.y) && (point.z > minPoint.z && point.z < maxPoint.z); + } + + /** + * Compares two vectors and see if they are equal. True if so. + */ + public boolean isEqual(Vector3 vector3) + { + return (this.x == vector3.x && this.y == vector3.y && this.z == vector3.z); + } + + /** + * Gets the distance between two vectors + * @return The distance + */ + public static double distance(Vector3 par1, Vector3 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + double var6 = par1.z - par2.z; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6); + } + + public double distanceTo(Vector3 vector3) + { + double var2 = vector3.x - this.x; + double var4 = vector3.y - this.y; + double var6 = vector3.z - this.z; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6); + } + + public static Vector3 subtract(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x - par2.x, par1.y - par2.y, par1.z - par2.z); + } + + public static Vector3 add(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x + par2.x, par1.y + par2.y, par1.z + par2.z); + } + + public static Vector3 add(Vector3 par1, double par2) + { + return new Vector3(par1.x + par2, par1.y + par2, par1.z + par2); + } + + public void add(Vector3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + } + + @Override + public void add(double par1) + { + this.x += par1; + this.y += par1; + this.z += par1; + } + + public static Vector3 multiply(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x * par2.x, par1.y * par2.y, par1.z * par2.z); + } + + public static Vector3 multiply(Vector3 par1, double par2) + { + return new Vector3(par1.x * par2, par1.y * par2, par1.z * par2); + } + + public static Vector3 readFromNBT(String prefix, NBTTagCompound par1NBTTagCompound) + { + Vector3 tempVector = new Vector3(); + tempVector.x = par1NBTTagCompound.getDouble(prefix + "X"); + tempVector.y = par1NBTTagCompound.getDouble(prefix + "Y"); + tempVector.z = par1NBTTagCompound.getDouble(prefix + "Z"); + return tempVector; + } + + /** + * Saves this Vector3 to disk + * @param prefix - The prefix of this save. Use some unique string. + * @param par1NBTTagCompound - The NBT compound object to save the data in + */ + public void writeToNBT(String prefix, NBTTagCompound par1NBTTagCompound) + { + par1NBTTagCompound.setDouble(prefix + "X", this.x); + par1NBTTagCompound.setDouble(prefix + "Y", this.y); + par1NBTTagCompound.setDouble(prefix + "Z", this.z); + } + + @Override + public Vector3 round() + { + return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)); + } + @Override + public Vector3 floor() + { + return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); + } + public Vector3 top() + { + return add(this, side[0]); + } + public Vector3 bottom() + { + return add(this, side[1]); + } + public Vector3 front() + { + return add(this, side[2]); + } + public Vector3 back() + { + return add(this, side[3]); + } + public Vector3 left() + { + return add(this, side[4]); + } + public Vector3 right() + { + return add(this, side[5]); + } + @Override + public String output() + { + return "Vector3: " + this.x + "," + this.y + "," + this.z; + } + + /** + * Gets a position relative to another position's side + * @param position - The position + * @param side - The side. 0-5 + * @return The position relative to the original position's side + */ + public void modifyPositionFromSide(ForgeDirection side) + { + switch (side.ordinal()) + { + case 0: this.y -= 1; break; + case 1: this.y += 1; break; + case 2: this.z -= 1; break; + case 3: this.z += 1; break; + case 4: this.x -= 1; break; + case 5: this.x += 1; break; + } + } + + public static TileEntity getTileEntityFromSide(World world, Vector3 position, ForgeDirection side) + { + position.modifyPositionFromSide(side); + return world.getBlockTileEntity(position.intX(), position.intY(), position.intZ()); + } + + /** + * Gets a connector unit based on the given side. + */ + public static TileEntity getConnectorFromSide(World world, Vector3 position, ForgeDirection side) + { + TileEntity tileEntity = getTileEntityFromSide(world, position, side); + + if (tileEntity instanceof IConnector) + { + if (((IConnector)tileEntity).canConnect(getOrientationFromSide(side, ForgeDirection.NORTH))) + { + return tileEntity; + } + } + + return null; + } + + /** + * Finds the side of a block depending on it's facing direction from the given side. + * The side numbers are compatible with the function"getBlockTextureFromSideAndMetadata". + * + * Bottom: 0; + * Top: 1; + * Back: 2; + * Front: 3; + * Left: 4; + * Right: 5; + * @param front - The direction in which this block is facing/front. Use a number between 0 and 5. Default is 3. + * @param side - The side you are trying to find. A number between 0 and 5. + * @return The side relative to the facing direction. + */ + + public static ForgeDirection getOrientationFromSide(ForgeDirection front, ForgeDirection side) + { + switch (front.ordinal()) + { + case 0: + switch (side.ordinal()) + { + case 0: return ForgeDirection.getOrientation(3); + case 1: return ForgeDirection.getOrientation(2); + case 2: return ForgeDirection.getOrientation(1); + case 3: return ForgeDirection.getOrientation(0); + case 4: return ForgeDirection.getOrientation(5); + case 5: return ForgeDirection.getOrientation(4); + } + + case 1: + switch (side.ordinal()) + { + case 0: return ForgeDirection.getOrientation(4); + case 1: return ForgeDirection.getOrientation(5); + case 2: return ForgeDirection.getOrientation(0); + case 3: return ForgeDirection.getOrientation(1); + case 4: return ForgeDirection.getOrientation(2); + case 5: return ForgeDirection.getOrientation(3); + } + + case 2: + switch (side.ordinal()) + { + case 0: return ForgeDirection.getOrientation(0); + case 1: return ForgeDirection.getOrientation(1); + case 2: return ForgeDirection.getOrientation(3); + case 3: return ForgeDirection.getOrientation(2); + case 4: return ForgeDirection.getOrientation(5); + case 5: return ForgeDirection.getOrientation(4); + } + + case 3: + return side; + + case 4: + switch (side.ordinal()) + { + case 0: return ForgeDirection.getOrientation(0); + case 1: return ForgeDirection.getOrientation(1); + case 2: return ForgeDirection.getOrientation(5); + case 3: return ForgeDirection.getOrientation(4); + case 4: return ForgeDirection.getOrientation(3); + case 5: return ForgeDirection.getOrientation(2); + } + + case 5: + switch (side.ordinal()) + { + case 0: return ForgeDirection.getOrientation(0); + case 1: return ForgeDirection.getOrientation(1); + case 2: return ForgeDirection.getOrientation(4); + case 3: return ForgeDirection.getOrientation(5); + case 4: return ForgeDirection.getOrientation(2); + case 5: return ForgeDirection.getOrientation(3); + } + } + + return ForgeDirection.UNKNOWN; + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/prefab/chunk/ChunkEventCaller.java b/src/common/universalelectricity/prefab/chunk/ChunkEventCaller.java new file mode 100644 index 000000000..cbecda5d8 --- /dev/null +++ b/src/common/universalelectricity/prefab/chunk/ChunkEventCaller.java @@ -0,0 +1,105 @@ +package universalelectricity.prefab.chunk; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.Chunk; +import net.minecraft.src.TileEntity; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.ChunkEvent.Load; +import net.minecraftforge.event.world.ChunkEvent.Unload; +import universalelectricity.prefab.Vector2; + +public class ChunkEventCaller +{ + public static final ChunkEventCaller INSTANCE = new ChunkEventCaller(); + + private static final List HANDLERS = new ArrayList(); + + public static void register(IChunkLoadHandler handler) + { + if(!HANDLERS.contains(handler)) + { + HANDLERS.add(handler); + } + } + + public static void remove(IChunkLoadHandler handler) + { + if(HANDLERS.contains(handler)) + { + HANDLERS.remove(handler); + } + } + + public void cleanUpChunkHandler() + { + List removeList = new ArrayList(); + + for(IChunkLoadHandler handler : HANDLERS) + { + if(handler == null) + { + removeList.add(handler); + continue; + } + + if(handler instanceof TileEntity) + { + if(((TileEntity)handler).isInvalid()) + { + removeList.add(handler); + continue; + } + } + } + + HANDLERS.removeAll(removeList); + } + + @ForgeSubscribe + public void onChunkLoad(Load event) + { + this.cleanUpChunkHandler(); + + for(IChunkLoadHandler handler : HANDLERS) + { + Chunk chunk = event.getChunk(); + + if(handler instanceof TileEntity) + { + if(Vector2.isPointInRegion(new Vector2(((TileEntity)handler).xCoord, ((TileEntity)handler).zCoord), new Vector2(chunk.xPosition << 4, chunk.zPosition << 4), new Vector2((chunk.xPosition << 4) + 16, (chunk.zPosition << 4) + 16))) + { + handler.onChunkLoad(chunk); + } + } + else + { + handler.onChunkLoad(chunk); + } + } + } + + @ForgeSubscribe + public void onChunkUnload(Unload event) + { + this.cleanUpChunkHandler(); + + for(IChunkLoadHandler handler : HANDLERS) + { + Chunk chunk = event.getChunk(); + + if(handler instanceof TileEntity) + { + if(Vector2.isPointInRegion(new Vector2(((TileEntity)handler).xCoord, ((TileEntity)handler).zCoord), new Vector2(chunk.xPosition << 4, chunk.zPosition << 4), new Vector2((chunk.xPosition << 4) + 16, (chunk.zPosition << 4) + 16))) + { + handler.onChunkUnload(chunk); + } + } + else + { + handler.onChunkUnload(chunk); + } + } + } +} diff --git a/src/common/universalelectricity/prefab/chunk/IChunkLoadHandler.java b/src/common/universalelectricity/prefab/chunk/IChunkLoadHandler.java new file mode 100644 index 000000000..ea6940d50 --- /dev/null +++ b/src/common/universalelectricity/prefab/chunk/IChunkLoadHandler.java @@ -0,0 +1,21 @@ +package universalelectricity.prefab.chunk; + +import net.minecraft.src.Chunk; + +/** + * Applied to all objects that requires to be called when a chunk loads. When applied to tile entities, it will + * @author Calclavia + * + */ +public interface IChunkLoadHandler +{ + /** + * Called when a chunk loads. + */ + public void onChunkLoad(Chunk chunk); + + /** + * Called when a chunk loads. + */ + public void onChunkUnload(Chunk chunk); +} diff --git a/src/common/universalelectricity/prefab/potion/CustomPotion.java b/src/common/universalelectricity/prefab/potion/CustomPotion.java new file mode 100644 index 000000000..e3f56ba51 --- /dev/null +++ b/src/common/universalelectricity/prefab/potion/CustomPotion.java @@ -0,0 +1,36 @@ +package universalelectricity.prefab.potion; + +import net.minecraft.src.Potion; +import cpw.mods.fml.common.registry.LanguageRegistry; + +public abstract class CustomPotion extends Potion +{ + /** + * Creates a new type of potion + * @param id - The ID of this potion. Make it greater than 20. + * @param isBadEffect - Is this potion a good potion or a bad one? + * @param color - The color of this potion. + * @param name - The name of this potion. + */ + public CustomPotion(int id, boolean isBadEffect, int color, String name) + { + super(id, isBadEffect, color); + this.setPotionName("potion."+name); + LanguageRegistry.instance().addStringLocalization(this.getName(), name); + } + + @Override + public Potion setIconIndex(int par1, int par2) + { + super.setIconIndex(par1, par2); + return this; + } + + /** + * You must register all your potion effects during mod initialization! + */ + public void register() + { + Potion.potionTypes[this.getId()] = this; + } +} diff --git a/src/common/universalelectricity/prefab/potion/CustomPotionEffect.java b/src/common/universalelectricity/prefab/potion/CustomPotionEffect.java new file mode 100644 index 000000000..a37b7b9d1 --- /dev/null +++ b/src/common/universalelectricity/prefab/potion/CustomPotionEffect.java @@ -0,0 +1,39 @@ +package universalelectricity.prefab.potion; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.ItemStack; +import net.minecraft.src.Potion; +import net.minecraft.src.PotionEffect; + +public class CustomPotionEffect extends PotionEffect +{ + public CustomPotionEffect(int potionID, int duration, int amplifier) + { + super(potionID, duration, amplifier); + } + + public CustomPotionEffect(Potion potion, int duration, int amplifier) + { + this(potion.getId(), duration, amplifier); + } + + /** + * Creates a potion effect with custom curable items. + * @param curativeItems - ItemStacks that can cure this potion effect + */ + public CustomPotionEffect(int potionID, int duration, int amplifier, List curativeItems) + { + super(potionID, duration, amplifier); + + if(curativeItems == null) + { + this.setCurativeItems(new ArrayList()); + } + else + { + this.setCurativeItems(curativeItems); + } + } +} diff --git a/src/common/universalelectricity/recipe/CraftingRecipe.java b/src/common/universalelectricity/recipe/CraftingRecipe.java new file mode 100644 index 000000000..289bfc9ca --- /dev/null +++ b/src/common/universalelectricity/recipe/CraftingRecipe.java @@ -0,0 +1,25 @@ +package universalelectricity.recipe; + +import net.minecraft.src.ItemStack; + +public class CraftingRecipe +{ + public ItemStack output; + public Object[] input; + + public CraftingRecipe(ItemStack output, Object[] input) + { + this.output = output; + this.input = input; + } + + public boolean isEqual(CraftingRecipe comparingRecipe) + { + if(this.input == comparingRecipe.input && this.output == comparingRecipe.output) + { + return true; + } + + return false; + } +} diff --git a/src/common/universalelectricity/recipe/IRecipeHandler.java b/src/common/universalelectricity/recipe/IRecipeHandler.java new file mode 100644 index 000000000..3ecd43977 --- /dev/null +++ b/src/common/universalelectricity/recipe/IRecipeHandler.java @@ -0,0 +1,24 @@ +package universalelectricity.recipe; + +import java.util.List; + +public interface IRecipeHandler +{ + /** + * Called to add a recipe + * @param input - The input of the recipe + * @param output - The output of the recipe + */ + public void addRecipe(Object[] input, Object[] output); + + /** + * Gets a recipe's output by it's input + * @return - The output. Most likely an ItemStack. + */ + public Object getRecipeOutputByInput(Object[] input); + + /** + * Returns all recipes from this recipe handler + */ + public List getAllRecipes(); +} diff --git a/src/common/universalelectricity/recipe/RecipeManager.java b/src/common/universalelectricity/recipe/RecipeManager.java new file mode 100644 index 000000000..d81399c9b --- /dev/null +++ b/src/common/universalelectricity/recipe/RecipeManager.java @@ -0,0 +1,386 @@ +package universalelectricity.recipe; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.src.Block; +import net.minecraft.src.CraftingManager; +import net.minecraft.src.FurnaceRecipes; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraftforge.common.Configuration; +import net.minecraftforge.oredict.ShapedOreRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; +import universalelectricity.UEConfig; + +/** + * Adds recipes with full Forge ore dictionary support and replaceable by add-ons. + * Use UERecipes.addRecipe(....) like how you use ModLoader.addRecipe. + * + * MAKE SURE YOU ADD/REPLACE YOUR RECIPE BEFORE @PostInit OR IT WONT BE REPLACABLE! + * @author Calclavia + * + */ +public class RecipeManager +{ + //Crafting Recipes + private static final List SHAPED_RECIPES = new ArrayList(); + private static final List SHAPELESS_RECIPES = new ArrayList(); + + //Smelting Recipes + private static final List SMELTING_RECIPES = new ArrayList(); + + //Custom recipe handlers for UE machines + private static final Map RECIPE_HANDLERS = new HashMap(); + + //Shaped Recipes + public static void addRecipe(ItemStack output, Object[] input) + { + SHAPED_RECIPES.add(new CraftingRecipe(output, input)); + } + + public static void addRecipe(Item output, Object[] input) + { + addRecipe(new ItemStack(output), input); + } + + public static void addRecipe(Block output, Object[] input) + { + addRecipe(new ItemStack(output), input); + } + + /** + * Use this function if you want to check if the recipe is allowed in the configuration file. + */ + public static void addRecipe(ItemStack output, Object[] input, String name, Configuration config, boolean defaultBoolean) + { + if(config != null) + { + if(UEConfig.getConfigData(config, "Allow "+name+" Crafting", defaultBoolean)) + { + addRecipe(output, input); + } + } + } + + public static void addRecipe(ItemStack output, Object[] input, Configuration config, boolean defaultBoolean) + { + addRecipe(output, input, output.getItemName(), config, defaultBoolean); + } + + public static List getRecipes() { return SHAPED_RECIPES; } + + public static CraftingRecipe getRecipeByOutput(ItemStack output) + { + for(CraftingRecipe recipe : SHAPED_RECIPES) + { + if(recipe.output == output) + { + return recipe; + } + } + return null; + } + + //Shapeless Recipes + public static void addShapelessRecipe(ItemStack output, Object[] input) + { + SHAPELESS_RECIPES.add(new CraftingRecipe(output, input)); + } + + public static void addShapelessRecipe(Item output, Object[] input) + { + addShapelessRecipe(new ItemStack(output), input); + } + + public static void addShapelessRecipe(Block output, Object[] input) + { + addShapelessRecipe(new ItemStack(output), input); + } + + /** + * Use this function if you want to check if the recipe is allowed in the configuration file. + */ + public static void addShapelessRecipe(ItemStack output, Object[] input, String name, Configuration config, boolean defaultBoolean) + { + if(config != null) + { + if(UEConfig.getConfigData(config, "Allow "+name+" Crafting", defaultBoolean)) + { + addShapelessRecipe(output, input); + } + } + } + public static void addShapelessRecipe(ItemStack output, Object[] input, Configuration config, boolean defaultBoolean) + { + addShapelessRecipe(output, input, output.getItemName(), config, defaultBoolean); + } + + public static List getShapelessRecipes() { return SHAPELESS_RECIPES; } + + public static CraftingRecipe getShapelessRecipeByOutput(ItemStack output) + { + for(CraftingRecipe recipe : SHAPELESS_RECIPES) + { + if(recipe.output == output) + { + return recipe; + } + } + return null; + } + + //Furnace Smelting Recipes + public static void addSmelting(ItemStack input, ItemStack output) + { + SMELTING_RECIPES.add(new SmeltingRecipe(input, output)); + } + + public static void addSmelting(Item input, ItemStack output) + { + addSmelting(new ItemStack(input), output); + } + + public static void addSmelting(Block input, ItemStack output) + { + addSmelting(new ItemStack(input), output); + } + + /** + * Use this function if you want to check if the recipe is allowed in the configuration file. + */ + public static void addSmelting(ItemStack input, ItemStack output, String name, Configuration config, boolean defaultBoolean) + { + if(config != null) + { + if(UEConfig.getConfigData(config, "Allow "+name+" Smelting", defaultBoolean)) + { + addSmelting(input, output); + } + } + } + + public static void addSmelting(ItemStack input, ItemStack output, Configuration config, boolean defaultBoolean) + { + addSmelting(input, output, output.getItemName(), config, defaultBoolean); + } + + + public static List getSmeltingRecipes() { return SMELTING_RECIPES; } + + public static SmeltingRecipe getSmeltingRecipeByOutput(ItemStack output) + { + for(SmeltingRecipe recipe : SMELTING_RECIPES) + { + if(recipe.output == output) + { + return recipe; + } + } + return null; + } + /** + * Registers your {@link #IRecipeHandler} to the Recipe Manager so other UE mods can access and modify your recipes. + * @param handlerName - The name of your recipe handler. Make it something unique. This String is what other mods + * will be using to access your recipe handler. + * @param handler - An instance of your IRecipeHandler + */ + public static void registerRecipeHandler(String handlerName, IRecipeHandler handler) + { + if(!RECIPE_HANDLERS.containsKey(handlerName)) + { + RECIPE_HANDLERS.put(handlerName, handler); + } + } + + public static IRecipeHandler getRecipeHandler(String name) + { + return RECIPE_HANDLERS.get(name); + } + + public static Map getAllCustomRecipes() { return RECIPE_HANDLERS; } + + /** + * Replacement functions must be called before post mod initialization! + */ + public static void replaceRecipe(CraftingRecipe recipeToReplace, CraftingRecipe newRecipe) + { + for(CraftingRecipe recipe : SHAPED_RECIPES) + { + if(recipe.isEqual(recipeToReplace)) + { + recipe = newRecipe; + } + } + } + + + public static void replaceShapelessRecipe(CraftingRecipe recipeToReplace, CraftingRecipe newRecipe) + { + for(CraftingRecipe recipe : SHAPELESS_RECIPES) + { + if(recipe.isEqual(recipeToReplace)) + { + recipe = newRecipe; + } + } + } + + public static void replaceSmeltingRecipe(SmeltingRecipe recipeToReplace, SmeltingRecipe newRecipe) + { + for(SmeltingRecipe recipe : SMELTING_RECIPES) + { + if(recipe.isEqual(recipeToReplace)) + { + recipe = newRecipe; + } + } + } + + /** + * Finds and returns all recipes that have this specific output + * @param output - The output of the recipe. + */ + public static List findRecipe(ItemStack output) + { + List returnList = new ArrayList(); + + for(CraftingRecipe recipe : SHAPED_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + returnList.add(recipe); + } + } + + return returnList; + } + + public static List findShapelessRecipe(ItemStack output) + { + List returnList = new ArrayList(); + + for(CraftingRecipe recipe : SHAPELESS_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + returnList.add(recipe); + } + } + + return returnList; + } + + public static List findSmeltingRecipe(ItemStack output) + { + List returnList = new ArrayList(); + + for(SmeltingRecipe recipe : SMELTING_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + returnList.add(recipe); + } + } + + return returnList; + } + + /** + * Removes all recipes with the specific output. + */ + public static void removeRecipe(ItemStack output) + { + for(CraftingRecipe recipe : SHAPED_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + SHAPED_RECIPES.remove(recipe); + } + } + } + + public static void removeShapelessRecipe(ItemStack output) + { + for(CraftingRecipe recipe : SHAPELESS_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + SHAPELESS_RECIPES.remove(recipe); + } + } + } + + public static void removeSmeltingRecipe(ItemStack output) + { + for(SmeltingRecipe recipe : SMELTING_RECIPES) + { + if(recipe.output.isItemEqual(output)) + { + SMELTING_RECIPES.remove(recipe); + } + } + } + + /** + * Removes a specific recipe from the list. + */ + public static void removeRecipe(CraftingRecipe output) + { + for(CraftingRecipe recipe : SHAPED_RECIPES) + { + if(recipe.isEqual(output)) + { + SHAPED_RECIPES.remove(recipe); + return; + } + } + } + + public static void removeShapelessRecipe(CraftingRecipe output) + { + for(CraftingRecipe recipe : SHAPELESS_RECIPES) + { + if(recipe.isEqual(output)) + { + SHAPELESS_RECIPES.remove(recipe); + return; + } + } + } + + public static void removeSmeltingRecipe(SmeltingRecipe output) + { + for(SmeltingRecipe recipe : SMELTING_RECIPES) + { + if(recipe.isEqual(output)) + { + SMELTING_RECIPES.remove(recipe); + return; + } + } + } + + /** + * Called in post init by {@link #BasicComponenets} to add all recipes. Don't call this function. + */ + public static void addRecipes() + { + for (CraftingRecipe recipe : SHAPED_RECIPES) + { + CraftingManager.getInstance().getRecipeList().add(new ShapedOreRecipe(recipe.output, recipe.input)); + } + + for (CraftingRecipe recipe : SHAPELESS_RECIPES) + { + CraftingManager.getInstance().getRecipeList().add(new ShapelessOreRecipe(recipe.output, recipe.input)); + } + + for (SmeltingRecipe recipe : SMELTING_RECIPES) + { + FurnaceRecipes.smelting().addSmelting(recipe.input.itemID, recipe.input.getItemDamage(), recipe.output); + } + } +} diff --git a/src/common/universalelectricity/recipe/SmeltingRecipe.java b/src/common/universalelectricity/recipe/SmeltingRecipe.java new file mode 100644 index 000000000..60c70aec6 --- /dev/null +++ b/src/common/universalelectricity/recipe/SmeltingRecipe.java @@ -0,0 +1,25 @@ +package universalelectricity.recipe; + +import net.minecraft.src.ItemStack; + +public class SmeltingRecipe +{ + public ItemStack input; + public ItemStack output; + + public SmeltingRecipe(ItemStack input, ItemStack output) + { + this.input = input; + this.output = output; + } + + public boolean isEqual(SmeltingRecipe comparingRecipe) + { + if(this.input == comparingRecipe.input && this.output == comparingRecipe.output) + { + return true; + } + + return false; + } +}