Made wrenching an Adapter's side turn it off.

For #1851.
No texture changes yet, but client sync is in place.
This commit is contained in:
Vexatos 2016-07-09 17:48:41 +02:00
parent 1fdd30ae72
commit c4fa6f157e
7 changed files with 122 additions and 27 deletions

View File

@ -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)) {

View File

@ -4,6 +4,7 @@ object PacketType extends Enumeration {
val
// Server -> Client
AbstractBusState,
AdapterState,
Analyze,
ChargerState,
ClientLog,

View File

@ -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,

View File

@ -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) {

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)