From fbdac0760fbe243ac47b0b2ad021c16702b8a49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 18 Nov 2013 17:34:51 +0100 Subject: [PATCH] expanded fake player class a bit to avoid weird things happening (such as the robots opening GUIs - hint: fun time!); added options on whether robots may activate blocks (levers, buttons) and whether onItemUseFirst should be called (disabled per default to get portal guns to work). the latter is a setting because it may cause issues in mods that actually use it --- li/cil/oc/Config.scala | 47 +++++++---- li/cil/oc/server/component/Robot.scala | 10 ++- li/cil/oc/util/RobotPlayer.scala | 107 ++++++++++++++++++------- 3 files changed, 117 insertions(+), 47 deletions(-) diff --git a/li/cil/oc/Config.scala b/li/cil/oc/Config.scala index 33d972c79..3c05d678a 100644 --- a/li/cil/oc/Config.scala +++ b/li/cil/oc/Config.scala @@ -16,12 +16,32 @@ object Config { // ----------------------------------------------------------------------- // + var blockRenderId = 0 + + // ----------------------------------------------------------------------- // + + var blockId = 3650 + var blockSpecialId = 3651 + var itemId = 4600 + + // ----------------------------------------------------------------------- // + // client + + var maxScreenTextRenderDistance = 10.0 + var screenTextFadeStartDistance = 8.0 + var textLinearFiltering = false + + // ----------------------------------------------------------------------- // + // power + var ignorePower = false + // power.buffer var bufferConverter = 100.0 var bufferCapacitor = 50.0 var bufferPowerSupply = 50.0 + // power.cost var computerCost = 1.0 var gpuFillCost = 1.0 / 100 var gpuClearCost = 1.0 / 400 @@ -34,23 +54,9 @@ object Config { var wirelessCostPerRange = 1.0 / 20.0 // ----------------------------------------------------------------------- // + // server - var blockRenderId = 0 - - // ----------------------------------------------------------------------- // - - var blockId = 3650 - var blockSpecialId = 3651 - var itemId = 4600 - - // ----------------------------------------------------------------------- // - - var maxScreenTextRenderDistance = 10.0 - var screenTextFadeStartDistance = 8.0 - var textLinearFiltering = false - - // ----------------------------------------------------------------------- // - + // server.computer var baseMemory = 0 var canComputersBeOwned = true var maxUsernameLength = 32 @@ -59,16 +65,25 @@ object Config { var threads = 4 var timeout = 3.0 + // server.filesystem var fileCost = 512 var filesBuffered = true var maxHandles = 16 var maxReadBuffer = 8 * 1024 + // server.misc var commandUser = "OpenComputers" var maxScreenHeight = 6 var maxScreenWidth = 8 var maxWirelessRange = 400.0 + // ----------------------------------------------------------------------- // + // robot + + var callOnItemUseFirst = false + var allowActivateBlocks = true + var canAttackPlayers = false + // ----------------------------------------------------------------------- // def load(file: File) = { diff --git a/li/cil/oc/server/component/Robot.scala b/li/cil/oc/server/component/Robot.scala index 9b507967e..b3d5b4086 100644 --- a/li/cil/oc/server/component/Robot.scala +++ b/li/cil/oc/server/component/Robot.scala @@ -111,6 +111,8 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) { val side = checkSideForAction(args, 0) val count = checkOptionalItemCount(args, 1) // TODO inventory, if available + + // TODO player.dropitem with blah result(robot.dropSlot(actualSlot(selectedSlot), count, side)) } @@ -118,6 +120,9 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) { def place(context: Context, args: Arguments): Array[AnyRef] = { val lookSide = checkSideForAction(args, 0) val side = if (args.isInteger(1)) checkSide(args, 1) else lookSide + if (side.getOpposite == lookSide) { + throw new IllegalArgumentException("invalid side") + } val sneaky = args.isBoolean(2) && args.checkBoolean(2) val player = robot.player(lookSide) val stack = player.robotInventory.selectedItemStack @@ -139,7 +144,6 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) { @LuaCallback("suck") def suck(context: Context, args: Arguments): Array[AnyRef] = { - // Pick up items lying around. val side = checkSideForAction(args, 0) val count = checkOptionalItemCount(args, 1) // TODO inventory, if available @@ -207,6 +211,9 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) { def use(context: Context, args: Arguments): Array[AnyRef] = { val lookSide = checkSideForAction(args, 0) val side = if (args.isInteger(1)) checkSide(args, 1) else lookSide + if (side.getOpposite == lookSide) { + throw new IllegalArgumentException("invalid side") + } val sneaky = args.isBoolean(2) && args.checkBoolean(2) val player = robot.player(lookSide) player.setSneaking(sneaky) @@ -228,7 +235,6 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) { @LuaCallback("turn") def turn(context: Context, args: Arguments): Array[AnyRef] = { - // Turn in the specified direction. val clockwise = args.checkBoolean(0) if (clockwise) robot.rotate(ForgeDirection.UP) else robot.rotate(ForgeDirection.DOWN) diff --git a/li/cil/oc/util/RobotPlayer.scala b/li/cil/oc/util/RobotPlayer.scala index 3dd08bc55..b58601ac0 100644 --- a/li/cil/oc/util/RobotPlayer.scala +++ b/li/cil/oc/util/RobotPlayer.scala @@ -1,9 +1,14 @@ package li.cil.oc.util +import li.cil.oc.Config import li.cil.oc.common.tileentity.Robot import net.minecraft.block.Block +import net.minecraft.entity.player.{EnumStatus, EntityPlayer} +import net.minecraft.entity.{EntityLivingBase, Entity} import net.minecraft.item.ItemStack -import net.minecraft.util.ChunkCoordinates +import net.minecraft.potion.PotionEffect +import net.minecraft.util.{DamageSource, ChunkCoordinates} +import net.minecraft.world.World import net.minecraftforge.common.{ForgeDirection, FakePlayer} import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action import net.minecraftforge.event.{Event, ForgeEventFactory} @@ -16,10 +21,30 @@ class RobotPlayer(val robot: Robot) extends FakePlayer(robot.world, "OpenCompute inventory = robotInventory yOffset = 1f - // TODO override def getBoundingBox = super.getBoundingBox - override def getPlayerCoordinates = new ChunkCoordinates(robot.x, robot.y, robot.z) + // ----------------------------------------------------------------------- // + + def updatePositionAndRotation(pitch: ForgeDirection) { + val offsetToGetPistonsToBePlacedProperly = pitch.offsetY * 0.83 + setLocationAndAngles( + robot.x + 0.5, + robot.y - offsetToGetPistonsToBePlacedProperly, + robot.z + 0.5, + robot.yaw match { + case ForgeDirection.WEST => 90 + case ForgeDirection.NORTH => 180 + case ForgeDirection.EAST => 270 + case _ => 0 + }, pitch.offsetY * -90) + } + + // ----------------------------------------------------------------------- // + + // TODO override def canAttackWithItem = super.canAttackWithItem + + // TODO override def attackTargetEntityWithCurrentItem(par1Entity: Entity) + def activateBlockOrUseItem(x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = { val event = ForgeEventFactory.onPlayerInteract(this, Action.RIGHT_CLICK_BLOCK, x, y, z, side) if (event.isCanceled) { @@ -29,15 +54,18 @@ class RobotPlayer(val robot: Robot) extends FakePlayer(robot.world, "OpenCompute val world = robot.world val stack = inventory.getCurrentItem val item = if (stack != null) stack.getItem else null - if (item != null && item.onItemUseFirst(stack, this, world, x, y, z, side, hitX, hitY, hitZ)) { - if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack) - if (stack.stackSize <= 0) inventory.setInventorySlotContents(0, null) - return true + if (Config.callOnItemUseFirst) { + if (item != null && item.onItemUseFirst(stack, this, world, x, y, z, side, hitX, hitY, hitZ)) { + if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack) + if (stack.stackSize <= 0) inventory.setInventorySlotContents(0, null) + return true + } } val blockId = world.getBlockId(x, y, z) val block = Block.blocksList(blockId) - val shouldActivate = block != null && (!isSneaking || (item == null || item.shouldPassSneakingClickToBlock(world, x, y, z))) + val canActivate = block != null && Config.allowActivateBlocks + val shouldActivate = canActivate && (!isSneaking || (item == null || item.shouldPassSneakingClickToBlock(world, x, y, z))) val activated = shouldActivate && (event.useBlock == Event.Result.DENY || block.onBlockActivated(world, x, y, z, this, side, hitX, hitY, hitZ)) @@ -78,27 +106,48 @@ class RobotPlayer(val robot: Robot) extends FakePlayer(robot.world, "OpenCompute } } - def updatePositionAndRotation(pitch: ForgeDirection) { - val offsetToGetPistonsToBePlacedProperly = pitch.offsetY * 0.83 - posX = robot.x + 0.5 - posY = robot.y + yOffset - offsetToGetPistonsToBePlacedProperly - posZ = robot.z + 0.5 - rotationPitch = pitch.offsetY * -90 - rotationYaw = robot.yaw match { - case ForgeDirection.WEST => 90 - case ForgeDirection.NORTH => 180 - case ForgeDirection.EAST => 270 - case _ => 0 - } + // ----------------------------------------------------------------------- // - prevPosX = posZ - prevPosY = posY - prevPosZ = posZ - prevRotationPitch = rotationPitch - cameraPitch = rotationPitch - prevCameraPitch = rotationPitch - prevRotationYaw = rotationYaw - cameraYaw = rotationYaw - prevCameraYaw = rotationYaw + override def swingItem() { + // TODO animation } + + override def canAttackPlayer(player: EntityPlayer) = + Config.canAttackPlayers && super.canAttackPlayer(player) + + override def canEat(value: Boolean) = false + + override def isPotionApplicable(effect: PotionEffect) = false + + override def attackEntityAsMob(entity: Entity) = false + + override def attackEntityFrom(source: DamageSource, damage: Float) = false + + override def setItemInUse(stack: ItemStack, maxItemUseDuration: Int) {} + + override def openGui(mod: AnyRef, modGuiId: Int, world: World, x: Int, y: Int, z: Int) {} + + override def closeScreen() {} + + override def heal(amount: Float) {} + + override def setHealth(value: Float) {} + + override def setDead() = isDead = true + + override def onDeath(source: DamageSource) {} + + override def setCurrentItemOrArmor(slot: Int, stack: ItemStack) {} + + override def setRevengeTarget(entity: EntityLivingBase) {} + + override def setLastAttacker(entity: Entity) {} + + override def mountEntity(entity: Entity) {} + + override def travelToDimension(dimension: Int) {} + + override def sleepInBedAt(x: Int, y: Int, z: Int) = EnumStatus.OTHER_PROBLEM + + override def interactWith(entity: Entity) = false // TODO Or do we want this? }