From 28a3f54f89208148367fa764fc04b047551a283c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 17 May 2014 19:06:39 +0200 Subject: [PATCH] Made angel upgrade use an event. Added missing recomputation trigger for RAM and component counts. --- .../oc/api/event/RobotPlaceInAirEvent.java | 34 +++++++++++++++++++ .../java/li/cil/oc/api/machine/Robot.java | 4 +++ src/main/scala/li/cil/oc/common/Proxy.scala | 3 +- .../li/cil/oc/common/block/RobotProxy.scala | 2 ++ .../oc/common/event/AngelUpgradeHandler.scala | 14 ++++++++ .../li/cil/oc/common/tileentity/Robot.scala | 6 ++-- .../cil/oc/server/component/robot/Robot.scala | 11 ++++-- 7 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/main/java/li/cil/oc/api/event/RobotPlaceInAirEvent.java create mode 100644 src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala diff --git a/src/main/java/li/cil/oc/api/event/RobotPlaceInAirEvent.java b/src/main/java/li/cil/oc/api/event/RobotPlaceInAirEvent.java new file mode 100644 index 000000000..55c3934b3 --- /dev/null +++ b/src/main/java/li/cil/oc/api/event/RobotPlaceInAirEvent.java @@ -0,0 +1,34 @@ +package li.cil.oc.api.event; + +import li.cil.oc.api.machine.Robot; + +/** + * This event is fired when a robot tries to place a block and has no point of + * reference, i.e. the place would have to be placed in "thin air". Per default + * this fails (because players can't do this, either). + *

+ * This is primarily intended for the 'Angel Upgrade', but it might be useful + * for other upgrades, too. + */ +public class RobotPlaceInAirEvent extends RobotEvent { + private boolean isAllowed = false; + + public RobotPlaceInAirEvent(Robot robot) { + super(robot); + } + + /** + * Whether the placement is allowed. Defaults to false. + */ + public boolean isAllowed() { + return isAllowed; + } + + /** + * Set whether the placement is allowed, can be used to allow robots to + * place blocks in thin air. + */ + public void setAllowed(boolean value) { + this.isAllowed = value; + } +} diff --git a/src/main/java/li/cil/oc/api/machine/Robot.java b/src/main/java/li/cil/oc/api/machine/Robot.java index 881ebb83a..f995f988a 100644 --- a/src/main/java/li/cil/oc/api/machine/Robot.java +++ b/src/main/java/li/cil/oc/api/machine/Robot.java @@ -42,6 +42,10 @@ public interface Robot extends ISidedInventory, Rotatable { /** * The number of hot-swappable component slots in this robot. + *

+ * Note: this will always be three, regardless of the number of + * installed containers. For unused slots the inventory will simply be + * empty at that slot. */ int containerCount(); diff --git a/src/main/scala/li/cil/oc/common/Proxy.scala b/src/main/scala/li/cil/oc/common/Proxy.scala index 78e5f4555..c8ae0fc79 100644 --- a/src/main/scala/li/cil/oc/common/Proxy.scala +++ b/src/main/scala/li/cil/oc/common/Proxy.scala @@ -19,7 +19,7 @@ import net.minecraft.item.{Item, ItemStack} import net.minecraft.block.Block import net.minecraftforge.oredict.OreDictionary import scala.collection.convert.WrapAsScala._ -import li.cil.oc.common.event.{ExperienceUpgradeHandler, UniversalElectricityToolHandler, RobotCommonHandler} +import li.cil.oc.common.event.{AngelUpgradeHandler, ExperienceUpgradeHandler, UniversalElectricityToolHandler, RobotCommonHandler} class Proxy { def preInit(e: FMLPreInitializationEvent) { @@ -96,6 +96,7 @@ class Proxy { Recipes.init() GameRegistry.registerCraftingHandler(CraftingHandler) + MinecraftForge.EVENT_BUS.register(AngelUpgradeHandler) MinecraftForge.EVENT_BUS.register(RobotCommonHandler) MinecraftForge.EVENT_BUS.register(ExperienceUpgradeHandler) if (Mods.UniversalElectricity.isAvailable) { diff --git a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala index f800d6716..26065b677 100644 --- a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala +++ b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala @@ -160,6 +160,8 @@ class RobotProxy(val parent: SpecialDelegator) extends RedstoneAware with Specia case Some((robot, owner)) => robot.owner = owner robot.info.load(stack) + robot.updateInventorySize() + robot.updateMaxComponentCount() case _ => } } diff --git a/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala b/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala new file mode 100644 index 000000000..ee77002f8 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/event/AngelUpgradeHandler.scala @@ -0,0 +1,14 @@ +package li.cil.oc.common.event + +import li.cil.oc.api.event.RobotPlaceInAirEvent +import li.cil.oc.api +import net.minecraftforge.event.ForgeSubscribe + +object AngelUpgradeHandler { + @ForgeSubscribe + def onPlaceInAir(e: RobotPlaceInAirEvent) { + val startComponents = 1 + e.robot.containerCount + e.robot.inventorySize + e.setAllowed(((1 to e.robot.containerCount) ++ (startComponents until startComponents + e.robot.componentCount)). + exists(slot => api.Items.get(e.robot.getStackInSlot(slot)) == api.Items.get("angelUpgrade"))) + } +} diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala index 39f2ae187..f6bf3b675 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala @@ -300,6 +300,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.PowerInfo updateInventorySize() updateMaxComponentCount() + computer.architecture.recomputeMemory() bot.load(nbt.getCompoundTag(Settings.namespace + "robot")) if (nbt.hasKey(Settings.namespace + "owner")) { @@ -405,6 +406,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.PowerInfo super.onConnect(node) if (node == this.node) { node.connect(bot.node) + // There's a chance the server sends a robot tile entity to its clients // before the tile entity's first update was called, in which case the // component list isn't initialized (e.g. when a client triggers a chunk @@ -563,7 +565,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.PowerInfo private var updatingInventorySize = false - private def updateInventorySize() = this.synchronized(if (!updatingInventorySize) try { + def updateInventorySize() = this.synchronized(if (!updatingInventorySize) try { updatingInventorySize = true inventorySize = computeInventorySize() val realSize = 1 + containerCount + inventorySize @@ -589,7 +591,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.PowerInfo updatingInventorySize = false }) - private def updateMaxComponentCount() { + def updateMaxComponentCount() { maxComponents = computeMaxComponents() } diff --git a/src/main/scala/li/cil/oc/server/component/robot/Robot.scala b/src/main/scala/li/cil/oc/server/component/robot/Robot.scala index 418a22d09..7c556f34c 100644 --- a/src/main/scala/li/cil/oc/server/component/robot/Robot.scala +++ b/src/main/scala/li/cil/oc/server/component/robot/Robot.scala @@ -18,6 +18,7 @@ import net.minecraftforge.event.world.BlockEvent import net.minecraftforge.fluids.FluidRegistry import scala.collection.convert.WrapAsScala._ import li.cil.oc.common.component.ManagedComponent +import li.cil.oc.api.event.RobotPlaceInAirEvent class Robot(val robot: tileentity.Robot) extends ManagedComponent { val node = api.Network.newNode(this, Visibility.Neighbors). @@ -44,7 +45,11 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent { def player = robot.player() - def hasAngelUpgrade = (robot.containerSlots ++ robot.componentSlots).exists(slot => api.Items.get(robot.getStackInSlot(slot)) == api.Items.get("angelUpgrade")) + def canPlaceInAir = { + val event = new RobotPlaceInAirEvent(robot) + MinecraftForge.EVENT_BUS.post(event) + event.isAllowed + } @Callback def name(context: Context, args: Arguments): Array[AnyRef] = result(robot.name) @@ -238,7 +243,7 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent { case Some(hit) if hit.typeOfHit == EnumMovingObjectType.TILE => val (bx, by, bz, hx, hy, hz) = clickParamsFromHit(hit) player.placeBlock(robot.selectedSlot, bx, by, bz, hit.sideHit, hx, hy, hz) - case None if hasAngelUpgrade && player.closestEntity[Entity]().isEmpty => + case None if canPlaceInAir && player.closestEntity[Entity]().isEmpty => val (bx, by, bz, hx, hy, hz) = clickParamsForPlace(facing) player.placeBlock(robot.selectedSlot, bx, by, bz, facing.ordinal, hx, hy, hz) case _ => false @@ -451,7 +456,7 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent { val (bx, by, bz, hx, hy, hz) = clickParamsFromHit(hit) activationResult(player.activateBlockOrUseItem(bx, by, bz, hit.sideHit, hx, hy, hz, duration)) case _ => - (if (hasAngelUpgrade) { + (if (canPlaceInAir) { val (bx, by, bz, hx, hy, hz) = clickParamsForPlace(facing) if (player.placeBlock(0, bx, by, bz, facing.ordinal, hx, hy, hz)) ActivationType.ItemPlaced