From c4fa6f157e5c6d58ccbe3b24f6a023de247828a6 Mon Sep 17 00:00:00 2001 From: Vexatos Date: Sat, 9 Jul 2016 17:48:41 +0200 Subject: [PATCH] Made wrenching an Adapter's side turn it off. For #1851. No texture changes yet, but client sync is in place. --- .../li/cil/oc/client/PacketHandler.scala | 11 ++++- .../scala/li/cil/oc/common/PacketType.scala | 3 +- .../li/cil/oc/common/block/Adapter.scala | 19 ++++++++ .../li/cil/oc/common/tileentity/Adapter.scala | 29 ++++++++++- .../oc/common/tileentity/NetSplitter.scala | 28 +++-------- .../common/tileentity/traits/OpenSides.scala | 48 +++++++++++++++++++ .../scala/li/cil/oc/server/PacketSender.scala | 11 ++++- 7 files changed, 122 insertions(+), 27 deletions(-) create mode 100644 src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala index ea3ca4563..61bb8efc5 100644 --- a/src/main/scala/li/cil/oc/client/PacketHandler.scala +++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala @@ -42,6 +42,7 @@ object PacketHandler extends CommonPacketHandler { override def dispatch(p: PacketParser) { p.packetType match { case PacketType.AbstractBusState => onAbstractBusState(p) + case PacketType.AdapterState => onAdapterState(p) case PacketType.Analyze => onAnalyze(p) case PacketType.ChargerState => onChargerState(p) case PacketType.ClientLog => onClientLog(p) @@ -102,6 +103,14 @@ object PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onAdapterState(p: PacketParser) = + p.readTileEntity[Adapter]() match { + case Some(t) => + t.openSides = t.uncompressSides(p.readByte()) + t.world.markBlockForUpdate(t.x, t.y, t.z) + case _ => // Invalid packet. + } + def onAnalyze(p: PacketParser) { val address = p.readUTF() if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { @@ -757,4 +766,4 @@ object PacketHandler extends CommonPacketHandler { case Some(waypoint) => waypoint.label = p.readUTF() case _ => // Invalid packet. } -} \ No newline at end of file +} diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index 807520dea..aa0d4c133 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -4,6 +4,7 @@ object PacketType extends Enumeration { val // Server -> Client AbstractBusState, + AdapterState, Analyze, ChargerState, ClientLog, @@ -86,4 +87,4 @@ object PacketType extends Enumeration { ServerPower, EndOfList = Value -} \ No newline at end of file +} diff --git a/src/main/scala/li/cil/oc/common/block/Adapter.scala b/src/main/scala/li/cil/oc/common/block/Adapter.scala index 5deabb33a..6b2a69917 100644 --- a/src/main/scala/li/cil/oc/common/block/Adapter.scala +++ b/src/main/scala/li/cil/oc/common/block/Adapter.scala @@ -2,7 +2,10 @@ package li.cil.oc.common.block import li.cil.oc.common.GuiType import li.cil.oc.common.tileentity +import li.cil.oc.integration.util.Wrench +import li.cil.oc.util.BlockPosition import net.minecraft.block.Block +import net.minecraft.entity.player.EntityPlayer import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.common.util.ForgeDirection @@ -44,6 +47,22 @@ class Adapter extends SimpleBlock with traits.GUI { case _ => // Ignore. } + override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = { + if (Wrench.holdsApplicableWrench(player, BlockPosition(x, y, z))) { + val sideToToggle = if (player.isSneaking) side.getOpposite else side + world.getTileEntity(x, y, z) match { + case adapter: tileentity.Adapter => + if (!world.isRemote) { + val oldValue = adapter.openSides(sideToToggle.ordinal()) + adapter.setSideOpen(sideToToggle, !oldValue) + } + true + case _ => false + } + } + else super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ) + } + private val sides = Array( ForgeDirection.NORTH, ForgeDirection.DOWN, diff --git a/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala b/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala index 565fed8f2..5eb3a356a 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Adapter.scala @@ -13,6 +13,7 @@ import li.cil.oc.api.internal import li.cil.oc.api.network.Analyzable import li.cil.oc.api.network._ import li.cil.oc.common.Slot +import li.cil.oc.server.{PacketSender => ServerPacketSender} import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound @@ -23,7 +24,7 @@ import net.minecraftforge.common.util.ForgeDirection import scala.collection.convert.WrapAsJava._ import scala.collection.mutable -class Adapter extends traits.Environment with traits.ComponentInventory with Analyzable with internal.Adapter with DeviceInfo { +class Adapter extends traits.Environment with traits.ComponentInventory with traits.OpenSides with Analyzable with internal.Adapter with DeviceInfo { val node = api.Network.newNode(this, Visibility.Network).create() private val blocks = Array.fill[Option[(ManagedEnvironment, api.driver.SidedBlock)]](6)(None) @@ -43,6 +44,22 @@ class Adapter extends traits.Environment with traits.ComponentInventory with Ana // ----------------------------------------------------------------------- // + override protected def defaultState = true + + override def setSideOpen(side: ForgeDirection, value: Boolean) { + super.setSideOpen(side, value) + if (isServer) { + ServerPacketSender.sendAdapterState(this) + world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "tile.piston.out", 0.5f, world.rand.nextFloat() * 0.25f + 0.7f) + world.notifyBlocksOfNeighborChange(x, y, z, block) + neighborChanged(side) + } else { + world.markBlockForUpdate(x, y, z) + } + } + + // ----------------------------------------------------------------------- // + override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = blocks collect { case Some(((environment, _))) => environment.node } @@ -74,6 +91,14 @@ class Adapter extends traits.Environment with traits.ComponentInventory with Ana Option(api.Driver.driverFor(world, x, y, z, d)) match { case Some(newDriver) => blocks(d.ordinal()) match { case Some((oldEnvironment, driver)) => + if(!isSideOpen(d)) { + // Good bye. + blocks(d.ordinal()) = None + updatingBlocks -= oldEnvironment + blocksData(d.ordinal()) = None + node.disconnect(oldEnvironment.node) + return + } if (newDriver != driver) { // This is... odd. Maybe moved by some other mod? First, clean up. blocks(d.ordinal()) = None @@ -92,7 +117,7 @@ class Adapter extends traits.Environment with traits.ComponentInventory with Ana node.connect(environment.node) } } // else: the more things change, the more they stay the same. - case _ => + case _ if isSideOpen(d) => // A challenger appears. Maybe. val environment = newDriver.createEnvironment(world, x, y, z, d) if (environment != null) { diff --git a/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala b/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala index 723158ff8..e212409cf 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/NetSplitter.scala @@ -1,17 +1,14 @@ package li.cil.oc.common.tileentity -import cpw.mods.fml.relauncher.Side -import cpw.mods.fml.relauncher.SideOnly -import li.cil.oc.Settings -import li.cil.oc.api +import cpw.mods.fml.relauncher.{Side, SideOnly} +import li.cil.oc.{Settings, api} import li.cil.oc.api.network.Visibility import li.cil.oc.common.EventHandler import li.cil.oc.server.{PacketSender => ServerPacketSender} import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.util.ForgeDirection -class NetSplitter extends traits.Environment with traits.RedstoneAware with api.network.SidedEnvironment { - private final val SideCount = ForgeDirection.VALID_DIRECTIONS.length +class NetSplitter extends traits.Environment with traits.OpenSides with traits.RedstoneAware with api.network.SidedEnvironment { _isOutputEnabled = true @@ -20,19 +17,10 @@ class NetSplitter extends traits.Environment with traits.RedstoneAware with api. var isInverted = false - var openSides = Array.fill(SideCount)(false) + override def isSideOpen(side: ForgeDirection) = if (isInverted) !super.isSideOpen(side) else super.isSideOpen(side) - def compressSides = (ForgeDirection.VALID_DIRECTIONS, openSides).zipped.foldLeft(0)((acc, entry) => acc | (if (entry._2) entry._1.flag else 0)).toByte - - def uncompressSides(byte: Byte) = ForgeDirection.VALID_DIRECTIONS.map(d => (d.flag & byte) != 0) - - def isSideOpen(side: ForgeDirection) = side != ForgeDirection.UNKNOWN && { - val isOpen = openSides(side.ordinal()) - if (isInverted) !isOpen else isOpen - } - - def setSideOpen(side: ForgeDirection, value: Boolean): Unit = if (side != ForgeDirection.UNKNOWN && openSides(side.ordinal()) != value) { - openSides(side.ordinal()) = value + override def setSideOpen(side: ForgeDirection, value: Boolean) { + super.setSideOpen(side, value) if (isServer) { node.remove() api.Network.joinOrCreateNetwork(this) @@ -83,25 +71,21 @@ class NetSplitter extends traits.Environment with traits.RedstoneAware with api. override def readFromNBTForServer(nbt: NBTTagCompound): Unit = { super.readFromNBTForServer(nbt) isInverted = nbt.getBoolean(Settings.namespace + "isInverted") - openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides")) } override def writeToNBTForServer(nbt: NBTTagCompound): Unit = { super.writeToNBTForServer(nbt) nbt.setBoolean(Settings.namespace + "isInverted", isInverted) - nbt.setByte(Settings.namespace + "openSides", compressSides) } @SideOnly(Side.CLIENT) override def readFromNBTForClient(nbt: NBTTagCompound): Unit = { super.readFromNBTForClient(nbt) isInverted = nbt.getBoolean(Settings.namespace + "isInverted") - openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides")) } override def writeToNBTForClient(nbt: NBTTagCompound): Unit = { super.writeToNBTForClient(nbt) nbt.setBoolean(Settings.namespace + "isInverted", isInverted) - nbt.setByte(Settings.namespace + "openSides", compressSides) } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala new file mode 100644 index 000000000..73fb0f0c7 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/OpenSides.scala @@ -0,0 +1,48 @@ +package li.cil.oc.common.tileentity.traits + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import li.cil.oc.Settings +import net.minecraft.nbt.NBTTagCompound +import net.minecraftforge.common.util.ForgeDirection + +/** + * @author Vexatos + */ +trait OpenSides extends TileEntity { + protected def SideCount = ForgeDirection.VALID_DIRECTIONS.length + + protected def defaultState: Boolean = false + + var openSides = Array.fill(SideCount)(defaultState) + + def compressSides = (ForgeDirection.VALID_DIRECTIONS, openSides).zipped.foldLeft(0)((acc, entry) => acc | (if (entry._2) entry._1.flag else 0)).toByte + + def uncompressSides(byte: Byte) = ForgeDirection.VALID_DIRECTIONS.map(d => (d.flag & byte) != 0) + + def isSideOpen(side: ForgeDirection) = side != ForgeDirection.UNKNOWN && openSides(side.ordinal()) + + def setSideOpen(side: ForgeDirection, value: Boolean): Unit = if (side != ForgeDirection.UNKNOWN && openSides(side.ordinal()) != value) { + openSides(side.ordinal()) = value + } + + override def readFromNBTForServer(nbt: NBTTagCompound) { + super.readFromNBTForServer(nbt) + openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides")) + } + + override def writeToNBTForServer(nbt: NBTTagCompound) { + super.writeToNBTForServer(nbt) + nbt.setByte(Settings.namespace + "openSides", compressSides) + } + + @SideOnly(Side.CLIENT) + override def readFromNBTForClient(nbt: NBTTagCompound) { + super.readFromNBTForClient(nbt) + openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides")) + } + + override def writeToNBTForClient(nbt: NBTTagCompound) { + super.writeToNBTForClient(nbt) + nbt.setByte(Settings.namespace + "openSides", compressSides) + } +} diff --git a/src/main/scala/li/cil/oc/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index 093a75484..1aa01ca3b 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -32,6 +32,15 @@ object PacketSender { pb.sendToPlayersNearTileEntity(t) } + def sendAdapterState(t: tileentity.Adapter): Unit = { + val pb = new SimplePacketBuilder(PacketType.AdapterState) + + pb.writeTileEntity(t) + pb.writeByte(t.compressSides) + + pb.sendToPlayersNearTileEntity(t) + } + def sendAnalyze(address: String, player: EntityPlayerMP) { val pb = new SimplePacketBuilder(PacketType.Analyze) @@ -740,4 +749,4 @@ object PacketSender { pb.sendToPlayersNearTileEntity(t) } -} \ No newline at end of file +}