diff --git a/assets/blocks.psd b/assets/blocks.psd index e1c7f8ea9..6c585ac8e 100644 Binary files a/assets/blocks.psd and b/assets/blocks.psd differ diff --git a/src/main/resources/assets/opencomputers/doc/en_US/block/index.md b/src/main/resources/assets/opencomputers/doc/en_US/block/index.md index 1275d7a48..4aed941c8 100644 --- a/src/main/resources/assets/opencomputers/doc/en_US/block/index.md +++ b/src/main/resources/assets/opencomputers/doc/en_US/block/index.md @@ -23,7 +23,6 @@ Keep in mind that some of these may not be available, depending on the recipe se ### Extensions * [Adapter](adapter.md) -* [Cable](cable.md) * [Geolyzer](geolyzer.md) * [Motion Sensor](motionSensor.md) * [Redstone I/O](redstone.md) @@ -38,6 +37,8 @@ Keep in mind that some of these may not be available, depending on the recipe se ## Networking * [Access Point](accessPoint.md) +* [Cable](cable.md) +* [Net Splitter](toggleThinger.md) * [Switch](switch.md) ## Power management diff --git a/src/main/resources/assets/opencomputers/doc/en_US/block/toggleThinger.md b/src/main/resources/assets/opencomputers/doc/en_US/block/toggleThinger.md new file mode 100644 index 000000000..91c418962 --- /dev/null +++ b/src/main/resources/assets/opencomputers/doc/en_US/block/toggleThinger.md @@ -0,0 +1,7 @@ +# Net Splitter + +![*.net *.split](oredict:oc:toggleThinger) + +The net splitter is a device that allows controlling connectivity between subnetworks. Unlike the [switch](switch.md) or [power converter](powerConverter.md) it directly connects adjacent subnetworks, i.e. components can be accessed. Each side's connectivity can be toggled using a wrench (e.g. the [scrench](../item/wrench.md)). When a redstone signal is applied to the net splitter, all sides' connectivity is inverted. + +This block can therefore be used to toggle connectivity to certain parts of a component network. Use a [redstone I/O block](redstone.md) or [redstone cards](../item/redstoneCard1.md) to automate the net splitter. diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index c3c8ed87e..ddee8cb38 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -36,6 +36,7 @@ tile.oc.screen2.name=Screen (Tier 2) tile.oc.screen3.name=Screen (Tier 3) tile.oc.serverRack.name=Server Rack tile.oc.switch.name=Switch +tile.oc.toggleThinger.name=Net Splitter tile.oc.waypoint.name=Waypoint # Items @@ -331,6 +332,7 @@ oc:tooltip.TabletCase=Basic case for tablets. Place it into the assembler to add oc:tooltip.Terminal=Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it. oc:tooltip.TexturePicker=This tool allows showing a string describing a block's surface, for use in 3D printer shape definitions. Totally not texture names, nope. No sir. oc:tooltip.Tier=§8Tier %s +oc:tooltip.ToggleThinger=Acts as a dynamic connector. Connectivity of each side can be toggled by hitting it with a wrench. Connectivity of all sides can be inverted by applying a redstone signal. oc:tooltip.TooLong=Hold [§f%s§7] for a detailed tooltip. oc:tooltip.Transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job. oc:tooltip.UpgradeAngel=Allows robots to place blocks in thin air, even if there is no point of reference. diff --git a/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerOn.png b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerOn.png new file mode 100644 index 000000000..9c61d7643 Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerOn.png differ diff --git a/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerSide.png b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerSide.png new file mode 100644 index 000000000..fcf2787f0 Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerSide.png differ diff --git a/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerTop.png b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerTop.png new file mode 100644 index 000000000..d2dc29f3e Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/blocks/ToggleThingerTop.png differ diff --git a/src/main/scala/li/cil/oc/Constants.scala b/src/main/scala/li/cil/oc/Constants.scala index 1b52ce623..d65482adc 100644 --- a/src/main/scala/li/cil/oc/Constants.scala +++ b/src/main/scala/li/cil/oc/Constants.scala @@ -38,6 +38,7 @@ object Constants { final val ScreenTier3 = "screen3" final val ServerRack = "serverRack" final val Switch = "switch" + final val ToggleThinger = "toggleThinger" final val Waypoint = "waypoint" def Case(tier: Int) = ItemUtils.caseNameWithTierSuffix("case", tier) diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala index d79c1db60..b9b514010 100644 --- a/src/main/scala/li/cil/oc/client/PacketHandler.scala +++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala @@ -74,6 +74,7 @@ object PacketHandler extends CommonPacketHandler { case PacketType.TextBufferInit => onTextBufferInit(p) case PacketType.TextBufferPowerChange => onTextBufferPowerChange(p) case PacketType.TextBufferMulti => onTextBufferMulti(p) + case PacketType.ToggleThingerState => onToggleThingerState(p) case PacketType.ScreenTouchMode => onScreenTouchMode(p) case PacketType.ServerPresence => onServerPresence(p) case PacketType.Sound => onSound(p) @@ -591,6 +592,15 @@ object PacketHandler extends CommonPacketHandler { buffer.rawSetForeground(col, row, color) } + def onToggleThingerState(p: PacketParser) = + p.readTileEntity[ToggleThinger]() match { + case Some(t) => + t.isInverted = p.readBoolean() + t.openSides = t.uncompressSides(p.readByte()) + t.world.markBlockForUpdate(t.x, t.y, t.z) + case _ => // Invalid packet. + } + def onScreenTouchMode(p: PacketParser) = p.readTileEntity[Screen]() match { case Some(t) => t.invertTouchMode = p.readBoolean() diff --git a/src/main/scala/li/cil/oc/client/Proxy.scala b/src/main/scala/li/cil/oc/client/Proxy.scala index 9d8ecf086..6d61adb77 100644 --- a/src/main/scala/li/cil/oc/client/Proxy.scala +++ b/src/main/scala/li/cil/oc/client/Proxy.scala @@ -69,6 +69,7 @@ private[oc] class Proxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.AccessPoint], SwitchRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.RobotProxy], RobotRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer) + ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ToggleThinger], ToggleThingerRenderer) MinecraftForgeClient.registerItemRenderer(Items.get(Constants.ItemName.Floppy).createItemStack(1).getItem, ItemRenderer) MinecraftForgeClient.registerItemRenderer(Items.get(Constants.BlockName.Print).createItemStack(1).getItem, ItemRenderer) diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala index 49b537d2d..8c8adaa77 100644 --- a/src/main/scala/li/cil/oc/client/Textures.scala +++ b/src/main/scala/li/cil/oc/client/Textures.scala @@ -97,6 +97,10 @@ object Textures { var iconSideActivity: IIcon = _ } + object ToggleThinger { + var iconOn: IIcon = _ + } + def init(tm: TextureManager) { tm.bindTexture(fontAntiAliased) tm.bindTexture(fontAliased) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala index 3cebc1142..90098f754 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala @@ -60,6 +60,13 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { RobotRenderer.renderChassis() RenderState.checkError(getClass.getName + ".renderInventoryBlock: robot") + case toggle: ToggleThinger => + GL11.glTranslatef(-0.5f, -0.5f, -0.5f) + Tessellator.instance.startDrawingQuads() + ToggleThinger.render(block, metadata, renderer) + Tessellator.instance.draw() + + RenderState.checkError(getClass.getName + ".renderInventoryBlock: toggleThinger") case _ => block match { case simple: SimpleBlock => @@ -131,6 +138,12 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { RenderState.checkError(getClass.getName + ".renderWorldBlock: rack") + true + case toggle: tileentity.ToggleThinger => + ToggleThinger.render(ForgeDirection.VALID_DIRECTIONS.map(toggle.isSideOpen), block, x, y, z, renderer) + + RenderState.checkError(getClass.getName + ".renderWorldBlock: toggleThinger") + true case _ => val result = renderer.renderStandardBlock(block, x, y, z) @@ -144,7 +157,8 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { private def needsFlipping(block: Block) = block.isInstanceOf[Hologram] || block.isInstanceOf[Printer] || - block.isInstanceOf[Print] + block.isInstanceOf[Print] || + block.isInstanceOf[ToggleThinger] // The texture flip this works around only seems to occur for blocks with custom block renderers? def patchedRenderer(renderer: RenderBlocks, block: Block) = diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ToggleThinger.scala b/src/main/scala/li/cil/oc/client/renderer/block/ToggleThinger.scala new file mode 100644 index 000000000..4b783af5c --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/ToggleThinger.scala @@ -0,0 +1,120 @@ +package li.cil.oc.client.renderer.block + +import net.minecraft.block.Block +import net.minecraft.client.renderer.RenderBlocks +import net.minecraftforge.common.util.ForgeDirection + +object ToggleThinger { + def render(openSides: Array[Boolean], block: Block, x: Int, y: Int, z: Int, renderer: RenderBlocks) { + val previousRenderAllFaces = renderer.renderAllFaces + renderer.renderAllFaces = true + + // Bottom. + renderer.setRenderBounds(0 / 16f, 0 / 16f, 5 / 16f, 5 / 16f, 5 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 5 / 16f, 16 / 16f, 5 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(5 / 16f, 0 / 16f, 0 / 16f, 11 / 16f, 5 / 16f, 5 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(5 / 16f, 0 / 16f, 11 / 16f, 11 / 16f, 5 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + // Corners. + renderer.setRenderBounds(0 / 16f, 0 / 16f, 0 / 16f, 5 / 16f, 16 / 16f, 5 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 5 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(0 / 16f, 0 / 16f, 11 / 16f, 5 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 11 / 16f, 16 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + // Top. + renderer.setRenderBounds(0 / 16f, 11 / 16f, 5 / 16f, 5 / 16f, 16 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(11 / 16f, 11 / 16f, 5 / 16f, 16 / 16f, 16 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 0 / 16f, 11 / 16f, 16 / 16f, 5 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 11 / 16f, 11 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + // Sides. + val down = openSides(ForgeDirection.DOWN.ordinal()) + renderer.setRenderBounds(5 / 16f, if (down) 0 / 16f else 2 / 16f, 5 / 16f, 11 / 16f, 5 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + val up = openSides(ForgeDirection.UP.ordinal()) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 5 / 16f, 11 / 16f, if (up) 16 / 16f else 14f / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + val north = openSides(ForgeDirection.NORTH.ordinal()) + renderer.setRenderBounds(5 / 16f, 5 / 16f, if (north) 0 / 16f else 2 / 16f, 11 / 16f, 11 / 16f, 5 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + val south = openSides(ForgeDirection.SOUTH.ordinal()) + renderer.setRenderBounds(5 / 16f, 5 / 16f, 11 / 16f, 11 / 16f, 11 / 16f, if (south) 16 / 16f else 14 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + val west = openSides(ForgeDirection.WEST.ordinal()) + renderer.setRenderBounds(if (west) 0 / 16f else 2 / 16f, 5 / 16f, 5 / 16f, 5 / 16f, 11 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + val east = openSides(ForgeDirection.EAST.ordinal()) + renderer.setRenderBounds(11 / 16f, 5 / 16f, 5 / 16f, if (east) 16 / 16f else 14 / 16f, 11 / 16f, 11 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + renderer.renderAllFaces = previousRenderAllFaces + } + + def render(block: Block, metadata: Int, renderer: RenderBlocks) { + // Bottom. + renderer.setRenderBounds(0 / 16f, 0 / 16f, 5 / 16f, 5 / 16f, 5 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 5 / 16f, 16 / 16f, 5 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 0 / 16f, 0 / 16f, 11 / 16f, 5 / 16f, 5 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 0 / 16f, 11 / 16f, 11 / 16f, 5 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + // Corners. + renderer.setRenderBounds(0 / 16f, 0 / 16f, 0 / 16f, 5 / 16f, 16 / 16f, 5 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 5 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(0 / 16f, 0 / 16f, 11 / 16f, 5 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(11 / 16f, 0 / 16f, 11 / 16f, 16 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + // Top. + renderer.setRenderBounds(0 / 16f, 11 / 16f, 5 / 16f, 5 / 16f, 16 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(11 / 16f, 11 / 16f, 5 / 16f, 16 / 16f, 16 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 0 / 16f, 11 / 16f, 16 / 16f, 5 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 11 / 16f, 11 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + + // Sides. + renderer.setRenderBounds(5 / 16f, 2 / 16f, 5 / 16f, 11 / 16f, 5 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 11 / 16f, 5 / 16f, 11 / 16f, 14 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 5 / 16f, 2 / 16f, 11 / 16f, 11 / 16f, 5 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(5 / 16f, 5 / 16f, 11 / 16f, 11 / 16f, 11 / 16f, 14 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(2 / 16f, 5 / 16f, 5 / 16f, 5 / 16f, 11 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(11 / 16f, 5 / 16f, 5 / 16f, 14 / 16f, 11 / 16f, 11 / 16f) + renderAllFaces(block, metadata, renderer) + } + + private def renderAllFaces(block: Block, metadata: Int, renderer: RenderBlocks): Unit = { + BlockRenderer.renderFaceYPos(block, metadata, renderer) + BlockRenderer.renderFaceYNeg(block, metadata, renderer) + BlockRenderer.renderFaceXPos(block, metadata, renderer) + BlockRenderer.renderFaceXNeg(block, metadata, renderer) + BlockRenderer.renderFaceZPos(block, metadata, renderer) + BlockRenderer.renderFaceZNeg(block, metadata, renderer) + } +} diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/ToggleThingerRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/ToggleThingerRenderer.scala new file mode 100644 index 000000000..5b919f433 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/ToggleThingerRenderer.scala @@ -0,0 +1,88 @@ +package li.cil.oc.client.renderer.tileentity + +import li.cil.oc.client.Textures +import li.cil.oc.common.tileentity +import li.cil.oc.util.RenderState +import net.minecraft.client.renderer.Tessellator +import net.minecraft.client.renderer.texture.TextureMap +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer +import net.minecraft.tileentity.TileEntity +import net.minecraftforge.common.util.ForgeDirection +import org.lwjgl.opengl.GL11 + +object ToggleThingerRenderer extends TileEntitySpecialRenderer { + override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) { + RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)") + + val toggleThinger = tileEntity.asInstanceOf[tileentity.ToggleThinger] + if (toggleThinger.openSides.contains(!toggleThinger.isInverted)) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) + + RenderState.disableLighting() + RenderState.makeItBlend() + + GL11.glPushMatrix() + + GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5) + GL11.glScaled(1.0025, -1.0025, 1.0025) + GL11.glTranslatef(-0.5f, -0.5f, -0.5f) + + bindTexture(TextureMap.locationBlocksTexture) + val t = Tessellator.instance + t.startDrawingQuads() + + val sideActivity = Textures.ToggleThinger.iconOn + + if (toggleThinger.isSideOpen(ForgeDirection.DOWN)) { + t.addVertexWithUV(0, 1, 0, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(1, 1, 0, sideActivity.getMinU, sideActivity.getMinV) + t.addVertexWithUV(1, 1, 1, sideActivity.getMinU, sideActivity.getMaxV) + t.addVertexWithUV(0, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV) + } + + if (toggleThinger.isSideOpen(ForgeDirection.UP)) { + t.addVertexWithUV(0, 0, 0, sideActivity.getMaxU, sideActivity.getMaxV) + t.addVertexWithUV(0, 0, 1, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(1, 0, 1, sideActivity.getMinU, sideActivity.getMinV) + t.addVertexWithUV(1, 0, 0, sideActivity.getMinU, sideActivity.getMaxV) + } + + if (toggleThinger.isSideOpen(ForgeDirection.NORTH)) { + t.addVertexWithUV(1, 1, 0, sideActivity.getMinU, sideActivity.getMaxV) + t.addVertexWithUV(0, 1, 0, sideActivity.getMaxU, sideActivity.getMaxV) + t.addVertexWithUV(0, 0, 0, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(1, 0, 0, sideActivity.getMinU, sideActivity.getMinV) + } + + if (toggleThinger.isSideOpen(ForgeDirection.SOUTH)) { + t.addVertexWithUV(0, 1, 1, sideActivity.getMinU, sideActivity.getMaxV) + t.addVertexWithUV(1, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV) + t.addVertexWithUV(1, 0, 1, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(0, 0, 1, sideActivity.getMinU, sideActivity.getMinV) + } + + if (toggleThinger.isSideOpen(ForgeDirection.WEST)) { + t.addVertexWithUV(0, 1, 0, sideActivity.getMinU, sideActivity.getMaxV) + t.addVertexWithUV(0, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV) + t.addVertexWithUV(0, 0, 1, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(0, 0, 0, sideActivity.getMinU, sideActivity.getMinV) + } + + if (toggleThinger.isSideOpen(ForgeDirection.EAST)) { + t.addVertexWithUV(1, 1, 1, sideActivity.getMinU, sideActivity.getMaxV) + t.addVertexWithUV(1, 1, 0, sideActivity.getMaxU, sideActivity.getMaxV) + t.addVertexWithUV(1, 0, 0, sideActivity.getMaxU, sideActivity.getMinV) + t.addVertexWithUV(1, 0, 1, sideActivity.getMinU, sideActivity.getMinV) + } + + t.draw() + + RenderState.enableLighting() + + GL11.glPopMatrix() + GL11.glPopAttrib() + } + + RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving") + } +} diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index b6eb1c0d4..2d90662f0 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -50,6 +50,7 @@ object PacketType extends Enumeration { TextBufferMultiRawSetBackground, TextBufferMultiRawSetForeground, TextBufferPowerChange, + ToggleThingerState, ScreenTouchMode, ServerPresence, Sound, diff --git a/src/main/scala/li/cil/oc/common/block/ToggleThinger.scala b/src/main/scala/li/cil/oc/common/block/ToggleThinger.scala new file mode 100644 index 000000000..fa66fba1f --- /dev/null +++ b/src/main/scala/li/cil/oc/common/block/ToggleThinger.scala @@ -0,0 +1,55 @@ +package li.cil.oc.common.block + +import cpw.mods.fml.relauncher.Side +import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.Settings +import li.cil.oc.client.Textures +import li.cil.oc.common.tileentity +import li.cil.oc.integration.util.Wrench +import li.cil.oc.util.BlockPosition +import net.minecraft.client.renderer.texture.IIconRegister +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.world.IBlockAccess +import net.minecraft.world.World +import net.minecraftforge.common.util.ForgeDirection + +class ToggleThinger extends RedstoneAware { + override protected def customTextures = Array( + Some("ToggleThingerTop"), + Some("ToggleThingerTop"), + Some("ToggleThingerSide"), + Some("ToggleThingerSide"), + Some("ToggleThingerSide"), + Some("ToggleThingerSide") + ) + + @SideOnly(Side.CLIENT) override + def registerBlockIcons(iconRegister: IIconRegister): Unit = { + super.registerBlockIcons(iconRegister) + Textures.ToggleThinger.iconOn = iconRegister.registerIcon(Settings.resourceDomain + ":ToggleThingerOn") + } + + override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection): Boolean = false + + // ----------------------------------------------------------------------- // + + override def createTileEntity(world: World, metadata: Int) = new tileentity.ToggleThinger() + + // ----------------------------------------------------------------------- // + + 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 toggleThinger: tileentity.ToggleThinger => + if (!world.isRemote) { + val oldValue = toggleThinger.openSides(sideToToggle.ordinal()) + toggleThinger.setSideOpen(sideToToggle, !oldValue) + } + true + case _ => false + } + } + else super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ) + } +} diff --git a/src/main/scala/li/cil/oc/common/init/Blocks.scala b/src/main/scala/li/cil/oc/common/init/Blocks.scala index fd5161737..5c86471d7 100644 --- a/src/main/scala/li/cil/oc/common/init/Blocks.scala +++ b/src/main/scala/li/cil/oc/common/init/Blocks.scala @@ -34,6 +34,7 @@ object Blocks { GameRegistry.registerTileEntity(classOf[tileentity.Switch], Settings.namespace + "switch") GameRegistry.registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen") GameRegistry.registerTileEntity(classOf[tileentity.ServerRack], Settings.namespace + "serverRack") + GameRegistry.registerTileEntity(classOf[tileentity.ToggleThinger], Settings.namespace + "toggleThinger") GameRegistry.registerTileEntity(classOf[tileentity.Waypoint], Settings.namespace + "waypoint") Recipes.addBlock(new AccessPoint(), Constants.BlockName.AccessPoint, "oc:accessPoint") @@ -75,5 +76,8 @@ object Blocks { // v1.5.10 Recipes.addBlock(new FakeEndstone(), Constants.BlockName.Endstone, "oc:stoneEndstone") + + // v1.5.14 + Recipes.addBlock(new ToggleThinger(), Constants.BlockName.ToggleThinger, "oc:toggleThinger") } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/ToggleThinger.scala b/src/main/scala/li/cil/oc/common/tileentity/ToggleThinger.scala new file mode 100644 index 000000000..312a0d3c2 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/ToggleThinger.scala @@ -0,0 +1,102 @@ +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 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 ToggleThinger extends traits.Environment with traits.RedstoneAware with api.network.SidedEnvironment { + private final val SideCount = ForgeDirection.VALID_DIRECTIONS.length + + val node = api.Network.newNode(this, Visibility.None). + create() + + var isInverted = false + + var openSides = Array.fill(SideCount)(false) + + 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 + if (isServer) { + node.remove() + api.Network.joinOrCreateNetwork(this) + ServerPacketSender.sendToggleThingerState(this) + } + else { + world.markBlockForUpdate(x, y, z) + } + } + + // ----------------------------------------------------------------------- // + + override def sidedNode(side: ForgeDirection) = if (isSideOpen(side)) node else null + + @SideOnly(Side.CLIENT) + override def canConnect(side: ForgeDirection) = isSideOpen(side) + + // ----------------------------------------------------------------------- // + + override def canUpdate = false + + override protected def initialize(): Unit = { + super.initialize() + EventHandler.schedule(this) + } + + // ----------------------------------------------------------------------- // + + override protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int): Unit = { + super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue) + val oldIsInverted = isInverted + isInverted = newMaxValue > 0 + if (isInverted != oldIsInverted) { + if (isServer) { + node.remove() + api.Network.joinOrCreateNetwork(this) + ServerPacketSender.sendToggleThingerState(this) + } + else { + world.markBlockForUpdate(x, y, z) + } + } + } + + 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/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index 7847db5e3..92ccccd86 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -529,6 +529,16 @@ object PacketSender { pb.sendToPlayersNearHost(host) } + def sendToggleThingerState(t: tileentity.ToggleThinger): Unit = { + val pb = new SimplePacketBuilder(PacketType.ToggleThingerState) + + pb.writeTileEntity(t) + pb.writeBoolean(t.isInverted) + pb.writeByte(t.compressSides) + + pb.sendToPlayersNearTileEntity(t) + } + def sendScreenTouchMode(t: tileentity.Screen, value: Boolean) { val pb = new SimplePacketBuilder(PacketType.ScreenTouchMode)