From 6e13f6d9b40fc3b544e5cff03e904dd6a73c4f87 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 01/21] Buggy implementation of rotate and configure --- .../projectred/fabrication/gatepart.scala | 7 +- .../projectred/fabrication/gaterenders.scala | 126 +++++++++--------- .../fabrication/guiicworkbench.scala | 24 +++- .../mrtjp/projectred/fabrication/ic.scala | 4 +- .../mrtjp/projectred/fabrication/op.scala | 8 ++ .../projectred/fabrication/opgates.scala | 26 ++-- .../projectred/fabrication/oputils.scala | 4 + .../projectred/fabrication/opwires.scala | 4 + 8 files changed, 122 insertions(+), 81 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala b/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala index ddaa333c9..923672fb0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala @@ -31,9 +31,10 @@ abstract class GateICPart def shape = gateShape & 0xff def setShape(s: Int) { gateShape = s.toByte } - def preparePlacement(rot: Int, meta: Int) { + def preparePlacement(rot: Int, configuration: Int, meta: Int) { gateSubID = meta.toByte setRotation(rot) + gateShape = configuration.toByte } override def save(tag: NBTTagCompound) { @@ -265,8 +266,8 @@ trait TComplexGateICPart extends GateICPart { case _ => super.read(packet, key) } - abstract override def preparePlacement(rot: Int, meta: Int) { - super.preparePlacement(rot, meta) + abstract override def preparePlacement(rotation: Int, configuration: Int, meta: Int) { + super.preparePlacement(rotation, configuration, meta) assertLogic() } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala b/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala index c7279f3d7..e2bd88417 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala @@ -59,9 +59,15 @@ object RenderICGate { r.renderDynamic(gate.rotationT `with` t, ortho) } + def renderWithConfiguration(configuration: Int, t: Transformation, id: Int): Unit = { + val r = renderers(id) + r.prepareStatic(configuration) + r.renderDynamic(t, true) + } + def renderInv(t: Transformation, id: Int) { val r = renderers(id) - r.prepareInv() + r.prepareStatic(0) r.renderDynamic(t, true) } } @@ -72,7 +78,7 @@ abstract class ICGateRenderer[T <: GateICPart] { def coreModels: Seq[ICComponentModel] def switchModels = Seq[ICComponentModel]() - def prepareInv() {} + def prepareStatic(configuration: Int) def prepareDynamic(gate: T, frame: Float) {} def renderDynamic(t: Transformation, ortho: Boolean) { @@ -93,7 +99,7 @@ abstract class RenderIO extends ICGateRenderer[IOGateICPart] { override val coreModels = Seq(new BaseComponentModel("IOSIMP")) ++ wires :+ iosig - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false iosig.on = false iosig.colour = invColour @@ -138,14 +144,14 @@ class RenderOR extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("OR")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false wires(3).on = false - wires(1).disabled = false - wires(2).disabled = false - wires(3).disabled = false + wires(1).disabled = (configuration & 1) != 0 + wires(2).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 torches(0).on = true torches(1).on = false } @@ -169,14 +175,14 @@ class RenderNOR extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("NOR")) ++ wires :+ torch - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false wires(3).on = false - wires(1).disabled = false - wires(2).disabled = false - wires(3).disabled = false + wires(1).disabled = (configuration & 1) != 0 + wires(2).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 torch.on = true } @@ -198,14 +204,14 @@ class RenderNOT extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("NOT")) ++ wires :+ torch - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = true wires(2).on = false wires(3).on = true - wires(0).disabled = false - wires(1).disabled = false - wires(3).disabled = false + wires(0).disabled = (configuration & 2) != 0 + wires(1).disabled = (configuration & 1) != 0 + wires(3).disabled = (configuration & 4) != 0 torch.on = true } @@ -233,17 +239,17 @@ class RenderAND extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("AND")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false wires(3).on = false - wires(1).disabled = false - wires(2).disabled = false - wires(3).disabled = false - torches(0).on = true - torches(1).on = true - torches(2).on = true + wires(3).disabled = (configuration & 1) != 0 + wires(1).disabled = (configuration & 2) != 0 + wires(2).disabled = (configuration & 4) != 0 + torches(2).on = !wires(1).on && !wires(1).disabled + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled torches(3).on = false } @@ -273,17 +279,17 @@ class RenderNAND extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("NAND")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false wires(3).on = false - wires(1).disabled = false - wires(2).disabled = false - wires(3).disabled = false - torches(0).on = true - torches(1).on = true - torches(2).on = true + wires(3).disabled = (configuration & 1) != 0 + wires(1).disabled = (configuration & 2) != 0 + wires(2).disabled = (configuration & 4) != 0 + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled + torches(2).on = !wires(1).on && !wires(1).disabled } override def prepareDynamic(gate: ComboGateICPart, frame: Float) { @@ -311,7 +317,7 @@ class RenderXOR extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("XOR")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(3).on = false wires(2).on = false @@ -344,7 +350,7 @@ class RenderXNOR extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("XNOR")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(3).on = false wires(2).on = false @@ -376,13 +382,13 @@ class RenderBuffer extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("BUFFER")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false wires(3).on = false - wires(1).disabled = false - wires(3).disabled = false + wires(1).disabled = (configuration & 1) != 0 + wires(3).disabled = (configuration & 2) != 0 torches(0).on = false torches(1).on = true } @@ -411,7 +417,7 @@ class RenderMultiplexer extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("MULTIPLEXER")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(1).on = true wires(2).on = true @@ -449,7 +455,7 @@ class RenderPulse extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("PULSE")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false wires(2).on = false @@ -490,11 +496,11 @@ class RenderRepeater extends ICGateRenderer[ComboGateICPart] { override def switchModels = Seq(varTorches(shape)) - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = false endTorch.on = false - shape = 0 + shape = configuration % 8 varTorches(0).on = true } @@ -502,7 +508,7 @@ class RenderRepeater extends ICGateRenderer[ComboGateICPart] { wires(0).on = (gate.state & 0x10) == 0 wires(1).on = (gate.state & 4) != 0 endTorch.on = (gate.state & 0x10) != 0 - shape = gate.shape + shape = gate.shape % 8 varTorches(shape).on = (gate.state & 4) == 0 } } @@ -518,7 +524,7 @@ class RenderRandomizer extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("RAND")) ++ wires ++ chips - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(1).on = false wires(2).on = false @@ -526,12 +532,12 @@ class RenderRandomizer extends ICGateRenderer[ComboGateICPart] { wires(4).on = false wires(5).on = false wires(6).on = false - wires(0).disabled = false - wires(1).disabled = false - wires(3).disabled = false - wires(4).disabled = false - wires(5).disabled = false - wires(6).disabled = false + wires(1).disabled = (configuration & 1) != 0 + wires(0).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 + wires(5).disabled = wires(1).disabled + wires(4).disabled = wires(0).disabled + wires(6).disabled = wires(3).disabled chips(0).on = false chips(1).on = false chips(2).on = false @@ -575,7 +581,7 @@ class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq() override def switchModels = if (shape == 0) m1 else m2 - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { reflect = false shape = 0 wires1(0).on = false @@ -613,7 +619,7 @@ class RenderToggleLatch extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq(new BaseComponentModel("TOGLATCH")) ++ wires ++ torches :+ lever - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(1).on = false torches(0).on = true @@ -643,7 +649,7 @@ class RenderTransparentLatch extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("TRANSLATCH")) ++ wires ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { reflect = false wires(0).on = true wires(1).on = false @@ -681,7 +687,7 @@ class RenderTimer extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq(new BaseComponentModel("TIME")) ++ wires ++ Seq(pointer) ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(1).on = false wires(2).on = false @@ -715,7 +721,7 @@ class RenderSequencer extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq(new BaseComponentModel("SEQUENCER"), pointer) ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { torches(1).on = true torches(2).on = false torches(3).on = false @@ -752,7 +758,7 @@ class RenderCounter extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq(new BaseComponentModel("COUNT")) ++ wires ++ Seq(pointer) ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { reflect = false wires(0).on = false wires(1).on = false @@ -787,7 +793,7 @@ class RenderStateCell extends ICGateRenderer[SequentialGateICPart] { new BaseComponentModel("STATECELL") ) ++ wires ++ Seq(chip, pointer) ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { reflect = false wires(0).on = false wires(1).on = false @@ -829,7 +835,7 @@ class RenderSynchronizer extends ICGateRenderer[SequentialGateICPart] { override val coreModels = Seq(new BaseComponentModel("SYNC")) ++ wires ++ chips ++ Seq(torch) - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = true wires(1).on = true wires(2).on = false @@ -872,15 +878,15 @@ class RenderDecRandomizer extends ICGateRenderer[ComboGateICPart] { override val coreModels = Seq(new BaseComponentModel("DECRAND")) ++ wires ++ chips ++ torches - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { wires(0).on = false wires(1).on = false wires(2).on = false wires(3).on = false wires(4).on = true wires(5).on = true - wires(0).disabled = false - wires(3).disabled = false + wires(0).disabled = configuration != 0 + wires(3).disabled = configuration != 0 torches(0).on = true torches(1).on = false torches(2).on = false @@ -917,7 +923,7 @@ class RenderNullCell extends ICGateRenderer[ArrayGateICPart] { override val coreModels = Seq(new BaseComponentModel("NULLCELL"), bottom, new CellStandModel, top) - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { bottom.signal = 0 top.signal = 0 } @@ -938,7 +944,7 @@ class RenderInvertCell extends ICGateRenderer[ArrayGateICPart] { new BaseComponentModel("INVCELL") ) ++ wires ++ Seq(bottom, torch, new CellStandModel, top) - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { bottom.signal = 0 top.signal = 255.toByte wires(0).on = false @@ -966,7 +972,7 @@ class RenderBufferCell extends ICGateRenderer[ArrayGateICPart] { bottom ) ++ torches ++ Seq(new CellStandModel, top) - override def prepareInv() { + override def prepareStatic(configuration: Int): Unit = { bottom.signal = 0 top.signal = 0 wires(0).on = false diff --git a/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala index 47642fbfa..94ed1a33b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala @@ -31,6 +31,8 @@ import scala.collection.immutable.ListMap class PrefboardNode(circuit: IntegratedCircuit) extends TNode { var currentOp: CircuitOp = null + var currentOpRotation: Int = 0 + var currentOpConfiguration: Int = 0 /** 0 - off 1 - name only 2 - minor details 3 - all details */ @@ -87,16 +89,18 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { ) if (currentOp != null) { - if (frame.contains(mouse) && rayTest(mouse) && !leftMouseDown) + if (frame.contains(mouse) && rayTest(mouse) && !leftMouseDown) { currentOp.renderHover( circuit, toGridPoint(mouse), + currentOpRotation, + currentOpConfiguration, f.x, f.y, size.width * scale, size.height * scale ) - else if (leftMouseDown) + } else if (leftMouseDown) currentOp.renderDrag( circuit, mouseStart, @@ -209,7 +213,7 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { leftMouseDown = false val mouseEnd = toGridPoint(p) val opUsed = - currentOp != null && circuit.sendOpUse(currentOp, mouseStart, mouseEnd) + currentOp != null && circuit.sendOpUse(currentOp, currentOpRotation, currentOpConfiguration, mouseStart, mouseEnd) if (!opUsed && mouseEnd == mouseStart) { val part = circuit.getPart(mouseEnd) if (part != null) part.onClicked() @@ -243,9 +247,16 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { case KEY_ESCAPE if currentOp != null => opPickDelegate(null) true - case _ if keycode == mcInst.gameSettings.keyBindPickBlock.getKeyCode => + case KEY_Q => doPickOp() true + case KEY_R if currentOp != null => + currentOpRotation += 1 + if (currentOpRotation == 4) currentOpRotation = 0 + true + case KEY_C if currentOp != null => + currentOpConfiguration += 1 + true case _ if keycode == mcInst.gameSettings.keyBindInventory.getKeyCode => opPickDelegate(CircuitOpDefs.Erase.getOp) true @@ -649,7 +660,10 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolset.title = name toolset.opSet = opset.map(_.getOp) toolset.setup() - toolset.opSelectDelegate = { op => pref.currentOp = op } + toolset.opSelectDelegate = { op => + pref.currentOp = op + pref.currentOpConfiguration = 0 + } toolbar.addChild(toolset) toolSets :+= toolset } diff --git a/src/main/scala/mrtjp/projectred/fabrication/ic.scala b/src/main/scala/mrtjp/projectred/fabrication/ic.scala index 6c72dcde8..8cc011101 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/ic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ic.scala @@ -277,9 +277,9 @@ class IntegratedCircuit { network.getICStreamOf(2).writeByte(x).writeByte(y) } - def sendOpUse(op: CircuitOp, start: Point, end: Point) = { + def sendOpUse(op: CircuitOp, rotation: Int, configuration: Int, start: Point, end: Point) = { if (op.checkOp(this, start, end)) { - op.writeOp(this, start, end, network.getICStreamOf(3).writeByte(op.id)) + op.writeOp(this, start, end, rotation, configuration, network.getICStreamOf(3).writeByte(op.id)) true } else false } diff --git a/src/main/scala/mrtjp/projectred/fabrication/op.scala b/src/main/scala/mrtjp/projectred/fabrication/op.scala index 99eea3676..57a2775ca 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/op.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/op.scala @@ -157,6 +157,8 @@ trait CircuitOp { circuit: IntegratedCircuit, start: Point, end: Point, + rotation: Int, + configuration: Int, out: MCDataOutput ) def readOp(circuit: IntegratedCircuit, in: MCDataInput) @@ -167,6 +169,8 @@ trait CircuitOp { def renderHover( circuit: IntegratedCircuit, point: Point, + rot: Int, + configuration: Int, x: Double, y: Double, xSize: Double, @@ -194,6 +198,8 @@ abstract class SimplePlacementOp extends CircuitOp { circuit: IntegratedCircuit, start: Point, end: Point, + rotation: Int, + configuration: Int, out: MCDataOutput ) { out.writeByte(end.x).writeByte(end.y) @@ -220,6 +226,8 @@ abstract class SimplePlacementOp extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, + rot: Int, + configuration: Int, x: Double, y: Double, xSize: Double, diff --git a/src/main/scala/mrtjp/projectred/fabrication/opgates.scala b/src/main/scala/mrtjp/projectred/fabrication/opgates.scala index 8b3b5af62..a571e6f6e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/opgates.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/opgates.scala @@ -13,6 +13,7 @@ import mrtjp.projectred.fabrication.CircuitOp._ import mrtjp.projectred.fabrication.ICComponentStore._ abstract class OpGateCommons(meta: Int) extends CircuitOp { + def canPlace(circuit: IntegratedCircuit, point: Point): Boolean def findRot(circuit: IntegratedCircuit, start: Point, end: Point): Int @@ -23,21 +24,25 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { circuit: IntegratedCircuit, start: Point, end: Point, + rotation: Int, + configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) - out.writeByte(findRot(circuit, start, end)) + out.writeByte(rotation) + out.writeByte(configuration) } override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { val point = Point(in.readByte(), in.readByte()) - val r = in.readUByte() + val rotation = in.readUByte() + val configuration = in.readUByte() if (circuit.getPart(point) == null && canPlace(circuit, point)) { val part = CircuitPart .createPart(ICGateDefinition(meta).gateType) .asInstanceOf[GateICPart] - part.preparePlacement(r, meta) + part.preparePlacement(rotation, configuration, meta) circuit.setPart(point, part) } } @@ -46,6 +51,8 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, + rot: Int, + configuration: Int, x: Double, y: Double, xSize: Double, @@ -54,7 +61,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { if (circuit.getPart(point) != null) return val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) - doRender(t, findRot(circuit, point, point)) + doRender(t, rot, configuration) renderHolo( x, @@ -80,7 +87,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { if (circuit.getPart(start) != null) return val t = orthoPartT(x, y, xSize, ySize, circuit.size, start.x, start.y) - doRender(t, findRot(circuit, start, end)) + doRender(t, findRot(circuit, start, end), 0) renderHolo( x, @@ -101,15 +108,12 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { height: Double ) { val t = orthoGridT(width, height) `with` new Translation(x, y, 0) - doRender(t, 0) + doRender(t, 0, 0) } @SideOnly(Side.CLIENT) - def doRender(t: Transformation, rot: Int) { - RenderICGate.renderInv( - Rotation.quarterRotations(rot).at(Vector3.center) `with` t, - meta - ) + def doRender(t: Transformation, rot: Int, configuration: Int) { + RenderICGate.renderWithConfiguration(configuration, Rotation.quarterRotations(rot).at(Vector3.center) `with` t, meta) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/mrtjp/projectred/fabrication/oputils.scala b/src/main/scala/mrtjp/projectred/fabrication/oputils.scala index c2d9d36ae..472fb8636 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/oputils.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/oputils.scala @@ -22,6 +22,8 @@ class CircuitOpErase extends CircuitOp { circuit: IntegratedCircuit, start: Point, end: Point, + rotation: Int, + configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) @@ -61,6 +63,8 @@ class CircuitOpErase extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, + rot: Int, + configuration: Int, x: Double, y: Double, xSize: Double, diff --git a/src/main/scala/mrtjp/projectred/fabrication/opwires.scala b/src/main/scala/mrtjp/projectred/fabrication/opwires.scala index 410a82da0..8bbd1c91f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/opwires.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/opwires.scala @@ -21,6 +21,8 @@ abstract class OpWire extends CircuitOp { circuit: IntegratedCircuit, start: Point, end: Point, + rotation: Int, + configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) @@ -45,6 +47,8 @@ abstract class OpWire extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, + rot: Int, + configuration: Int, x: Double, y: Double, xSize: Double, From 74cca35a42ef05f7a07f99b32779e4a6daf0f26f Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 02/21] Restructuring of the fabrication module --- ...fmpgatepart.scala => FMPCircuitGate.scala} | 5 +- .../{tileicprinter.scala => ICPrinter.scala} | 18 +- ...ileicworkbench.scala => ICWorkbench.scala} | 8 +- .../fabrication/IntegratedCircuit.scala | 302 ++++++ .../fabrication/{items.scala => Items.scala} | 12 +- .../{proxies.scala => Proxies.scala} | 2 +- .../fabrication/RenderCircuit.scala | 71 ++ .../projectred/fabrication/WorldCircuit.scala | 129 +++ .../circuitparts/ArrayGateICLogic.scala | 25 + .../ArrayGateICLogicCrossing.scala | 114 ++ .../circuitparts/ArrayGateICPart.scala | 22 + .../circuitparts/CircuitPart.scala | 100 ++ .../circuitparts/CircuitPartDefs.scala | 36 + .../circuitparts/ComboICGateLogic.scala | 63 ++ .../circuitparts/ComboICGatePart.scala | 14 + .../GateICPart.scala} | 158 +-- .../circuitparts/ICGateDefinition.scala | 67 ++ .../circuitparts/ICGateLogic.scala | 31 + .../circuitparts/ICGateRenderer.scala | 98 ++ .../circuitparts/IWireICPart.scala | 66 ++ .../RedstoneGateICPart.scala} | 45 +- .../circuitparts/RedstoneICGateLogic.scala | 32 + .../circuitparts/SequentialGateICPart.scala | 55 + .../circuitparts/SequentialICGateLogic.scala | 29 + .../circuitparts/TArrayGateICPart.scala | 119 +++ .../circuitparts/TArrayICGateLogic.scala | 38 + .../circuitparts/TClientNetCircuitPart.scala | 18 + .../circuitparts/TComplexGateICPart.scala | 49 + .../circuitparts/TComplexICGateLogic.scala | 23 + .../circuitparts/TConnectableICPart.scala | 43 + .../circuitparts/TErrorCircuitPart.scala | 10 + .../circuitparts/TExtraStateLogic.scala | 50 + .../circuitparts/TICAcquisitions.scala | 24 + .../circuitparts/TICBundledAcquisitions.scala | 20 + .../fabrication/circuitparts/TICOrient.scala | 38 + .../circuitparts/TICRSAcquisitions.scala | 13 + .../circuitparts/TPoweredCircuitPart.scala | 12 + .../circuitparts/TPropagatingICPart.scala | 49 + .../circuitparts/TRSPropagatingICPart.scala | 32 + .../circuitparts/TSimpleRSICGateLogic.scala | 67 ++ .../circuitparts/cells/BufferCell.scala | 48 + .../circuitparts/cells/InvertCell.scala | 42 + .../circuitparts/cells/NullCell.scala | 33 + .../circuitparts/io/AnalogIO.scala | 30 + .../circuitparts/io/BundledIO.scala | 31 + .../circuitparts/io/IOGateICPart.scala | 69 ++ .../circuitparts/io/IOICGateLogic.scala | 112 ++ .../circuitparts/io/RenderIO.scala | 34 + .../circuitparts/io/SimpleIO.scala | 45 + .../circuitparts/io/TFreqIOICGateLogic.scala | 82 ++ .../circuitparts/io/TIOCircuitPart.scala | 30 + .../circuitparts/io/TRSIOICGateLogic.scala | 23 + .../circuitparts/latches/SRLatch.scala | 149 +++ .../circuitparts/latches/ToggleLatch.scala | 83 ++ .../latches/TransparentLatch.scala | 67 ++ .../circuitparts/misc/Counter.scala | 208 ++++ .../circuitparts/misc/DecRandomizer.scala | 91 ++ .../circuitparts/misc/Randomizer.scala | 88 ++ .../circuitparts/misc/Synchronizer.scala | 103 ++ .../circuitparts/primitives/AND.scala | 62 ++ .../circuitparts/primitives/Buffer.scala | 55 + .../circuitparts/primitives/Multiplexer.scala | 80 ++ .../circuitparts/primitives/NAND.scala | 58 + .../circuitparts/primitives/NOR.scala | 51 + .../circuitparts/primitives/NOT.scala | 52 + .../circuitparts/primitives/OR.scala | 54 + .../circuitparts/primitives/XNOR.scala | 58 + .../circuitparts/primitives/XOR.scala | 54 + .../circuitparts/timing/Pulse.scala | 40 + .../circuitparts/timing/Repeater.scala | 80 ++ .../circuitparts/timing/Sequencer.scala | 131 +++ .../circuitparts/timing/StateCell.scala | 121 +++ .../circuitparts/timing/Timer.scala | 203 ++++ .../circuitparts/wire/AlloyWire.scala | 56 + .../wire/BundledCable.scala} | 58 +- .../wire/Button.scala} | 33 +- .../circuitparts/wire/InsulatedWire.scala | 113 ++ .../wire/Lever.scala} | 36 +- .../wire/RedstoneTorch.scala} | 23 +- .../circuitparts/wire/Redwire.scala | 113 ++ .../wire/Wire.scala} | 16 +- .../projectred/fabrication/components.scala | 10 +- .../fabrication/gatepartarray.scala | 282 ----- .../projectred/fabrication/gatepartcomb.scala | 334 ------ .../projectred/fabrication/gatepartio.scala | 325 ------ .../projectred/fabrication/gatepartseq.scala | 744 ------------- .../projectred/fabrication/gaterenders.scala | 993 ------------------ .../fabrication/gui/CircuitGui.scala | 108 ++ .../fabrication/gui/GuiICWorkbench.scala | 220 ++++ .../fabrication/gui/ICCounterGateGui.scala | 101 ++ .../fabrication/gui/ICGateGui.scala | 32 + .../fabrication/gui/ICIOFreqGateGui.scala | 77 ++ .../fabrication/gui/ICIOGateGui.scala | 43 + .../fabrication/gui/ICTimerGateGui.scala | 79 ++ .../fabrication/gui/PrefboardRenderer.scala | 114 ++ .../projectred/fabrication/gui/TGateGui.scala | 35 + .../fabrication/gui/nodes/ICToolsetNode.scala | 145 +++ .../fabrication/gui/nodes/InfoNode.scala | 56 + .../fabrication/gui/nodes/NewICNode.scala | 179 ++++ .../fabrication/gui/nodes/PrefboardNode.scala | 299 ++++++ .../mrtjp/projectred/fabrication/icguis.scala | 394 ------- .../projectred/fabrication/icrenders.scala | 309 ------ .../fabrication/operations/CircuitOp.scala | 92 ++ .../CircuitOpDefs.scala} | 174 +-- .../CircuitOpErase.scala} | 6 +- .../GateOps.scala} | 11 +- .../fabrication/operations/ICPartOps.scala | 47 + .../operations/SimplePlacementOp.scala | 107 ++ .../WireOps.scala} | 8 +- .../fabrication/partabstracts.scala | 158 --- .../projectred/fabrication/wirepartrs.scala | 182 ---- .../fabrication/wirepropagation.scala | 58 +- 112 files changed, 6537 insertions(+), 4207 deletions(-) rename src/main/scala/mrtjp/projectred/fabrication/{fmpgatepart.scala => FMPCircuitGate.scala} (98%) rename src/main/scala/mrtjp/projectred/fabrication/{tileicprinter.scala => ICPrinter.scala} (97%) rename src/main/scala/mrtjp/projectred/fabrication/{tileicworkbench.scala => ICWorkbench.scala} (98%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala rename src/main/scala/mrtjp/projectred/fabrication/{items.scala => Items.scala} (97%) rename src/main/scala/mrtjp/projectred/fabrication/{proxies.scala => Proxies.scala} (99%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala rename src/main/scala/mrtjp/projectred/fabrication/{gatepart.scala => circuitparts/GateICPart.scala} (50%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala rename src/main/scala/mrtjp/projectred/fabrication/{gatepartrs.scala => circuitparts/RedstoneGateICPart.scala} (60%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TClientNetCircuitPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TConnectableICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TErrorCircuitPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICAcquisitions.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICOrient.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICRSAcquisitions.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPoweredCircuitPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TRSPropagatingICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/RenderIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TRSIOICGateLogic.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala rename src/main/scala/mrtjp/projectred/fabrication/{wirepartbundled.scala => circuitparts/wire/BundledCable.scala} (80%) rename src/main/scala/mrtjp/projectred/fabrication/{buttonpart.scala => circuitparts/wire/Button.scala} (77%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala rename src/main/scala/mrtjp/projectred/fabrication/{leverpart.scala => circuitparts/wire/Lever.scala} (71%) rename src/main/scala/mrtjp/projectred/fabrication/{torchpart.scala => circuitparts/wire/RedstoneTorch.scala} (57%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala rename src/main/scala/mrtjp/projectred/fabrication/{wirepartabstracts.scala => circuitparts/wire/Wire.scala} (79%) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gatepartarray.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gatepartcomb.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gatepartio.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gatepartseq.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/icguis.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/icrenders.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala rename src/main/scala/mrtjp/projectred/fabrication/{op.scala => operations/CircuitOpDefs.scala} (52%) rename src/main/scala/mrtjp/projectred/fabrication/{oputils.scala => operations/CircuitOpErase.scala} (94%) rename src/main/scala/mrtjp/projectred/fabrication/{opgates.scala => operations/GateOps.scala} (88%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala rename src/main/scala/mrtjp/projectred/fabrication/{opwires.scala => operations/WireOps.scala} (93%) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/partabstracts.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/wirepartrs.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/fmpgatepart.scala b/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala similarity index 98% rename from src/main/scala/mrtjp/projectred/fabrication/fmpgatepart.scala rename to src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala index 8473b298f..d5bdb0c7c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/fmpgatepart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala @@ -10,7 +10,8 @@ import codechicken.lib.gui.GuiDraw import codechicken.lib.render.{CCRenderState, TextureUtils} import codechicken.lib.vec._ import mrtjp.core.math.MathLib -import mrtjp.projectred.fabrication.IIOCircuitPart._ +import mrtjp.projectred.fabrication.ItemICBlueprint.{getConnModes, getICName, hasICInside} +import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart.{Analog, Bundled, NoConn, Simple} import mrtjp.projectred.integration import mrtjp.projectred.integration._ import mrtjp.projectred.transmission.BundledCommons._ @@ -19,6 +20,7 @@ import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import org.lwjgl.opengl.GL11 + class CircuitGatePart extends RedstoneGatePart with TBundledGatePart @@ -296,7 +298,6 @@ class RenderCircuitGate extends GateRenderer[CircuitGatePart] { ) override def prepareInv(stack: ItemStack) { - import ItemICBlueprint._ if (hasICInside(stack)) { name = getICName(stack) val cm = getConnModes(stack) diff --git a/src/main/scala/mrtjp/projectred/fabrication/tileicprinter.scala b/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala similarity index 97% rename from src/main/scala/mrtjp/projectred/fabrication/tileicprinter.scala rename to src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala index 006672b06..2291c23b1 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/tileicprinter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala @@ -6,14 +6,9 @@ package mrtjp.projectred.fabrication import java.util.{ArrayList => JAList, List => JList} - import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.gui.GuiDraw -import codechicken.lib.render.uv.{ - IconTransformation, - MultiIconTransformation, - UVTransformation -} +import codechicken.lib.render.uv.{IconTransformation, MultiIconTransformation, UVTransformation} import codechicken.lib.render.{CCModel, CCRenderState, TextureUtils} import codechicken.lib.vec._ import cpw.mods.fml.relauncher.{Side, SideOnly} @@ -27,6 +22,8 @@ import mrtjp.core.world.WorldLib import mrtjp.projectred.ProjectRedCore.log import mrtjp.projectred.core.PartDefs import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.circuitparts.GateICPart +import mrtjp.projectred.fabrication.circuitparts.wire.{AlloyWireICPart, BundledCableICPart, ButtonICPart, InsulatedWireICPart, LeverICPart, TorchICPart} import mrtjp.projectred.integration.ComponentStore import mrtjp.projectred.transmission.WireDef import net.minecraft.client.renderer.RenderBlocks @@ -36,12 +33,7 @@ import net.minecraft.client.resources.I18n import net.minecraft.entity.player.EntityPlayer import net.minecraft.init.{Blocks, Items} import net.minecraft.item.ItemStack -import net.minecraft.item.crafting.{ - CraftingManager, - IRecipe, - ShapedRecipes, - ShapelessRecipes -} +import net.minecraft.item.crafting.{CraftingManager, IRecipe, ShapedRecipes, ShapelessRecipes} import net.minecraft.nbt.NBTTagCompound import net.minecraft.tileentity.TileEntity import net.minecraft.util.{IIcon, ResourceLocation} @@ -465,7 +457,7 @@ object TileICPrinter { getOrCacheComponents(stack).foreach(add(_, 0.25)) } - import mrtjp.projectred.fabrication.{ICGateDefinition => gd} + import mrtjp.projectred.fabrication.circuitparts.{ICGateDefinition => gd} for (part <- ic.parts.values) part match { case p: TorchICPart => add(new ItemStack(Blocks.redstone_torch), 0.25) diff --git a/src/main/scala/mrtjp/projectred/fabrication/tileicworkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala similarity index 98% rename from src/main/scala/mrtjp/projectred/fabrication/tileicworkbench.scala rename to src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala index c3ea71ab1..df7148cb3 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/tileicworkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala @@ -9,18 +9,14 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.packet.PacketCustom import codechicken.lib.render.uv.MultiIconTransformation import codechicken.lib.vec.{Rotation, Vector3} -import mrtjp.core.block.{ - InstancedBlock, - InstancedBlockTile, - TInstancedBlockRender, - TTileOrient -} +import mrtjp.core.block.{InstancedBlock, InstancedBlockTile, TInstancedBlockRender, TTileOrient} import mrtjp.core.gui.NodeContainer import mrtjp.core.render.TCubeMapRender import mrtjp.core.world.WorldLib import mrtjp.projectred.ProjectRedFabrication import mrtjp.projectred.api.IScrewdriver import mrtjp.projectred.fabrication.ItemICBlueprint._ +import mrtjp.projectred.fabrication.gui.GuiICWorkbench import net.minecraft.block.material.Material import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.entity.item.EntityItem diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala new file mode 100644 index 000000000..67533e58a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.ProjectRedCore.log +import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TErrorCircuitPart, TClientNetCircuitPart} +import mrtjp.projectred.fabrication.operations.CircuitOp +import net.minecraft.nbt.{NBTTagCompound, NBTTagList} + +import scala.collection.mutable.{Map => MMap} + +class IntegratedCircuit { + var network: WorldCircuit = null + + var name = "untitled" + var size = Size.zeroSize + + var parts = MMap[(Int, Int), CircuitPart]() + var errors = Map.empty[Point, (String, Int)] + + private var scheduledTicks = MMap[(Int, Int), Long]() + + /** Mapped inputs and outputs of this IC. Outputs go to the world, inputs come + * in from the world. OOOO OOOO OOOO OOOO IIII IIII IIII IIII + */ + val iostate = Array(0, 0, 0, 0) + + var outputChangedDelegate = { () => () } + + def setInput(r: Int, state: Int) { + iostate(r) = iostate(r) & 0xffff0000 | state & 0xffff + } + + def setOutput(r: Int, state: Int) { + iostate(r) = iostate(r) & 0xffff | (state & 0xffff) << 16 + } + + def onInputChanged(mask: Int) { + val ioparts = parts.values.collect { case io: TIOCircuitPart => io } + for (r <- 0 until 4) if ((mask & 1 << r) != 0) { + ioparts.foreach(_.onExtInputChanged(r)) + sendInputUpdate(r) + } + } + + def onOutputChanged(mask: Int) { + val ioparts = parts.values.collect { case io: TIOCircuitPart => io } + for (r <- 0 until 4) if ((mask & 1 << r) != 0) { + ioparts.foreach(_.onExtOutputChanged(r)) + outputChangedDelegate() + sendOutputUpdate(r) + } + } + + def save(tag: NBTTagCompound) { + tag.setString("name", name) + tag.setByte("sw", size.width.toByte) + tag.setByte("sh", size.height.toByte) + tag.setIntArray("iost", iostate) + + val tagList = new NBTTagList + for (part <- parts.values) { + val partTag = new NBTTagCompound + partTag.setByte("id", part.id.toByte) + partTag.setByte("xpos", part.x.toByte) + partTag.setByte("ypos", part.y.toByte) + part.save(partTag) + tagList.appendTag(partTag) + } + tag.setTag("parts", tagList) + + // etc + } + + def load(tag: NBTTagCompound) { + clear() + name = tag.getString("name") + size = Size(tag.getByte("sw") & 0xff, tag.getByte("sh") & 0xff) + val ta = tag.getIntArray("iost") + for (i <- 0 until 4) iostate(i) = ta(i) + + val partList = tag.getTagList("parts", 10) + for (i <- 0 until partList.tagCount) { + val partTag = partList.getCompoundTagAt(i) + val part = CircuitPart.createPart(partTag.getByte("id") & 0xff) + setPart_do( + partTag.getByte("xpos") & 0xff, + partTag.getByte("ypos") & 0xff, + part + ) + part.load(partTag) + } + + // etc + } + + def writeDesc(out: MCDataOutput) { + out.writeString(name) + out.writeByte(size.width).writeByte(size.height) + for (i <- 0 until 4) out.writeInt(iostate(i)) + + for (((x, y), part) <- parts) { + out.writeByte(part.id) + out.writeByte(x).writeByte(y) + part.writeDesc(out) + } + out.writeByte(255) + + // etc + } + + def readDesc(in: MCDataInput) { + clear() + name = in.readString() + size = Size(in.readUByte(), in.readUByte()) + for (i <- 0 until 4) iostate(i) = in.readInt() + + var id = in.readUByte() + while (id != 255) { + val part = CircuitPart.createPart(id) + setPart_do(in.readUByte(), in.readUByte(), part) + part.readDesc(in) + id = in.readUByte() + } + // etc + } + + def read(in: MCDataInput, key: Int) = key match { + case 0 => readDesc(in) + case 1 => + val part = CircuitPart.createPart(in.readUByte()) + setPart_do(in.readUByte(), in.readUByte(), part) + part.readDesc(in) + case 2 => removePart(in.readUByte(), in.readUByte()) + case 3 => CircuitOp.getOperation(in.readUByte()).readOp(this, in) + case 4 => + getPart(in.readUByte(), in.readUByte()) match { + case g: TClientNetCircuitPart => g.readClientPacket(in) + case _ => log.error("Server IC stream received invalid client packet") + } + case 5 => iostate(in.readUByte()) = in.readInt() + case 6 => setInput(in.readUByte(), in.readShort()) + case 7 => setOutput(in.readUByte(), in.readShort()) + case _ => + } + + def sendPartAdded(part: CircuitPart) { + val out = network.getICStreamOf(1) + out.writeByte(part.id) + out.writeByte(part.x).writeByte(part.y) + part.writeDesc(out) + } + + def sendRemovePart(x: Int, y: Int) { + network.getICStreamOf(2).writeByte(x).writeByte(y) + } + + def sendOpUse(op: CircuitOp, rotation: Int, configuration: Int, start: Point, end: Point) = { + if (op.checkOp(this, start, end)) { + op.writeOp(this, start, end, rotation, configuration, network.getICStreamOf(3).writeByte(op.id)) + true + } else false + } + + def sendClientPacket( + part: TClientNetCircuitPart, + writer: MCDataOutput => Unit + ) { + val s = network.getICStreamOf(4).writeByte(part.x).writeByte(part.y) + writer(s) + } + + def sendIOUpdate(r: Int) { + network.getICStreamOf(5).writeByte(r).writeInt(iostate(r)) + } + + def sendInputUpdate(r: Int) { + network.getICStreamOf(6).writeByte(r).writeShort(iostate(r) & 0xffff) + } + + def sendOutputUpdate(r: Int) { + network.getICStreamOf(7).writeByte(r).writeShort(iostate(r) >> 16) + } + + def clear() { + parts.values.foreach { + _.unbind() + } // remove references + parts = MMap() + scheduledTicks = MMap() + name = "untitled" + size = Size.zeroSize + for (i <- 0 until 4) iostate(i) = 0 + } + + def isEmpty = size == Size.zeroSize + + def nonEmpty = !isEmpty + + private def assertCoords(x: Int, y: Int) { + if (!(0 until size.width contains x) || !(0 until size.height contains y)) + throw new IndexOutOfBoundsException( + "Circuit does not contain " + Point(x, y) + ) + } + + def tick() { + val t = network.getWorld.getTotalWorldTime + var rem = Seq[(Int, Int)]() + for ((k, v) <- scheduledTicks) if (v >= t) { + getPart(k._1, k._2).scheduledTick() + rem :+= k + } + rem.foreach(scheduledTicks.remove) + + for (part <- parts.values) part.update() + } + + def refreshErrors() { + val eparts = parts.values.collect { case p: TErrorCircuitPart => p } + val elist = Map.newBuilder[Point, (String, Int)] + + for (part <- eparts) { + val error = part.postErrors + if (error != null) + elist += Point(part.x, part.y) -> error + } + + errors = elist.result() + } + + def setPart(x: Int, y: Int, part: CircuitPart) { + setPart_do(x, y, part) + part.onAdded() + if (!network.isRemote) sendPartAdded(part) + } + + private def setPart_do(x: Int, y: Int, part: CircuitPart) { + assertCoords(x, y) + part.bind(this, x, y) + parts += (x, y) -> part + } + + def getPart(x: Int, y: Int): CircuitPart = parts.getOrElse((x, y), null) + + def removePart(x: Int, y: Int) { + assertCoords(x, y) + val part = getPart(x, y) + if (part != null) { + if (!network.isRemote) sendRemovePart(x, y) + parts.remove((x, y)) + part.onRemoved() + part.unbind() + } + } + + def notifyNeighbor(x: Int, y: Int) { + val part = getPart(x, y) + if (part != null) part.onNeighborChanged() + } + + def notifyNeighbors(x: Int, y: Int, mask: Int) { + for (r <- 0 until 4) if ((mask & 1 << r) != 0) { + val point = Point(x, y).offset(r) + val part = getPart(point.x, point.y) + if (part != null) part.onNeighborChanged() + } + } + + def scheduleTick(x: Int, y: Int, ticks: Int) { + scheduledTicks += (x, y) -> (network.getWorld.getTotalWorldTime + ticks) + } + + // Convinience functions + def setPart(p: Point, part: CircuitPart) { + setPart(p.x, p.y, part) + } + + def getPart(p: Point): CircuitPart = getPart(p.x, p.y) + + def removePart(p: Point) { + removePart(p.x, p.y) + } + + def notifyNeighbor(p: Point) { + notifyNeighbor(p.x, p.y) + } + + def notifyNeighbors(p: Point, mask: Int) { + notifyNeighbors(p.x, p.y, mask) + } + + def scheduleTick(p: Point, ticks: Int) { + scheduleTick(p.x, p.y, ticks) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/items.scala b/src/main/scala/mrtjp/projectred/fabrication/Items.scala similarity index 97% rename from src/main/scala/mrtjp/projectred/fabrication/items.scala rename to src/main/scala/mrtjp/projectred/fabrication/Items.scala index f6dddbd8f..d9050d454 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/items.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/Items.scala @@ -6,14 +6,14 @@ package mrtjp.projectred.fabrication import java.util.{List => JList} - import codechicken.lib.gui.GuiDraw import cpw.mods.fml.common.registry.GameRegistry import mrtjp.core.color.Colors import mrtjp.core.item.ItemCore import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.IIOCircuitPart._ +import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart +import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart._ import mrtjp.projectred.integration.GateDefinition import mrtjp.projectred.{ProjectRedFabrication, ProjectRedIntegration} import net.minecraft.client.renderer.texture.IIconRegister @@ -26,12 +26,10 @@ import net.minecraft.util.EnumChatFormatting._ import net.minecraft.util.{EnumChatFormatting, IIcon} import net.minecraft.world.World import net.minecraftforge.client.IItemRenderer -import net.minecraftforge.client.IItemRenderer.{ - ItemRenderType, - ItemRendererHelper -} +import net.minecraftforge.client.IItemRenderer.{ItemRenderType, ItemRendererHelper} import org.lwjgl.opengl.GL11._ + class ItemICBlueprint extends ItemMap // extend ItemMap so minecraft will handle the FP render for us { @@ -143,7 +141,7 @@ object ItemICBlueprint { def saveICToGate(ic: IntegratedCircuit, gate: ItemStack) { assertStackTag(gate) - val ioparts = ic.parts.values.collect { case io: IIOCircuitPart => + val ioparts = ic.parts.values.collect { case io: TIOCircuitPart => io }.toSeq var (ri, ro, bi, bo) = (0, 0, 0, 0) diff --git a/src/main/scala/mrtjp/projectred/fabrication/proxies.scala b/src/main/scala/mrtjp/projectred/fabrication/Proxies.scala similarity index 99% rename from src/main/scala/mrtjp/projectred/fabrication/proxies.scala rename to src/main/scala/mrtjp/projectred/fabrication/Proxies.scala index 4165756a0..a51cfd638 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/proxies.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/Proxies.scala @@ -5,7 +5,6 @@ */ package mrtjp.projectred.fabrication import java.lang.{Character => JC} - import codechicken.lib.data.MCDataInput import codechicken.multipart.MultiPartRegistry import codechicken.multipart.MultiPartRegistry.IPartFactory2 @@ -20,6 +19,7 @@ import mrtjp.projectred.core.{IProxy, PartDefs} import mrtjp.projectred.integration.{GateDefinition, RenderGate} import mrtjp.projectred.{ProjectRedFabrication, ProjectRedIntegration} import mrtjp.projectred.Tags +import mrtjp.projectred.fabrication.gui.GuiICWorkbench import net.minecraft.init.{Blocks, Items} import net.minecraft.inventory.InventoryCrafting import net.minecraft.item.ItemStack diff --git a/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala new file mode 100644 index 000000000..26db20b3a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication + +import codechicken.lib.vec._ +import mrtjp.projectred.fabrication.gui.PrefboardRenderer +import net.minecraft.client.renderer.texture.IIconRegister +import org.lwjgl.opengl.GL11._ + + +object RenderCircuit { + def registerIcons(reg: IIconRegister) { + ICComponentStore.registerIcons(reg) + } + + def renderOrtho( + circuit: IntegratedCircuit, + x: Double, + y: Double, + xSize: Double, + ySize: Double, + frame: Float + ) { + val t = + ICComponentStore.orthoGridT(xSize, ySize) `with` new Translation(x, y, 0) + renderBoard(circuit, t, true) + renderCircuit(circuit, t, true, frame) + } + + def renderDynamic( + circuit: IntegratedCircuit, + t: Transformation, + frame: Float + ) { + glDisable(GL_DEPTH_TEST) + renderBoard(circuit, t, true) + renderCircuit(circuit, t, true, frame) + glEnable(GL_DEPTH_TEST) + } + + def renderBoard( + circuit: IntegratedCircuit, + t: Transformation, + ortho: Boolean + ) { + PrefboardRenderer.render(circuit, t, ortho) + } + + def renderCircuit( + circuit: IntegratedCircuit, + t: Transformation, + ortho: Boolean, + frame: Float + ) { + for (((x, y), part) <- circuit.parts) { + val tlist = new TransformationList( + new Scale(1.0 / circuit.size.width, 1, 1.0 / circuit.size.height), + new Translation( + x * 1.0 / circuit.size.width, + 0, + y * 1.0 / circuit.size.height + ), + t + ) + part.renderDynamic(tlist, ortho, frame) + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala new file mode 100644 index 000000000..08feec109 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.packet.PacketCustom +import codechicken.lib.vec.BlockCoord +import mrtjp.core.vec.Point +import mrtjp.projectred.ProjectRedCore.log +import mrtjp.projectred.fabrication.circuitparts.CircuitPart +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.world.World +import net.minecraftforge.fluids.FluidStack + +trait WorldCircuit { + def getIC: IntegratedCircuit + + def getWorld: World + + def getICStreamOf(key: Int): MCDataOutput + + def getPartStream(x: Int, y: Int): MCDataOutput + + def isRemote: Boolean + + def markSave() +} + + +object DummyMCIO extends MCDataOutput { + override def writeVarInt(i: Int) = this + override def writeCoord(x: Int, y: Int, z: Int) = this + override def writeCoord(coord: BlockCoord) = this + override def writeString(s: String) = this + override def writeFloat(f: Float) = this + override def writeDouble(d: Double) = this + override def writeShort(s: Int) = this + override def writeVarShort(s: Int) = this + override def writeInt(i: Int) = this + override def writeFluidStack(liquid: FluidStack) = this + override def writeByteArray(array: Array[Byte]) = this + override def writeBoolean(b: Boolean) = this + override def writeItemStack(stack: ItemStack) = this + override def writeNBTTagCompound(tag: NBTTagCompound) = this + override def writeChar(c: Char) = this + override def writeLong(l: Long) = this + override def writeByte(b: Int) = this +} + +trait SimulatedWorldCircuit extends WorldCircuit { + override def getICStreamOf(key: Int) = DummyMCIO + override def getPartStream(x: Int, y: Int) = DummyMCIO + override def isRemote = false +} + +trait NetWorldCircuit extends WorldCircuit { + private var icStream: PacketCustom = null + private var partStream: PacketCustom = null + + def createPartStream(): PacketCustom + def sendPartStream(out: PacketCustom) + override def getPartStream(x: Int, y: Int): MCDataOutput = { + if (partStream == null) partStream = createPartStream() + + val part = getIC.getPart(x, y) + partStream.writeByte(part.id) + partStream.writeByte(x).writeByte(y) + + partStream + } + def flushPartStream() { + if (partStream != null) { + partStream.writeByte(255) // terminator + sendPartStream(partStream.compress()) + partStream = null + } + } + def readPartStream(in: MCDataInput) { + try { + var id = in.readUByte() + while (id != 255) { + val (x, y) = (in.readUByte(), in.readUByte()) + var part = getIC.getPart(x, y) + if (part == null || part.id != id) { + log.error("client part stream couldnt find part " + Point(x, y)) + part = CircuitPart.createPart(id) + } + part.read(in) + id = in.readUByte() + } + } catch { + case ex: IndexOutOfBoundsException => + log.error("Circuit part stream failed to be read.") + ex.printStackTrace() + } + } + + def createICStream(): PacketCustom + def sendICStream(out: PacketCustom) + override def getICStreamOf(key: Int): MCDataOutput = { + if (icStream == null) icStream = createICStream() + icStream.writeByte(key) + icStream + } + def flushICStream() { + if (icStream != null) { + icStream.writeByte(255) // terminator + sendICStream(icStream.compress()) + icStream = null + } + } + def readICStream(in: MCDataInput) { + try { + var id = in.readUByte() + while (id != 255) { + getIC.read(in, id) + id = in.readUByte() + } + } catch { + case ex: IndexOutOfBoundsException => + log.error("Circuit IC stream failed to be read") + } + } +} + diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala new file mode 100644 index 000000000..fe7a0a966 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.circuitparts.cells.{BufferCell, InvertCell, NullCell} + +object ArrayGateICLogic { + + import ICGateDefinition._ + + def create(gate: ArrayGateICPart, subID: Int) = subID match { + case NullCell.ordinal => new NullCell(gate) + case InvertCell.ordinal => new InvertCell(gate) + case BufferCell.ordinal => new BufferCell(gate) + case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) + } +} + +abstract class ArrayGateICLogic(val gate: ArrayGateICPart) + extends RedstoneICGateLogic[ArrayGateICPart] + with TArrayICGateLogic[ArrayGateICPart] + with TComplexICGateLogic[ArrayGateICPart] \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala new file mode 100644 index 000000000..5bc085a64 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import net.minecraft.nbt.NBTTagCompound + +abstract class ArrayGateICLogicCrossing(gate: ArrayGateICPart) + extends ArrayGateICLogic(gate) { + var signal1: Byte = 0 + var signal2: Byte = 0 + + override def redwireMask(shape: Int) = 0xf + + override def propogationMask(r: Int) = if (r % 2 == 0) 0x5 else 0xa + + override def inputMask(shape: Int) = 0xf + + override def outputMask(shape: Int) = 0xf + + override def getSignal(mask: Int) = + (if (mask == 0x5) signal1 else signal2) & 0xff + + override def setSignal(mask: Int, signal: Int) { + if (mask == 0x5) signal1 = signal.toByte else signal2 = signal.toByte + } + + override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("s1", signal1) + tag.setByte("s2", signal2) + } + + override def load(tag: NBTTagCompound) { + super.load(tag) + signal1 = tag.getByte("s1") + signal2 = tag.getByte("s2") + } + + override def writeDesc(packet: MCDataOutput) { + super.writeDesc(packet) + packet.writeByte(signal1) + packet.writeByte(signal2) + } + + override def readDesc(packet: MCDataInput) { + super.readDesc(packet) + signal1 = packet.readByte() + signal2 = packet.readByte() + } + + override def read(packet: MCDataInput, key: Int) = key match { + case 11 => + signal1 = packet.readByte() + signal2 = packet.readByte() + case _ => + } + + def sendSignalUpdate() { + gate.writeStreamOf(11).writeByte(signal1).writeByte(signal2) + } + + override def onChange(gate: ArrayGateICPart) { + val oldSignal = (gate.state & 1) != 0 + val newSignal = signal1 != 0 + + if (oldSignal != newSignal) { + gate.setState(gate.state & 2 | (if (newSignal) 1 else 0)) + gate.onInputChange() + gate.scheduleTick(0) + } + } + + override def scheduledTick(gate: ArrayGateICPart) { + val input = (gate.state & 1) != 0 + val oldOutput = (gate.state & 2) != 0 + val newOutput = !input + + if (oldOutput != newOutput) { + gate.setState(gate.state & 1 | (if (newOutput) 2 else 0)) + gate.onOutputChange(0) + gate.onChange() + } + } + + override def onSignalUpdate() { + sendSignalUpdate() + } + + override def overrideSignal(mask: Int) = if (mask == 0xa) powerUp else false + + override def calculateSignal(mask: Int) = 255 + + def powerUp: Boolean + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: ArrayGateICPart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + + if (detailLevel >= 3) { + data += "lower: 0x" + Integer.toHexString(signal1 & 0xff) + data += "upper: 0x" + Integer.toHexString(signal2 & 0xff) + } else if (detailLevel >= 2) { + data += "lower: " + (if (signal1 != 0) "high" else "low") + data += "upper: " + (if (signal2 != 0) "high" else "low") + } + + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala new file mode 100644 index 000000000..837aa8430 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + + +class ArrayGateICPart + extends RedstoneGateICPart + with TComplexGateICPart + with TArrayGateICPart { + private var logic: ArrayGateICLogic = null + + override def getLogic[T] = logic.asInstanceOf[T] + + override def assertLogic() { + if (logic == null) logic = ArrayGateICLogic.create(this, subID) + } + + override def getPartType = CircuitPartDefs.ArrayGate +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala new file mode 100644 index 000000000..3444f90bb --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.vec.Transformation +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.projectred.fabrication.operations.CircuitOp +import net.minecraft.nbt.NBTTagCompound + +object CircuitPart { + def createPart(id: Int) = CircuitPartDefs(id).createPart +} + +/** + * Base Class for all Gates, that are displayed in the IC Workbench + */ +abstract class CircuitPart { + var world: IntegratedCircuit = null + var loc: (Byte, Byte) = null + + def bind(ic: IntegratedCircuit, x: Int, y: Int) { + world = ic + loc = (x.toByte, y.toByte) + } + + def unbind() { + world = null + loc = null + } + + def x = loc._1 & 0xff + + def y = loc._2 & 0xff + + def id = getPartType.id + + def getPartType: CircuitPartDefs.CircuitPartDef + + def save(tag: NBTTagCompound) {} + + def load(tag: NBTTagCompound) {} + + def writeDesc(out: MCDataOutput) {} + + def readDesc(in: MCDataInput) {} + + def writeStreamOf(key: Int): MCDataOutput = + world.network.getPartStream(x, y).writeByte(key) + + def read(in: MCDataInput) { + read(in, in.readUByte()) + } + + def read(in: MCDataInput, key: Int) = key match { + case 0 => readDesc(in) + case _ => + } + + def sendDescUpdate() { + writeDesc(writeStreamOf(0)) + } + + def update() {} + + def scheduledTick() {} + + def scheduleTick(ticks: Int) { + world.scheduleTick(x, y, ticks) + } + + def onAdded() {} + + def onRemoved() {} + + def onNeighborChanged() {} + + @SideOnly(Side.CLIENT) + def onClicked() {} + + @SideOnly(Side.CLIENT) + def onActivated() {} + + @SideOnly(Side.CLIENT) + def getPartName: String + + @SideOnly(Side.CLIENT) + def getPickOp: CircuitOp = null + + @SideOnly(Side.CLIENT) + def getRolloverData(detailLevel: Int): Seq[String] = + if (detailLevel > 0) Seq(getPartName) else Seq.empty + + @SideOnly(Side.CLIENT) + def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) {} +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala new file mode 100644 index 000000000..dc507671d --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.core.util.Enum +import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart +import mrtjp.projectred.fabrication.circuitparts.wire._ + + +object CircuitPartDefs extends Enum { + type EnumVal = CircuitPartDef + + val Torch = CircuitPartDef(() => new TorchICPart) + val Lever = CircuitPartDef(() => new LeverICPart) + val Button = CircuitPartDef(() => new ButtonICPart) + + val AlloyWire = CircuitPartDef(() => new AlloyWireICPart) + val InsulatedWire = CircuitPartDef(() => new InsulatedWireICPart) + val BundledCable = CircuitPartDef(() => new BundledCableICPart) + + val IOGate = CircuitPartDef(() => new IOGateICPart) + val SimpleGate = CircuitPartDef(() => new ComboICGatePart) + val ComplexGate = CircuitPartDef(() => new SequentialGateICPart) + val ArrayGate = CircuitPartDef(() => new ArrayGateICPart) + + case class CircuitPartDef(factory: () => CircuitPart) extends Value { + def id = ordinal + + override def name = s"$id" + + def createPart = factory.apply() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala new file mode 100644 index 000000000..e6c61472c --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.circuitparts.latches.TransparentLatch +import mrtjp.projectred.fabrication.circuitparts.misc.{DecRandomizer, Randomizer} +import mrtjp.projectred.fabrication.circuitparts.primitives._ +import mrtjp.projectred.fabrication.circuitparts.timing.Repeater + +abstract class ComboICGateLogic + extends RedstoneICGateLogic[ComboICGatePart] + with TSimpleRSICGateLogic[ComboICGatePart] { + override def cycleShape(gate: ComboICGatePart) = { + val oldShape = gate.shape + val newShape = cycleShape(oldShape) + if (newShape != oldShape) { + gate.setShape(newShape) + true + } else false + } + + def cycleShape(shape: Int): Int = { + if (deadSides == 0) return shape + + var shape1 = shape + import java.lang.Integer.{bitCount, numberOfLeadingZeros => lead} + do shape1 = ComboICGateLogic.advanceDead(shape1) while (bitCount( + shape1 + ) > maxDeadSides || 32 - lead(shape1) > deadSides) + shape1 + } + + def deadSides = 0 + + def maxDeadSides = deadSides - 1 +} + +object ComboICGateLogic { + val advanceDead = Seq(1, 2, 4, 0, 5, 6, 3) + + val instances = new Array[ComboICGateLogic](ICGateDefinition.values.length) + initialize() + + def initialize() { + instances(ICGateDefinition.OR.ordinal) = OR + instances(ICGateDefinition.NOR.ordinal) = NOR + instances(ICGateDefinition.NOT.ordinal) = NOT + instances(ICGateDefinition.AND.ordinal) = AND + instances(ICGateDefinition.NAND.ordinal) = NAND + instances(ICGateDefinition.XOR.ordinal) = XOR + instances(ICGateDefinition.XNOR.ordinal) = XNOR + instances(ICGateDefinition.Buffer.ordinal) = Buffer + instances(ICGateDefinition.Multiplexer.ordinal) = Multiplexer + instances(ICGateDefinition.Pulse.ordinal) = Pulse + instances(ICGateDefinition.Repeater.ordinal) = Repeater + instances(ICGateDefinition.Randomizer.ordinal) = Randomizer + instances(ICGateDefinition.TransparentLatch.ordinal) = TransparentLatch + instances(ICGateDefinition.DecRandomizer.ordinal) = DecRandomizer + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala new file mode 100644 index 000000000..0f050dc62 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +class ComboICGatePart extends RedstoneGateICPart { + override def getLogic[T] = ComboICGateLogic.instances(subID).asInstanceOf[T] + + def getLogicCombo = getLogic[ComboICGateLogic] + + override def getPartType = CircuitPartDefs.SimpleGate +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala similarity index 50% rename from src/main/scala/mrtjp/projectred/fabrication/gatepart.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala index 923672fb0..946be37ea 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala @@ -3,17 +3,17 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.util.Enum -import mrtjp.projectred.integration.GateDefinition.GateDef +import mrtjp.projectred.fabrication.gui.IGuiCircuitPart +import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound abstract class GateICPart - extends CircuitPart + extends CircuitPart with TConnectableICPart with TICOrient with IGuiCircuitPart { @@ -24,12 +24,16 @@ abstract class GateICPart var schedDigital = false def getLogic[T]: T + def getLogicPrimitive = getLogic[ICGateLogic[GateICPart]] def subID = gateSubID & 0xff def shape = gateShape & 0xff - def setShape(s: Int) { gateShape = s.toByte } + + def setShape(s: Int) { + gateShape = s.toByte + } def preparePlacement(rot: Int, configuration: Int, meta: Int) { gateSubID = meta.toByte @@ -109,13 +113,14 @@ abstract class GateICPart } var iter = 0 + def processScheduledDigital() { while (schedDigital && iter < 3) // recursion control - { - schedDigital = false - iter += 1 - scheduledTick() - } + { + schedDigital = false + iter += 1 + scheduledTick() + } } def onChange() { @@ -183,7 +188,7 @@ abstract class GateICPart @SideOnly(Side.CLIENT) override def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) { - RenderICGate.renderDynamic(this, t, ortho, frame) + ICGateRenderer.renderDynamic(this, t, ortho, frame) } @SideOnly(Side.CLIENT) @@ -209,134 +214,3 @@ abstract class GateICPart override def getPickOp = CircuitOpDefs.values(CircuitOpDefs.SimpleIO.ordinal + subID).getOp } - -abstract class ICGateLogic[T <: GateICPart] { - def canConnectTo(gate: T, part: CircuitPart, r: Int): Boolean - - def cycleShape(gate: T) = false - - def onChange(gate: T) - - def scheduledTick(gate: T) - - def onTick(gate: T) {} - - def setup(gate: T) {} - - def activate(gate: T) {} - - @SideOnly(Side.CLIENT) - def getRolloverData(gate: T, detailLevel: Int): Seq[String] = Seq.empty - - @SideOnly(Side.CLIENT) - def createGui(gate: T): CircuitGui = new ICGateGui(gate) -} - -trait TComplexGateICPart extends GateICPart { - def getLogicComplex = getLogic[TComplexICGateLogic[TComplexGateICPart]] - - def assertLogic() - - abstract override def save(tag: NBTTagCompound) { - super.save(tag) - getLogicComplex.save(tag) - } - - abstract override def load(tag: NBTTagCompound) { - super.load(tag) - assertLogic() - getLogicComplex.load(tag) - } - - abstract override def writeDesc(packet: MCDataOutput) { - super.writeDesc(packet) - getLogicComplex.writeDesc(packet) - } - - abstract override def readDesc(packet: MCDataInput) { - super.readDesc(packet) - assertLogic() - getLogicComplex.readDesc(packet) - } - - abstract override def read(packet: MCDataInput, key: Int) = key match { - case k if k > 10 => - assertLogic() // this may be a net dump part - getLogicComplex.read(packet, k) - case _ => super.read(packet, key) - } - - abstract override def preparePlacement(rotation: Int, configuration: Int, meta: Int) { - super.preparePlacement(rotation, configuration, meta) - assertLogic() - } -} - -trait TComplexICGateLogic[T <: TComplexGateICPart] extends ICGateLogic[T] { - def save(tag: NBTTagCompound) {} - def load(tag: NBTTagCompound) {} - - def readDesc(packet: MCDataInput) {} - def writeDesc(packet: MCDataOutput) {} - - /** Allocated keys > 10 - */ - def read(packet: MCDataInput, key: Int) {} -} - -object ICGateDefinition extends Enum { - type EnumVal = ICGateDef - - import mrtjp.projectred.integration.{GateDefinition => gd} - - val IOSimple = ICGateDef("Simple IO", CircuitPartDefs.IOGate.id) - val IOAnalog = ICGateDef("Analog IO", CircuitPartDefs.IOGate.id) - val IOBundled = ICGateDef("Bundled IO", CircuitPartDefs.IOGate.id) - - val OR = ICGateDef("OR gate", CircuitPartDefs.SimpleGate.id, gd.OR) - val NOR = ICGateDef("NOR gate", CircuitPartDefs.SimpleGate.id, gd.NOR) - val NOT = ICGateDef("NOT gate", CircuitPartDefs.SimpleGate.id, gd.NOT) - val AND = ICGateDef("AND gate", CircuitPartDefs.SimpleGate.id, gd.AND) - val NAND = ICGateDef("NAND gate", CircuitPartDefs.SimpleGate.id, gd.NAND) - val XOR = ICGateDef("XOR gate", CircuitPartDefs.SimpleGate.id, gd.XOR) - val XNOR = ICGateDef("XNOR gate", CircuitPartDefs.SimpleGate.id, gd.XNOR) - val Buffer = - ICGateDef("Buffer gate", CircuitPartDefs.SimpleGate.id, gd.Buffer) - val Multiplexer = - ICGateDef("Multiplexer", CircuitPartDefs.SimpleGate.id, gd.Multiplexer) - val Pulse = ICGateDef("Pulse Former", CircuitPartDefs.SimpleGate.id, gd.Pulse) - val Repeater = - ICGateDef("Repeater", CircuitPartDefs.SimpleGate.id, gd.Repeater) - val Randomizer = - ICGateDef("Randomizer", CircuitPartDefs.SimpleGate.id, gd.Randomizer) - val SRLatch = - ICGateDef("SR Latch", CircuitPartDefs.ComplexGate.id, gd.SRLatch) - val ToggleLatch = - ICGateDef("Toggle Latch", CircuitPartDefs.ComplexGate.id, gd.ToggleLatch) - val TransparentLatch = ICGateDef( - "Transparent Latch", - CircuitPartDefs.SimpleGate.id, - gd.TransparentLatch - ) - val Timer = ICGateDef("Timer", CircuitPartDefs.ComplexGate.id, gd.Timer) - val Sequencer = - ICGateDef("Sequencer", CircuitPartDefs.ComplexGate.id, gd.Sequencer) - val Counter = ICGateDef("Counter", CircuitPartDefs.ComplexGate.id, gd.Counter) - val StateCell = - ICGateDef("State Cell", CircuitPartDefs.ComplexGate.id, gd.StateCell) - val Synchronizer = - ICGateDef("Synchronizer", CircuitPartDefs.ComplexGate.id, gd.Synchronizer) - val DecRandomizer = - ICGateDef("Dec Randomizer", CircuitPartDefs.SimpleGate.id, gd.DecRandomizer) - val NullCell = - ICGateDef("Null Cell", CircuitPartDefs.ArrayGate.id, gd.NullCell) - val InvertCell = - ICGateDef("Invert Cell", CircuitPartDefs.ArrayGate.id, gd.InvertCell) - val BufferCell = - ICGateDef("Buffer Cell", CircuitPartDefs.ArrayGate.id, gd.BufferCell) - - case class ICGateDef(unlocal: String, gateType: Int, intDef: GateDef = null) - extends Value { - override def name = unlocal - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala new file mode 100644 index 000000000..00f3ac112 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.core.util.Enum +import mrtjp.projectred.integration.GateDefinition.GateDef + + +object ICGateDefinition extends Enum { + type EnumVal = ICGateDef + + import mrtjp.projectred.integration.{GateDefinition => gd} + + val IOSimple = ICGateDef("Simple IO", CircuitPartDefs.IOGate.id) + val IOAnalog = ICGateDef("Analog IO", CircuitPartDefs.IOGate.id) + val IOBundled = ICGateDef("Bundled IO", CircuitPartDefs.IOGate.id) + + val OR = ICGateDef("OR gate", CircuitPartDefs.SimpleGate.id, gd.OR) + val NOR = ICGateDef("NOR gate", CircuitPartDefs.SimpleGate.id, gd.NOR) + val NOT = ICGateDef("NOT gate", CircuitPartDefs.SimpleGate.id, gd.NOT) + val AND = ICGateDef("AND gate", CircuitPartDefs.SimpleGate.id, gd.AND) + val NAND = ICGateDef("NAND gate", CircuitPartDefs.SimpleGate.id, gd.NAND) + val XOR = ICGateDef("XOR gate", CircuitPartDefs.SimpleGate.id, gd.XOR) + val XNOR = ICGateDef("XNOR gate", CircuitPartDefs.SimpleGate.id, gd.XNOR) + val Buffer = + ICGateDef("Buffer gate", CircuitPartDefs.SimpleGate.id, gd.Buffer) + val Multiplexer = + ICGateDef("Multiplexer", CircuitPartDefs.SimpleGate.id, gd.Multiplexer) + val Pulse = ICGateDef("Pulse Former", CircuitPartDefs.SimpleGate.id, gd.Pulse) + val Repeater = + ICGateDef("Repeater", CircuitPartDefs.SimpleGate.id, gd.Repeater) + val Randomizer = + ICGateDef("Randomizer", CircuitPartDefs.SimpleGate.id, gd.Randomizer) + val SRLatch = + ICGateDef("SR Latch", CircuitPartDefs.ComplexGate.id, gd.SRLatch) + val ToggleLatch = + ICGateDef("Toggle Latch", CircuitPartDefs.ComplexGate.id, gd.ToggleLatch) + val TransparentLatch = ICGateDef( + "Transparent Latch", + CircuitPartDefs.SimpleGate.id, + gd.TransparentLatch + ) + val Timer = ICGateDef("Timer", CircuitPartDefs.ComplexGate.id, gd.Timer) + val Sequencer = + ICGateDef("Sequencer", CircuitPartDefs.ComplexGate.id, gd.Sequencer) + val Counter = ICGateDef("Counter", CircuitPartDefs.ComplexGate.id, gd.Counter) + val StateCell = + ICGateDef("State Cell", CircuitPartDefs.ComplexGate.id, gd.StateCell) + val Synchronizer = + ICGateDef("Synchronizer", CircuitPartDefs.ComplexGate.id, gd.Synchronizer) + val DecRandomizer = + ICGateDef("Dec Randomizer", CircuitPartDefs.SimpleGate.id, gd.DecRandomizer) + val NullCell = + ICGateDef("Null Cell", CircuitPartDefs.ArrayGate.id, gd.NullCell) + val InvertCell = + ICGateDef("Invert Cell", CircuitPartDefs.ArrayGate.id, gd.InvertCell) + val BufferCell = + ICGateDef("Buffer Cell", CircuitPartDefs.ArrayGate.id, gd.BufferCell) + + case class ICGateDef(unlocal: String, gateType: Int, intDef: GateDef = null) + extends Value { + override def name = unlocal + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala new file mode 100644 index 000000000..f918dfe39 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICGateGui} + +abstract class ICGateLogic[T <: GateICPart] { + def canConnectTo(gate: T, part: CircuitPart, r: Int): Boolean + + def cycleShape(gate: T) = false + + def onChange(gate: T) + + def scheduledTick(gate: T) + + def onTick(gate: T) {} + + def setup(gate: T) {} + + def activate(gate: T) {} + + @SideOnly(Side.CLIENT) + def getRolloverData(gate: T, detailLevel: Int): Seq[String] = Seq.empty + + @SideOnly(Side.CLIENT) + def createGui(gate: T): CircuitGui = new ICGateGui(gate) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala new file mode 100644 index 000000000..7c0829dfd --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.vec.Transformation +import mrtjp.projectred.fabrication.ICComponentModel +import mrtjp.projectred.fabrication.ICComponentStore.{finishRender, prepairRender} +import mrtjp.projectred.fabrication.circuitparts.cells.{RenderBufferCell, RenderInvertCell, RenderNullCell} +import mrtjp.projectred.fabrication.circuitparts.io.{RenderAnalogIO, RenderBundledIO, RenderSimpleIO} +import mrtjp.projectred.fabrication.circuitparts.latches.{RenderSRLatch, RenderToggleLatch, RenderTransparentLatch} +import mrtjp.projectred.fabrication.circuitparts.misc.{RenderCounter, RenderDecRandomizer, RenderRandomizer, RenderSynchronizer} +import mrtjp.projectred.fabrication.circuitparts.primitives.{RenderAND, RenderBuffer, RenderMultiplexer, RenderNAND, RenderNOR, RenderNOT, RenderOR, RenderXNOR, RenderXOR} +import mrtjp.projectred.fabrication.circuitparts.timing.{RenderPulse, RenderRepeater, RenderSequencer, RenderStateCell, RenderTimer} +import net.minecraft.client.renderer.texture.IIconRegister + + +object ICGateRenderer { + var renderers = buildRenders() + + def buildRenders() = Seq[ICGateRenderer[_]]( + new RenderSimpleIO, + new RenderAnalogIO, + new RenderBundledIO, + new RenderOR, + new RenderNOR, + new RenderNOT, + new RenderAND, + new RenderNAND, + new RenderXOR, + new RenderXNOR, + new RenderBuffer, + new RenderMultiplexer, + new RenderPulse, + new RenderRepeater, + new RenderRandomizer, + new RenderSRLatch, + new RenderToggleLatch, + new RenderTransparentLatch, + new RenderTimer, + new RenderSequencer, + new RenderCounter, + new RenderStateCell, + new RenderSynchronizer, + new RenderDecRandomizer, + new RenderNullCell, + new RenderInvertCell, + new RenderBufferCell + ) + + def registerIcons(reg: IIconRegister) {} + + def renderDynamic( + gate: GateICPart, + t: Transformation, + ortho: Boolean, + frame: Float + ) { + val r = renderers(gate.subID).asInstanceOf[ICGateRenderer[GateICPart]] + r.prepareDynamic(gate, frame) + r.renderDynamic(gate.rotationT `with` t, ortho) + } + + def renderWithConfiguration(configuration: Int, t: Transformation, id: Int): Unit = { + val r = renderers(id) + r.prepareStatic(configuration) + r.renderDynamic(t, true) + } + + def renderInv(t: Transformation, id: Int) { + val r = renderers(id) + r.prepareStatic(0) + r.renderDynamic(t, true) + } +} + + +abstract class ICGateRenderer[T <: GateICPart] { + var reflect = false + + def coreModels: Seq[ICComponentModel] + def switchModels = Seq[ICComponentModel]() + + def prepareStatic(configuration: Int) + def prepareDynamic(gate: T, frame: Float) {} + + def renderDynamic(t: Transformation, ortho: Boolean) { + renderModels(t, if (reflect) 1 else 0, ortho) + } + + def renderModels(t: Transformation, orient: Int, ortho: Boolean) { + prepairRender() + for (m <- coreModels ++ switchModels) m.renderModel(t, orient, ortho) + finishRender() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala new file mode 100644 index 000000000..b483f0852 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.IntegratedCircuit + +object IWireICPart { + + /** Standard operation procedure, no special propogation rules. The propogator + * signal may not have increased. + */ + final val RISING = 0 + + /** Used when the propogator signal dropped (to 0). Propagation should + * continue until a rising or constant change is encountered at which point a + * RISING should be propogated back to this wire. + */ + final val DROPPING = 1 + + /** Used when a wire's connection state has changed. Even if the signal + * remains the same, new connections still need to be recalculated + */ + final val FORCE = 2 + + /** Used when the propogator did not change signal, but a new connection may + * have been established and signal needs recalculating + */ + final val FORCED = 3 +} + +trait IWireICPart { + + /** Recalculates the signal of this wire and calls the appropriate propogation + * methods in WirePropagator. DO NOT CALL THIS YOURSELF. Use + * WirePropagator.propagateTo + * + * @param prev + * The part which called this propogation (should be connected) may be + * null. + * @param mode + * One of RISING, DROPPING, FORCE and FORCED specified above + */ + def updateAndPropagate(prev: CircuitPart, mode: Int) + + /** Called at the end of a propogation run for partChanged events. Marks the + * end of a state change for this part. + */ + def onSignalUpdate() + + /** @param r + * The rotation of this part to test for wire connection. + * @return + * true if the specified side of this block is connected to, for example, a + * 'wire' where signal should decrease by one. + */ + def diminishOnSide(r: Int): Boolean + + /** The world in which this part resides + * + * @return + */ + def world: IntegratedCircuit +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepartrs.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala similarity index 60% rename from src/main/scala/mrtjp/projectred/fabrication/gatepartrs.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala index 0988f3537..8e65d8748 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepartrs.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala @@ -3,23 +3,27 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.{MCDataInput, MCDataOutput} +import mrtjp.projectred.fabrication.circuitparts.wire.IICRedwireEmitter import net.minecraft.nbt.NBTTagCompound abstract class RedstoneGateICPart - extends GateICPart + extends GateICPart with TICRSAcquisitions - with IPoweredCircuitPart { + with TPoweredCircuitPart { /** Mapped inputs and outputs of the gate. OOOO IIII High nybble is output. - * Low nybble is input - */ + * Low nybble is input + */ private var gateState: Byte = 0 def state = gateState & 0xff - def setState(s: Int) { gateState = s.toByte } + + def setState(s: Int) { + gateState = s.toByte + } def getLogicRS = getLogic[RedstoneICGateLogic[RedstoneGateICPart]] @@ -74,31 +78,8 @@ abstract class RedstoneGateICPart def getRedstoneInput(r: Int) = calcSignal(toAbsolute(r)) override def resolveSignal(part: Any, r: Int) = part match { - case re: IICRedwireEmitter => re.getRedwireSignal(r) - case ip: IPoweredCircuitPart => ip.rsOutputLevel(r) - case _ => 0 - } -} - -abstract class RedstoneICGateLogic[T <: RedstoneGateICPart] - extends ICGateLogic[T] { - override def canConnectTo(gate: T, part: CircuitPart, r: Int) = part match { - case re: IICRedwireEmitter => canConnect(gate, r) - case _ => false - } - - def canConnect(gate: T, r: Int): Boolean = canConnect(gate.shape, r) - def canConnect(shape: Int, r: Int): Boolean = - ((inputMask(shape) | outputMask(shape)) & 1 << r) != 0 - - def outputMask(shape: Int) = 0 - def inputMask(shape: Int) = 0 - - def getOutput(gate: T, r: Int) = if ((gate.state & 0x10 << r) != 0) 255 else 0 - def getInput(gate: T, mask: Int) = { - var input = 0 - for (r <- 0 until 4) - if ((mask & 1 << r) != 0 && gate.getRedstoneInput(r) > 0) input |= 1 << r - input + case re: IICRedwireEmitter => re.getRedwireSignal(r) + case ip: TPoweredCircuitPart => ip.rsOutputLevel(r) + case _ => 0 } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala new file mode 100644 index 000000000..35cbce2a2 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.circuitparts.wire.IICRedwireEmitter + + +abstract class RedstoneICGateLogic[T <: RedstoneGateICPart] + extends ICGateLogic[T] { + override def canConnectTo(gate: T, part: CircuitPart, r: Int) = part match { + case re: IICRedwireEmitter => canConnect(gate, r) + case _ => false + } + + def canConnect(gate: T, r: Int): Boolean = canConnect(gate.shape, r) + def canConnect(shape: Int, r: Int): Boolean = + ((inputMask(shape) | outputMask(shape)) & 1 << r) != 0 + + def outputMask(shape: Int) = 0 + def inputMask(shape: Int) = 0 + + def getOutput(gate: T, r: Int) = if ((gate.state & 0x10 << r) != 0) 255 else 0 + def getInput(gate: T, mask: Int) = { + var input = 0 + for (r <- 0 until 4) + if ((mask & 1 << r) != 0 && gate.getRedstoneInput(r) > 0) input |= 1 << r + input + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala new file mode 100644 index 000000000..a2c19387e --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.MCDataInput +import mrtjp.projectred.ProjectRedCore.log +import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic +import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic + + +class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart { + var logic: SequentialICGateLogic = null + + override def assertLogic() { + if (logic == null) logic = SequentialICGateLogic.create(this, subID) + } + + override def getLogic[T]: T = logic.asInstanceOf[T] + + override def getPartType = CircuitPartDefs.ComplexGate + + override def readClientPacket(in: MCDataInput, key: Int) = key match { + case 3 => + getLogicPrimitive match { + case t: ITimerGuiLogic => + t.setTimerMax(this, t.getTimerMax + in.readShort()) + case _ => + log.error( + "Server IC stream received client packet for incorrect gate type" + ) + } + case 4 => + getLogicPrimitive match { + case t: ICounterGuiLogic => + val actionID = in.readByte() + actionID match { + case 0 => t.setCounterMax(this, t.getCounterMax + in.readShort()) + case 1 => t.setCounterIncr(this, t.getCounterIncr + in.readShort()) + case 2 => t.setCounterDecr(this, t.getCounterDecr + in.readShort()) + case _ => + log.error( + "Server IC stream received client packet for incorrect gate type" + ) + } + case _ => + log.error( + "Server IC stream received client packet for incorrect gate type" + ) + } + case _ => super.readClientPacket(in, key) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala new file mode 100644 index 000000000..d82a4496c --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.circuitparts.latches._ +import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, Synchronizer} +import mrtjp.projectred.fabrication.circuitparts.timing._ + + +abstract class SequentialICGateLogic(val gate: SequentialGateICPart) + extends RedstoneICGateLogic[SequentialGateICPart] + with TComplexICGateLogic[SequentialGateICPart] + +object SequentialICGateLogic { + + def create(gate: SequentialGateICPart, subID: Int) = subID match { + case ICGateDefinition.SRLatch.ordinal => new SRLatch(gate) + case ICGateDefinition.ToggleLatch.ordinal => new ToggleLatch(gate) + case ICGateDefinition.Timer.ordinal => new Timer(gate) + case ICGateDefinition.Sequencer.ordinal => new Sequencer(gate) + case ICGateDefinition.Counter.ordinal => new Counter(gate) + case ICGateDefinition.StateCell.ordinal => new StateCell(gate) + case ICGateDefinition.Synchronizer.ordinal => new Synchronizer(gate) + case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala new file mode 100644 index 000000000..fa8ad7a91 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.ICPropagator +import mrtjp.projectred.fabrication.circuitparts.wire.IRedwireICPart +import mrtjp.projectred.transmission.IWirePart + +trait TArrayGateICPart + extends RedstoneGateICPart + with IRedwireICPart + with TRSPropagatingICPart { + def getLogicArray = getLogic[TArrayICGateLogic[TArrayGateICPart]] + + override def getSignal = + getLogicArray.getSignal(toInternalMask(propagationMask)) + + override def setSignal(signal: Int) = + getLogicArray.setSignal(toInternalMask(propagationMask), signal) + + abstract override def updateAndPropagate(prev: CircuitPart, mode: Int) { + val rd = sideDiff(prev) + var uMask = 0 + for (r <- 0 until 4) if ((rd & 1 << r) != 0) { + val pMask = getLogicArray.propogationMask(toInternal(r)) + if (pMask > 0 && (pMask & uMask) != pMask) { + propagationMask = toAbsoluteMask(pMask) + super.updateAndPropagate(prev, mode) + uMask |= pMask + } + } + if (uMask == 0) ICPropagator.addNeighborChange(Point(x, y)) + propagationMask = 0xf + } + + override def propagateOther(mode: Int) { + val nonConn = ~(connMap | connMap >> 4 | connMap >> 8) & 0xf + notify(nonConn & propagationMask) + } + + def sideDiff(part: CircuitPart): Int = { + if (part.world == null) return 0xf + val here = Point(x, y) + val there = Point(part.x, part.y) + there - here match { + case Point(0, -1) => 1 << 0 + case Point(1, 0) => 1 << 1 + case Point(0, 1) => 1 << 2 + case Point(-1, 0) => 1 << 3 + case _ => + throw new RuntimeException( + s"Circuit array gate tried to propagate from $here to #$there" + ) + } + } + + override def calculateSignal: Int = { + val ipmask = toInternalMask(propagationMask) + if (getLogicArray.overrideSignal(ipmask)) + return getLogicArray.calculateSignal(ipmask) + + var s = 0 + ICPropagator.redwiresProvidePower = false + + def raise(sig: Int) { + if (sig > s) s = sig + } + + for (r <- 0 until 4) + if ((propagationMask & 1 << r) != 0) raise(calcSignal(r)) + ICPropagator.redwiresProvidePower = true + s + } + + abstract override def onChange() { + super.onChange() + ICPropagator.propagateTo(this, IWirePart.RISING) + } + + override def onSignalUpdate() { + world.network.markSave() + super.onChange() + getLogicArray.onSignalUpdate() + } + + override def resolveSignal(part: Any, r: Int) = part match { + case re: IRedwireICPart if re.diminishOnSide(r) => + re.getRedwireSignal(r) - 1 + case _ => super.resolveSignal(part, r) + } + + override def getRedwireSignal(r: Int) = { + val ir = toInternal(r) + val pmask = getLogicArray.propogationMask(ir) + if (pmask != 0) getLogicArray.getSignal(pmask) + else getLogicRS.getOutput(this, ir) + } + + override def canConnectRS(r: Int): Boolean = { + if (super.canConnectRS(r)) return true + getLogicArray.canConnectRedwire(this, toInternal(r)) + } + + override def rsOutputLevel(r: Int): Int = { + val ir = toInternal(r) + if ((getLogicArray.redwireMask(shape) & 1 << ir) != 0) + return if (ICPropagator.redwiresProvidePower) + getLogicArray.getSignal(getLogicArray.propogationMask(ir)) + else 0 + super.rsOutputLevel(r) + } + + override def diminishOnSide(r: Int) = + (getLogicArray.redwireMask(shape) & 1 << toInternal(r)) != 0 +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayICGateLogic.scala new file mode 100644 index 000000000..52aa1da9f --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayICGateLogic.scala @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.circuitparts.wire.IRedwireICPart + +trait TArrayICGateLogic[T <: TArrayGateICPart] extends RedstoneICGateLogic[T] { + abstract override def canConnectTo(gate: T, part: CircuitPart, r: Int) = + part match { + case re: IRedwireICPart if canConnectRedwire(gate, r) => true + case _ => super.canConnectTo(gate, part, r) + } + + def canConnectRedwire(gate: T, r: Int): Boolean = + canConnectRedwire(gate.shape, r) + + def canConnectRedwire(shape: Int, r: Int): Boolean = + (redwireMask(shape) & 1 << r) != 0 + + def redwireMask(shape: Int): Int + + def propogationMask(r: Int): Int + + def getSignal(mask: Int): Int + + def setSignal(mask: Int, signal: Int) + + def overrideSignal(mask: Int) = false + + def calculateSignal(mask: Int) = 0 + + def canCross = false + + def onSignalUpdate() +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TClientNetCircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TClientNetCircuitPart.scala new file mode 100644 index 000000000..eb97b5693 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TClientNetCircuitPart.scala @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import cpw.mods.fml.relauncher.{Side, SideOnly} + +trait TClientNetCircuitPart extends CircuitPart { + def readClientPacket(in: MCDataInput) + + @SideOnly(Side.CLIENT) + def sendClientPacket(writer: MCDataOutput => Unit = { _ => }) { + world.sendClientPacket(this, writer) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala new file mode 100644 index 000000000..17197cf74 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import net.minecraft.nbt.NBTTagCompound + +trait TComplexGateICPart extends GateICPart { + def getLogicComplex = getLogic[TComplexICGateLogic[TComplexGateICPart]] + + def assertLogic() + + abstract override def save(tag: NBTTagCompound) { + super.save(tag) + getLogicComplex.save(tag) + } + + abstract override def load(tag: NBTTagCompound) { + super.load(tag) + assertLogic() + getLogicComplex.load(tag) + } + + abstract override def writeDesc(packet: MCDataOutput) { + super.writeDesc(packet) + getLogicComplex.writeDesc(packet) + } + + abstract override def readDesc(packet: MCDataInput) { + super.readDesc(packet) + assertLogic() + getLogicComplex.readDesc(packet) + } + + abstract override def read(packet: MCDataInput, key: Int) = key match { + case k if k > 10 => + assertLogic() // this may be a net dump part + getLogicComplex.read(packet, k) + case _ => super.read(packet, key) + } + + abstract override def preparePlacement(rotation: Int, configuration: Int, meta: Int) { + super.preparePlacement(rotation, configuration, meta) + assertLogic() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala new file mode 100644 index 000000000..1d2ee7030 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import net.minecraft.nbt.NBTTagCompound + +trait TComplexICGateLogic[T <: TComplexGateICPart] extends ICGateLogic[T] { + def save(tag: NBTTagCompound) {} + + def load(tag: NBTTagCompound) {} + + def readDesc(packet: MCDataInput) {} + + def writeDesc(packet: MCDataOutput) {} + + /** Allocated keys > 10 + */ + def read(packet: MCDataInput, key: Int) {} +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TConnectableICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TConnectableICPart.scala new file mode 100644 index 000000000..b9c154bae --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TConnectableICPart.scala @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +trait TConnectableICPart extends CircuitPart with TICAcquisitions { + var connMap: Byte = 0 + + def maskConnects(r: Int) = (connMap & 1 << r) != 0 + + def discover(r: Int) = getStraight(r) match { + case c: TConnectableICPart => + canConnectPart(c, r) && c.connect(this, rotFromStraight(r)) + case c => discoverOverride(r, c) + } + + def discoverOverride(r: Int, part: CircuitPart) = false + + def connect(part: CircuitPart, r: Int) = { + if (canConnectPart(part, r)) { + val oldConn = connMap + connMap = (connMap | 1 << r).toByte + if (oldConn != connMap) onMaskChanged() + true + } else false + } + + def updateConns() = { + var newConn = 0 + for (r <- 0 until 4) if (discover(r)) newConn |= 1 << r + if (newConn != connMap) { + connMap = newConn.toByte + onMaskChanged() + true + } else false + } + + def canConnectPart(part: CircuitPart, r: Int): Boolean + + def onMaskChanged() {} +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TErrorCircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TErrorCircuitPart.scala new file mode 100644 index 000000000..12e73b7b2 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TErrorCircuitPart.scala @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +trait TErrorCircuitPart extends CircuitPart { + def postErrors: (String, Int) // (message, colour) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala new file mode 100644 index 000000000..0b7288373 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import net.minecraft.nbt.NBTTagCompound + +trait TExtraStateLogic extends SequentialICGateLogic { + private var lState2: Byte = 0 + + def state2 = lState2 & 0xff + + def setState2(state: Int) { + lState2 = state.toByte + } + + def clientState2 = false + + abstract override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("state2", lState2) + } + + abstract override def load(tag: NBTTagCompound) { + super.load(tag) + lState2 = tag.getByte("state2") + } + + abstract override def writeDesc(packet: MCDataOutput) { + super.writeDesc(packet) + if (clientState2) packet.writeByte(lState2) + } + + abstract override def readDesc(packet: MCDataInput) { + super.readDesc(packet) + if (clientState2) lState2 = packet.readByte() + } + + abstract override def read(packet: MCDataInput, key: Int) = key match { + case 11 => lState2 = packet.readByte() + case _ => super.read(packet, key) + } + + def sendState2Update() { + gate.writeStreamOf(11).writeByte(lState2) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICAcquisitions.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICAcquisitions.scala new file mode 100644 index 000000000..e9a7641aa --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICAcquisitions.scala @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.core.vec.Point + +trait TICAcquisitions extends CircuitPart { + def getStraight(r: Int) = world.getPart(posOfStraight(r)) + + def posOfStraight(r: Int) = Point(x, y).offset(r) + + def rotFromStraight(r: Int) = (r + 2) % 4 + + def notifyToDir(r: Int) { + world.notifyNeighbor(posOfStraight(r)) + } + + def notify(mask: Int) { + world.notifyNeighbors(x, y, mask) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala new file mode 100644 index 000000000..9f5658084 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + + +trait TICBundledAcquisitions extends TICAcquisitions { + def calcArray(r: Int): Array[Byte] = + resolveArray(getStraight(r), rotFromStraight(r)) + + def resolveArray(part: Any, r: Int): Array[Byte] +} + + + + + + diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICOrient.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICOrient.scala new file mode 100644 index 000000000..c0b5d0cf6 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICOrient.scala @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import codechicken.lib.vec.{Rotation, Vector3} + +trait TICOrient extends CircuitPart { + var orientation: Byte = 0 + + def rotation = orientation & 0x3 + + def setRotation(r: Int) { + orientation = (orientation & 0xfc | r).toByte + } + + def rotationT = + Rotation.quarterRotations(rotation).at(new Vector3(0.5, 0, 0.5)) + + // internal r from absRot + def toInternal(absRot: Int) = (absRot + 4 - rotation) % 4 + + // absRot from internal r + def toAbsolute(r: Int) = (r + rotation) % 4 + + def toInternalMask(mask: Int) = TICOrient.shiftMask(mask, toInternal(0)) + + def toAbsoluteMask(mask: Int) = TICOrient.shiftMask(mask, toAbsolute(0)) +} + +object TICOrient { + def shiftMask(mask: Int, r: Int) = + (mask & ~0xf) | (mask << r | mask >> 4 - r) & 0xf + + def flipMaskZ(mask: Int) = mask & 5 | mask << 2 & 8 | mask >> 2 & 2 +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICRSAcquisitions.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICRSAcquisitions.scala new file mode 100644 index 000000000..fd82e77e5 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICRSAcquisitions.scala @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +trait TICRSAcquisitions extends TICAcquisitions with TPoweredCircuitPart { + def calcSignal(r: Int): Int = + resolveSignal(getStraight(r), rotFromStraight(r)) + + def resolveSignal(part: Any, r: Int): Int +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPoweredCircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPoweredCircuitPart.scala new file mode 100644 index 000000000..5b3aea5e2 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPoweredCircuitPart.scala @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +trait TPoweredCircuitPart { + def rsOutputLevel(r: Int): Int + + def canConnectRS(r: Int): Boolean +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala new file mode 100644 index 000000000..caff02c03 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.core.vec.Point +import IWireICPart.FORCED +import mrtjp.projectred.fabrication.ICPropagator + +trait TPropagatingICPart + extends CircuitPart + with TConnectableICPart + with IWireICPart { + var propagationMask = 0xf + + def propagate(prev: CircuitPart, mode: Int) { + if (mode != FORCED) ICPropagator.addPartChange(this) + for (r <- 0 until 4) + if ((propagationMask & 1 << r) != 0) + if (maskConnects(r)) + propagateExternal(getStraight(r), posOfStraight(r), prev, mode) + + propagateOther(mode) + } + + def propagateOther(mode: Int) {} + + def propagateExternal( + to: CircuitPart, + at: Point, + from: CircuitPart, + mode: Int + ) { + if (to != null) { + if (to == from) return + if (propagateTo(to, mode)) return + } + ICPropagator.addNeighborChange(at) + } + + def propagateTo(part: CircuitPart, mode: Int) = part match { + case w: IWireICPart => + ICPropagator.propagateTo(w, this, mode) + true + case _ => false + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TRSPropagatingICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TRSPropagatingICPart.scala new file mode 100644 index 000000000..a384e1327 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TRSPropagatingICPart.scala @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import mrtjp.projectred.fabrication.ICPropagator +import IWireICPart._ + +trait TRSPropagatingICPart extends TPropagatingICPart { + def calculateSignal: Int + + def getSignal: Int + + def setSignal(signal: Int) + + override def updateAndPropagate(prev: CircuitPart, mode: Int) { + if (mode == DROPPING && getSignal == 0) return + val newSignal = calculateSignal + if (newSignal < getSignal) { + if (newSignal > 0) ICPropagator.propagateAnalogDrop(this) + setSignal(0) + propagate(prev, DROPPING) + } else if (newSignal > getSignal) { + setSignal(newSignal) + if (mode == DROPPING) propagate(null, RISING) + else propagate(prev, RISING) + } else if (mode == DROPPING) propagateTo(prev, RISING) + else if (mode == FORCE) propagate(prev, FORCED) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala new file mode 100644 index 000000000..90254792d --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts + +import cpw.mods.fml.relauncher.{Side, SideOnly} + + +trait TSimpleRSICGateLogic[T <: RedstoneGateICPart] + extends RedstoneICGateLogic[T] { + def getDelay(shape: Int) = 0 + + def feedbackMask(shape: Int) = 0 + + def calcOutput(gate: T, input: Int) = 0 + + override def onChange(gate: T) { + val iMask = inputMask(gate.shape) + val oMask = outputMask(gate.shape) + val fMask = feedbackMask(gate.shape) + val oldInput = gate.state & 0xf + val newInput = getInput(gate, iMask | fMask) + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + } + + val newOutput = calcOutput(gate, gate.state & iMask) & oMask + if (newOutput != (gate.state >> 4)) gate.scheduleTick(getDelay(gate.shape)) + } + + override def scheduledTick(gate: T) { + val iMask = inputMask(gate.shape) + val oMask = outputMask(gate.shape) + val oldOutput = gate.state >> 4 + val newOutput = calcOutput(gate, gate.state & iMask) & oMask + if (oldOutput != newOutput) { + gate.setState(gate.state & 0xf | newOutput << 4) + gate.onOutputChange(oMask) + } + onChange(gate) + } + + override def setup(gate: T) { + val iMask = inputMask(gate.shape) + val oMask = outputMask(gate.shape) + val output = calcOutput(gate, getInput(gate, iMask)) & oMask + if (output != 0) { + gate.setState(output << 4) + gate.onOutputChange( + output + ) // use output for change mask because nothing is going low + } + } + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: T, detailLevel: Int) = { + val s = Seq.newBuilder[String] + if (detailLevel > 2) + s += "I: " + rolloverInput(gate) += "O: " + rolloverOutput(gate) + super.getRolloverData(gate, detailLevel) ++ s.result() + } + def rolloverInput(gate: T) = "0x" + Integer.toHexString(gate.state & 0xf) + def rolloverOutput(gate: T) = "0x" + Integer.toHexString(gate.state >> 4) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala new file mode 100644 index 000000000..0c1e2fdd1 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.cells + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} + + +class BufferCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { + override def powerUp = (gate.state & 2) == 0 +} + + +class RenderBufferCell extends ICGateRenderer[ArrayGateICPart] { + val wires = generateWireModels("BUFFCELL", 2) + val torches = + Seq(new RedstoneTorchModel(11, 13), new RedstoneTorchModel(8, 8)) + val top = new CellTopWireModel + val bottom = new InvertCellBottomWireModel + + override val coreModels = + Seq(new BaseComponentModel("BUFFCELL")) ++ wires ++ Seq( + bottom + ) ++ torches ++ Seq(new CellStandModel, top) + + override def prepareStatic(configuration: Int): Unit = { + bottom.signal = 0 + top.signal = 0 + wires(0).on = false + wires(1).on = true + torches(0).on = true + torches(1).on = false + } + + override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { + val logic = gate.getLogic[BufferCell] + bottom.signal = logic.signal1 + top.signal = logic.signal2 + torches(0).on = logic.signal1 == 0 + torches(1).on = logic.signal1 != 0 + wires(0).on = logic.signal1 != 0 + wires(1).on = logic.signal1 == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala new file mode 100644 index 000000000..49667a274 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.cells + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} + + +class InvertCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { + override def powerUp = (gate.state & 2) != 0 +} + + +class RenderInvertCell extends ICGateRenderer[ArrayGateICPart] { + val wires = generateWireModels("INVCELL", 1) + val torch = new RedstoneTorchModel(8, 8) + val top = new CellTopWireModel + val bottom = new InvertCellBottomWireModel + + override val coreModels = Seq( + new BaseComponentModel("INVCELL") + ) ++ wires ++ Seq(bottom, torch, new CellStandModel, top) + + override def prepareStatic(configuration: Int): Unit = { + bottom.signal = 0 + top.signal = 255.toByte + wires(0).on = false + torch.on = true + } + + override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { + val logic = gate.getLogic[InvertCell] + bottom.signal = logic.signal1 + top.signal = logic.signal2 + wires(0).on = logic.signal1 != 0 + torch.on = logic.signal1 == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala new file mode 100644 index 000000000..9e31e49ae --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.cells + +import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, CellStandModel, CellTopWireModel, NullCellBottomWireModel} + + +class NullCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { + override def powerUp = false +} + + +class RenderNullCell extends ICGateRenderer[ArrayGateICPart] { + val top = new CellTopWireModel + val bottom = new NullCellBottomWireModel + + override val coreModels = + Seq(new BaseComponentModel("NULLCELL"), bottom, new CellStandModel, top) + + override def prepareStatic(configuration: Int): Unit = { + bottom.signal = 0 + top.signal = 0 + } + + override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { + bottom.signal = gate.getLogic[NullCell].signal1 + top.signal = gate.getLogic[NullCell].signal2 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala new file mode 100644 index 000000000..5fd1c4f72 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import mrtjp.projectred.fabrication.ICComponentStore.signalColour + + +class AnalogIOICGateLogic(gate: IOGateICPart) + extends IOICGateLogic(gate) + with TFreqIOICGateLogic + with TRSIOICGateLogic { + override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Analog + + override def getFreqName = "0x" + Integer.toHexString(freq) + + override def toggleWorldInput() { + val newInput = (gate.world.iostate(gate.rotation) & 1 << freq) ^ 1 << freq + gate.world.setInput(gate.rotation, if (newInput == 0) 1 else newInput) + } +} + +class RenderAnalogIO extends RenderIO { + override def invColour = signalColour(0.toByte) + override def dynColour(gate: IOGateICPart) = signalColour( + (gate.getLogic[AnalogIOICGateLogic].freq * 17).toByte + ) +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala new file mode 100644 index 000000000..8133a54d9 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import mrtjp.core.color.Colors + + +class BundledIOICGateLogic(gate: IOGateICPart) + extends IOICGateLogic(gate) + with TFreqIOICGateLogic { + override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Bundled + + override def getFreqName = Colors(freq).name.toLowerCase + + override def toggleWorldInput() { + gate.world.setInput( + gate.rotation, + (gate.world.iostate(gate.rotation) & 0xffff) ^ 1 << freq + ) + } +} + +class RenderBundledIO extends RenderIO { + override def invColour = Colors(0).rgba + override def dynColour(gate: IOGateICPart) = Colors( + gate.getLogic[AnalogIOICGateLogic].freq + ).rgba +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala new file mode 100644 index 000000000..44d5677b0 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import codechicken.lib.data.MCDataInput +import mrtjp.projectred.fabrication.circuitparts.{CircuitPartDefs, RedstoneGateICPart, TComplexGateICPart} + +class IOGateICPart + extends RedstoneGateICPart + with TIOCircuitPart + with TComplexGateICPart { + private var logic: IOICGateLogic = null + + override def getLogic[T] = logic.asInstanceOf[T] + + def getLogicIO = getLogic[IOICGateLogic] + + override def assertLogic() { + if (logic == null) logic = IOICGateLogic.create(this, subID) + } + + override def readClientPacket(in: MCDataInput, key: Int) = key match { + case 5 => + getLogicIO match { + case f: TFreqIOICGateLogic => f.freqUp() + case _ => + } + case 6 => + getLogicIO match { + case f: TFreqIOICGateLogic => f.freqDown() + case _ => + } + case _ => super.readClientPacket(in, key) + } + + override def getPartType = CircuitPartDefs.IOGate + + override def onExtInputChanged(r: Int) { + if (r == rotation) getLogicIO.extInputChange(this) + } + + override def onExtOutputChanged(r: Int) { + if (r == rotation) getLogicIO.extOutputChange(this) + } + + override def getIOSide = rotation + + override def getIOMode = getLogicIO.getIOMode(this) + + override def getConnMode = getLogicIO.getConnMode(this) + + override def getRedstoneInput(r: Int): Int = { + if (r == 0) getLogicIO.resolveInputFromWorld // r is to outside world + else super.getRedstoneInput(r) + } + + override def onOutputChange(mask: Int) { + super.onOutputChange(mask) + if ((mask & 1) != 0) { + val oldOutput = world.iostate(rotation) >>> 16 + getLogicIO.setWorldOutput((state & 0x10) != 0) + val newOutput = world.iostate(rotation) >>> 16 + if (oldOutput != newOutput) world.onOutputChanged(1 << rotation) + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala new file mode 100644 index 000000000..4a6f07df3 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.circuitparts.{ICGateDefinition, RedstoneICGateLogic, TComplexICGateLogic, TICOrient} + + +object IOICGateLogic { + def create(gate: IOGateICPart, subID: Int) = subID match { + case ICGateDefinition.IOSimple.ordinal => new SimpleIOICGateLogic(gate) + case ICGateDefinition.IOAnalog.ordinal => new AnalogIOICGateLogic(gate) + case ICGateDefinition.IOBundled.ordinal => new BundledIOICGateLogic(gate) + case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) + } +} + +abstract class IOICGateLogic(val gate: IOGateICPart) + extends RedstoneICGateLogic[IOGateICPart] + with TComplexICGateLogic[IOGateICPart] { + + import TIOCircuitPart._ + + override def inputMask(shape: Int) = shape match { + case 0 => 1 + case 1 => 4 + case 2 => 5 + } + + override def outputMask(shape: Int) = shape match { + case 0 => 4 + case 1 => 1 + case 2 => 5 + } + + override def cycleShape(gate: IOGateICPart) = { + gate.setShape((gate.shape + 1) % 3) + true + } + + def extInputChange(gate: IOGateICPart) { + gate.onChange() + } + + def extOutputChange(gate: IOGateICPart) {} + + def getIOMode(gate: IOGateICPart): Int = gate.shape match { + case 0 => Input + case 1 => Output + case 2 => InOut + } + + def getConnMode(gate: IOGateICPart): Int + + def resolveInputFromWorld: Int + + def resolveOutputToWorld: Int + + def setWorldOutput(state: Boolean) + + def toggleWorldInput() + + override def onChange(gate: IOGateICPart) { + val oldInput = gate.state & 0xf + val newInput = getInput(gate, ~(gate.state >> 4) & inputMask(gate.shape)) + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + gate.scheduleTick(0) + } + } + + override def scheduledTick(gate: IOGateICPart) { + val oldOutput = gate.state >> 4 + val newOutput = + TICOrient.shiftMask(gate.state & 0xf, 2) & outputMask(gate.shape) + if (oldOutput != newOutput) { + gate.setState(gate.state & 0xf | newOutput << 4) + gate.onOutputChange(oldOutput ^ newOutput) + } + onChange(gate) + } + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: IOGateICPart, detailLevel: Int) = { + val s = Seq.newBuilder[String] + if (detailLevel >= 2) { + val f = getFreqName + if (f.nonEmpty) s += "freq: " + f + s += "mode: " + (gate.shape match { + case 0 => "I" + case 1 => "O" + case 2 => "IO" + }) + } + if (detailLevel >= 3) { + s += "I: " + (if (resolveInputFromWorld != 0) "high" else "low") + s += "O: " + (if (resolveOutputToWorld != 0) "high" else "low") + } + super.getRolloverData(gate, detailLevel) ++ s.result() + } + + def getFreqName = "" + + override def activate(gate: IOGateICPart) { + toggleWorldInput() + gate.world.onInputChanged(1 << gate.rotation) + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/RenderIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/RenderIO.scala new file mode 100644 index 000000000..944e22cd5 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/RenderIO.scala @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.ICGateRenderer +import mrtjp.projectred.fabrication.{BaseComponentModel, IOSigModel} + +abstract class RenderIO extends ICGateRenderer[IOGateICPart] { + val wires = generateWireModels("IOSIMP", 1) + val iosig = new IOSigModel + + override val coreModels = + Seq(new BaseComponentModel("IOSIMP")) ++ wires :+ iosig + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + iosig.on = false + iosig.colour = invColour + } + + override def prepareDynamic(gate: IOGateICPart, frame: Float) { + wires(0).on = (gate.state & 0x44) != 0 + iosig.on = wires(0).on + iosig.colour = dynColour(gate) + } + + def invColour: Int + + def dynColour(gate: IOGateICPart): Int +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala new file mode 100644 index 000000000..34e5d9b13 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore.signalColour +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICIOGateGui} + + +class SimpleIOICGateLogic(gate: IOGateICPart) + extends IOICGateLogic(gate) + with TRSIOICGateLogic { + override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Simple + + override def resolveInputFromWorld = + if ((gate.world.iostate(gate.rotation) & 0xfffe) != 0) 255 + else 0 + + override def resolveOutputToWorld = + if (((gate.world.iostate(gate.rotation) >> 16) & 0xfffe) != 0) 255 else 0 + + override def setWorldOutput(state: Boolean) { + gate.world.setOutput(gate.rotation, if (state) 0x8000 else 1) + } + + override def toggleWorldInput() { + gate.world.setInput( + gate.rotation, + if ((gate.world.iostate(gate.rotation) & 0x8000) != 0) 1 else 0x8000 + ) + } + + @SideOnly(Side.CLIENT) + override def createGui(gate: IOGateICPart): CircuitGui = new ICIOGateGui(gate) +} + +class RenderSimpleIO extends RenderIO { + override def invColour = signalColour(0.toByte) + override def dynColour(gate: IOGateICPart) = signalColour( + (if (iosig.on) 255 else 0).toByte + ) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala new file mode 100644 index 000000000..3fa8b721a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICIOFreqGateGui} +import net.minecraft.nbt.NBTTagCompound + +trait TFreqIOICGateLogic extends IOICGateLogic { + var freq = 0 + + override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("freq", freq.toByte) + } + + override def load(tag: NBTTagCompound) { + super.load(tag) + freq = tag.getByte("freq") + } + + override def writeDesc(out: MCDataOutput) { + super.writeDesc(out) + out.writeByte(freq) + } + + override def readDesc(in: MCDataInput) { + super.readDesc(in) + freq = in.readUByte() + } + + override def read(in: MCDataInput, key: Int) = key match { + case 12 => freq = in.readUByte() + case _ => super.read(in, key) + } + + def sendFreqUpdate() { + gate.writeStreamOf(12).writeByte(freq) + } + + def freqUp() { + if (freq < 15) { + freq += 1 + sendFreqUpdate() + gate.onChange() + } + } + + def freqDown() { + if (freq > 0) { + freq -= 1 + sendFreqUpdate() + gate.onChange() + } + } + + override def resolveInputFromWorld = + if ((gate.world.iostate(gate.rotation) & 1 << freq) != 0) 255 + else 0 + + override def resolveOutputToWorld = + if ((gate.world.iostate(gate.rotation) >>> 16 & 1 << freq) != 0) 255 + else 0 + + override def setWorldOutput(state: Boolean) { + val s = + ((gate.world.iostate(gate.rotation) >>> 16) & ~(1 << freq)) | (if (state) + 1 + else + 0) << freq + gate.world.setOutput(gate.rotation, s) + } + + @SideOnly(Side.CLIENT) + override def createGui(gate: IOGateICPart): CircuitGui = new ICIOFreqGateGui( + gate + ) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala new file mode 100644 index 000000000..5cb8dc06b --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +object TIOCircuitPart { + val Closed = 0 + val Input = 1 + val Output = 2 + val InOut = 3 + + val NoConn = 0 + val Simple = 1 + val Analog = 2 + val Bundled = 3 +} + +trait TIOCircuitPart { + def onExtInputChanged(r: Int) + + def onExtOutputChanged(r: Int) + + def getIOSide: Int + + def getIOMode: Int + + def getConnMode: Int +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TRSIOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TRSIOICGateLogic.scala new file mode 100644 index 000000000..422f72504 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TRSIOICGateLogic.scala @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.io + +trait TRSIOICGateLogic extends IOICGateLogic { + override def setup(gate: IOGateICPart) { + if ((gate.world.iostate(gate.rotation) & 0xffff) == 0) { + gate.world.setInput(gate.rotation, 1) + gate.world.onInputChanged(1 << gate.rotation) + } + } + + override def extInputChange(gate: IOGateICPart) { + if ((gate.world.iostate(gate.rotation) & 0xffff) == 0) { + gate.world.setInput(gate.rotation, 1) + gate.world.onInputChanged(1 << gate.rotation) + } + super.extInputChange(gate) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala new file mode 100644 index 000000000..22cd2d2b4 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.latches + +import mrtjp.projectred.core.TFaceOrient.{flipMaskZ, shiftMask} +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +class SRLatch(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with TExtraStateLogic { + override def outputMask(shape: Int) = if ((shape >> 1) == 0) 0xf else 5 + override def inputMask(shape: Int) = 0xa + + override def cycleShape(gate: SequentialGateICPart) = { + gate.setShape((gate.shape + 1) % 4) + setState2(flipMaskZ(state2)) + gate.setState(flipMaskZ(gate.state)) + gate.onOutputChange(0xf) + gate.scheduleTick(0) + true + } + + override def setup(gate: SequentialGateICPart) { + setState2(2) + gate.setState(0x30) + } + + override def onChange(gate: SequentialGateICPart) { + val stateInput = state2 + + val oldInput = gate.state & 0xf + val newInput = getInput(gate, 0xa) + val oldOutput = gate.state >> 4 + + if (newInput != oldInput) + if ( + stateInput != 0xa && newInput != 0 && newInput != stateInput + ) // state needs changing + { + gate.setState(newInput) + setState2(newInput) + gate.onOutputChange(oldOutput) // always going low + gate.scheduleTick(0) + } else { + gate.setState(oldOutput << 4 | newInput) + gate.onInputChange() + } + } + + override def scheduledTick(gate: SequentialGateICPart) { + val oldOutput = gate.state >> 4 + val newOutput = calcOutput(gate) + + if (oldOutput != newOutput) { + gate.setState(gate.state & 0xf | newOutput << 4) + gate.onOutputChange(outputMask(gate.shape)) + } + onChange(gate) + } + + def calcOutput(gate: SequentialGateICPart): Int = { + var input = gate.state & 0xf + var stateInput = state2 + + if ((gate.shape & 1) != 0) // reverse + { + input = flipMaskZ(input) + stateInput = flipMaskZ(stateInput) + } + + if (stateInput == 0xa) // disabled + { + if (input == 0xa) { + gate.scheduleTick(0) + return 0 + } + + stateInput = + if (input == 0) + if (gate.world.network.getWorld.rand.nextBoolean()) 2 else 8 + else input + + setState2( + if ((gate.shape & 1) != 0) flipMaskZ(stateInput) else stateInput + ) + } + + var output = shiftMask(stateInput, 1) + if ((gate.shape & 2) == 0) output |= stateInput + if ((gate.shape & 1) != 0) output = flipMaskZ(output) // reverse + output + } +} + + +class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { + val wires1 = generateWireModels("RSLATCH", 2) + val wires2 = generateWireModels("RSLATCH2", 4) + val torches1 = + Seq(new RedstoneTorchModel(8, 3), new RedstoneTorchModel(8, 13)) + val torches2 = + Seq(new RedstoneTorchModel(9.5, 3), new RedstoneTorchModel(6.5, 13)) + val base1 = new BaseComponentModel("RSLATCH") + val base2 = new BaseComponentModel("RSLATCH2") + + val m1 = Seq(base1) ++ wires1 ++ torches1 + val m2 = Seq(base2) ++ wires2 ++ torches2 + + var shape = 0 + + override val coreModels = Seq() + + override def switchModels = if (shape == 0) m1 else m2 + + override def prepareStatic(configuration: Int): Unit = { + reflect = false + shape = 0 + wires1(0).on = false + wires1(1).on = true + torches1(0).on = false + torches1(1).on = true + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + reflect = (gate.shape & 1) != 0 + shape = gate.shape >> 1 + var state = gate.state + if (reflect) state = flipMaskZ(state >> 4) << 4 | flipMaskZ(state) + if (shape == 0) { + wires1(0).on = (state & 0x88) != 0 + wires1(1).on = (state & 0x22) != 0 + torches1(0).on = (state & 0x10) != 0 + torches1(1).on = (state & 0x40) != 0 + } else { + wires2(1).on = (state & 2) != 0 + wires2(3).on = (state & 8) != 0 + torches2(0).on = (state & 0x10) != 0 + torches2(1).on = (state & 0x40) != 0 + wires2(0).on = torches2(1).on + wires2(2).on = torches2(0).on + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala new file mode 100644 index 000000000..14b70b24a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.latches + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} +import mrtjp.projectred.fabrication.{BaseComponentModel, LeverModel, RedstoneTorchModel} + + +class ToggleLatch(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with TExtraStateLogic { + override def outputMask(shape: Int) = 5 + override def inputMask(shape: Int) = 0xa + + override def clientState2 = true + + override def setup(gate: SequentialGateICPart) { + gate.setState(0x10) + gate.sendStateUpdate() + } + + override def onChange(gate: SequentialGateICPart) { + val oldInput = gate.state & 0xf + val newInput = getInput(gate, 0xa) + val high = newInput & ~oldInput + + if (high == 2 || high == 8) toggle(gate) + + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + } + } + + override def scheduledTick(gate: SequentialGateICPart) { + val oldOutput = gate.state >> 4 + val newOutput = if (state2 == 0) 1 else 4 + if (oldOutput != newOutput) { + gate.setState(newOutput << 4 | gate.state & 0xf) + gate.onOutputChange(5) + } + onChange(gate) + } + + override def activate(gate: SequentialGateICPart) { + toggle(gate) + } + + def toggle(gate: SequentialGateICPart) { + setState2(state2 ^ 1) + gate.scheduleTick(0) + } +} + + +class RenderToggleLatch extends ICGateRenderer[SequentialGateICPart] { + val wires = generateWireModels("TOGLATCH", 2) + val torches = Seq(new RedstoneTorchModel(4, 4), new RedstoneTorchModel(4, 12)) + val lever = new LeverModel(11, 8) + + override val coreModels = + Seq(new BaseComponentModel("TOGLATCH")) ++ wires ++ torches :+ lever + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(1).on = false + torches(0).on = true + torches(1).on = false + lever.on = true + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + wires(0).on = (gate.state & 8) != 0 + wires(1).on = (gate.state & 2) != 0 + torches(0).on = (gate.state & 0x10) != 0 + torches(1).on = (gate.state & 0x40) != 0 + lever.on = (gate.state & 0x10) != 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala new file mode 100644 index 000000000..e93a07ac5 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.latches + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object TransparentLatch extends ComboICGateLogic { + override def outputMask(shape: Int) = if (shape == 0) 3 else 9 + override def inputMask(shape: Int) = if (shape == 0) 0xc else 6 + + override def cycleShape(shape: Int) = shape ^ 1 + + override def calcOutput(gate: ComboICGatePart, input: Int) = { + if ((input & 4) == 0) gate.state >> 4 + else if ((input & 0xa) == 0) 0 + else 0xf + } +} + +class RenderTransparentLatch extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("TRANSLATCH", 5) + val torches = Seq( + new RedstoneTorchModel(4, 12.5), + new RedstoneTorchModel(4, 8), + new RedstoneTorchModel(8, 8), + new RedstoneTorchModel(8, 2), + new RedstoneTorchModel(14, 8) + ) + + override val coreModels = + Seq(new BaseComponentModel("TRANSLATCH")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + reflect = false + wires(0).on = true + wires(1).on = false + wires(2).on = true + wires(3).on = false + wires(4).on = false + torches(0).on = true + torches(1).on = false + torches(2).on = true + torches(3).on = false + torches(4).on = false + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + reflect = gate.shape == 1 + val on = (gate.state & 0x10) != 0 + wires(0).on = !on + wires(1).on = (gate.state & 4) != 0 + wires(2).on = (gate.state & 4) == 0 + wires(3).on = on + wires(4).on = (gate.state & 0xa) != 0 + torches(0).on = wires(2).on + torches(1).on = !wires(2).on && !wires(4).on + torches(2).on = !wires(1).on && !wires(3).on + torches(3).on = on + torches(4).on = on + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala new file mode 100644 index 000000000..a69f313f2 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.misc + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.math.MathHelper +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.core.TFaceOrient.flipMaskZ +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICCounterGateGui} +import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import net.minecraft.nbt.NBTTagCompound + + +trait ICounterGuiLogic { + def getCounterMax: Int + def setCounterMax(gate: GateICPart, i: Int) + + def getCounterIncr: Int + def setCounterIncr(gate: GateICPart, i: Int) + + def getCounterDecr: Int + def setCounterDecr(gate: GateICPart, i: Int) + + def getCounterValue: Int + def setCounterValue(gate: GateICPart, i: Int) +} + + +class Counter(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with ICounterGuiLogic { + var value = 0 + var max = 10 + var incr = 1 + var decr = 1 + + override def outputMask(shape: Int) = 5 + override def inputMask(shape: Int) = 10 + + override def save(tag: NBTTagCompound) { + tag.setInteger("val", value) + tag.setInteger("max", max) + tag.setInteger("inc", incr) + tag.setInteger("dec", decr) + } + + override def load(tag: NBTTagCompound) { + value = tag.getInteger("val") + max = tag.getInteger("max") + incr = tag.getInteger("inc") + decr = tag.getInteger("dec") + } + + override def writeDesc(packet: MCDataOutput) { + packet.writeInt(value).writeInt(max).writeInt(incr).writeInt(decr) + } + + override def readDesc(packet: MCDataInput) { + value = packet.readInt() + max = packet.readInt() + incr = packet.readInt() + decr = packet.readInt() + } + + override def read(packet: MCDataInput, key: Int) = key match { + case 11 => value = packet.readInt() + case 12 => max = packet.readInt() + case 13 => incr = packet.readInt() + case 14 => decr = packet.readInt() + case _ => + } + + def sendValueUpdate() { gate.writeStreamOf(11).writeInt(value) } + def sendMaxUpdate() { gate.writeStreamOf(12).writeInt(max) } + def sendIncrUpdate() { gate.writeStreamOf(13).writeInt(incr) } + def sendDecrUpdate() { gate.writeStreamOf(14).writeInt(decr) } + + override def getCounterValue = value + override def getCounterMax = max + override def getCounterIncr = incr + override def getCounterDecr = decr + + override def setCounterValue(gate: GateICPart, i: Int) { + val oldVal = value + value = Math.min(max, Math.max(0, i)) + if (value != oldVal) + sendValueUpdate() + } + + override def setCounterMax(gate: GateICPart, i: Int) { + val oldMax = max + max = Math.min(32767, Math.max(1, i)) + if (max != oldMax) { + sendMaxUpdate() + val oldVal = value + value = Math.min(value, Math.max(0, i)) + if (value != oldVal) { + sendValueUpdate() + gate.scheduleTick(2) + } + } + } + + override def setCounterIncr(gate: GateICPart, i: Int) { + val oldIncr = incr + incr = Math.min(max, Math.max(1, i)) + if (incr != oldIncr) + sendIncrUpdate() + } + + override def setCounterDecr(gate: GateICPart, i: Int) { + val oldDecr = decr + decr = Math.min(max, Math.max(1, i)) + if (decr != oldDecr) + sendDecrUpdate() + } + + def onChange(gate: SequentialGateICPart) { + val oldInput = gate.state & 0xf + var newInput = getInput(gate, 0xa) + if (gate.shape == 1) newInput = flipMaskZ(newInput) + val high = newInput & ~oldInput + + if ((high & 2) != 0) setCounterValue(gate, value + incr) + if ((high & 8) != 0) setCounterValue(gate, value - decr) + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + gate.scheduleTick(2) + } + } + + override def cycleShape(gate: SequentialGateICPart) = { + gate.setShape(if (gate.shape == 1) 0 else 1) + true + } + + def scheduledTick(gate: SequentialGateICPart) { + val oldOutput = gate.state + var newOutput = 0 + if (value == max) newOutput = 1 + else if (value == 0) newOutput = 4 + if (newOutput != oldOutput) gate.setState(gate.state & 0xf | newOutput << 4) + if (newOutput != oldOutput) gate.onOutputChange(5) + } + + @SideOnly(Side.CLIENT) + override def createGui(gate: SequentialGateICPart): CircuitGui = + new ICCounterGateGui(gate) + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + if (detailLevel > 1) { + data += "state: " + getCounterValue + if (detailLevel > 2) { + data += "max: " + getCounterMax + data += "incr: " + getCounterIncr + data += "decr: " + getCounterDecr + } + } + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} + + +class RenderCounter extends ICGateRenderer[SequentialGateICPart] { + val wires = generateWireModels("COUNT", 2) + val torches = Seq( + new RedstoneTorchModel(11, 8), + new RedstoneTorchModel(8, 3), + new RedstoneTorchModel(8, 13) + ) + val pointer = new PointerModel(11, 8, 1.2d) + + torches(0).on = true + + override val coreModels = + Seq(new BaseComponentModel("COUNT")) ++ wires ++ Seq(pointer) ++ torches + + override def prepareStatic(configuration: Int): Unit = { + reflect = false + wires(0).on = false + wires(1).on = false + torches(1).on = false + torches(2).on = true + pointer.angle = 220 * MathHelper.torad + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + reflect = gate.shape == 1 + wires(0).on = (gate.state & 8) != 0 + wires(1).on = (gate.state & 2) != 0 + torches(1).on = (gate.state & 0x10) != 0 + torches(2).on = (gate.state & 0x40) != 0 + + val max = gate.getLogic[Counter].max + val value = gate.getLogic[Counter].value + pointer.angle = + (value / max.toDouble * (340 - 220) + 210) * MathHelper.torad + if (gate.shape == 1) reflect = true + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala new file mode 100644 index 000000000..b80176f31 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.misc + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedChipModel, RedstoneTorchModel, YellowChipModel} + +import java.util.Random + + +object DecRandomizer extends ComboICGateLogic { + val rand = new Random + + override def cycleShape(shape: Int) = shape ^ 1 + + override def outputMask(shape: Int) = if (shape == 0) 11 else 9 + override def inputMask(shape: Int) = 4 + override def feedbackMask(shape: Int) = 2 + + override def getDelay(shape: Int) = 2 + + override def calcOutput(gate: ComboICGatePart, input: Int) = { + if (input == 0) if ((gate.state >> 4) == 0) 1 else gate.state >> 4 + else Seq(1, 8, 2)(rand.nextInt((~gate.shape | 2) & 3)) + } + + override def onChange(gate: ComboICGatePart) { + super.onChange(gate) + if ((gate.state & 4) != 0) gate.scheduleTick(2) + } +} + + +class RenderDecRandomizer extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("DECRAND", 6) + val chips = Seq( + new YellowChipModel(5, 13), + new YellowChipModel(11, 13), + new RedChipModel(5.5, 8) + ) + val torches = Seq( + new RedstoneTorchModel(8, 2.5), + new RedstoneTorchModel(14, 8), + new RedstoneTorchModel(2, 8), + new RedstoneTorchModel(9, 8) + ) + + override val coreModels = + Seq(new BaseComponentModel("DECRAND")) ++ wires ++ chips ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(4).on = true + wires(5).on = true + wires(0).disabled = configuration != 0 + wires(3).disabled = configuration != 0 + torches(0).on = true + torches(1).on = false + torches(2).on = false + torches(3).on = false + chips(0).on = false + chips(1).on = true + chips(2).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + val state = gate.state + wires(0).on = (state >> 4) == 2 + wires(1).on = (state >> 4) == 8 + wires(2).on = (state & 4) != 0 + wires(3).on = (state & 4) != 0 + wires(4).on = (state >> 4) == 1 || (state >> 4) == 2 + wires(5).on = (state >> 4) == 1 + wires(0).disabled = gate.shape != 0 + wires(3).disabled = gate.shape != 0 + torches(0).on = (state >> 4) == 1 + torches(1).on = (state >> 4) == 2 + torches(2).on = (state >> 4) == 8 + torches(3).on = !wires(4).on + chips(0).on = (state >> 4) == 2 + chips(1).on = (state >> 4) == 1 || (state >> 4) == 2 + chips(2).on = true + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala new file mode 100644 index 000000000..94810240e --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.misc + +import mrtjp.projectred.core.TFaceOrient +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, YellowChipModel} + +import java.util.Random + + +object Randomizer extends ComboICGateLogic { + val rand = new Random + + override def outputMask(shape: Int) = + ~((shape & 1) << 1 | (shape & 2) >> 1 | (shape & 4) << 1) & 0xb + override def inputMask(shape: Int) = 4 + override def feedbackMask(shape: Int) = outputMask(shape) + + override def deadSides = 3 + + override def getDelay(shape: Int) = 2 + + override def calcOutput(gate: ComboICGatePart, input: Int) = { + if (input == 0) gate.state >> 4 + else + outputMask(gate.shape) & TFaceOrient.shiftMask(rand.nextInt(8), 3) + } + + override def onChange(gate: ComboICGatePart) { + super.onChange(gate) + if ((gate.state & 4) != 0) gate.scheduleTick(2) + } +} + +class RenderRandomizer extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("RAND", 7) + val chips = Seq( + new YellowChipModel(8, 5.5), + new YellowChipModel(11.5, 11.5), + new YellowChipModel(4.5, 11.5) + ) + + override val coreModels = + Seq(new BaseComponentModel("RAND")) ++ wires ++ chips + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(4).on = false + wires(5).on = false + wires(6).on = false + wires(1).disabled = (configuration & 1) != 0 + wires(0).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 + wires(5).disabled = wires(1).disabled + wires(4).disabled = wires(0).disabled + wires(6).disabled = wires(3).disabled + chips(0).on = false + chips(1).on = false + chips(2).on = false + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(2).on = (gate.state & 4) != 0 + wires(0).on = (gate.state & 0x11) != 0 + wires(1).on = (gate.state & 0x22) != 0 + wires(3).on = (gate.state & 0x88) != 0 + wires(4).on = wires(2).on + wires(5).on = wires(2).on + wires(6).on = wires(2).on + wires(1).disabled = (gate.shape & 1) != 0 + wires(0).disabled = (gate.shape & 2) != 0 + wires(3).disabled = (gate.shape & 4) != 0 + wires(5).disabled = wires(1).disabled + wires(4).disabled = wires(0).disabled + wires(6).disabled = wires(3).disabled + chips(0).on = (gate.state & 0x10) != 0 + chips(1).on = (gate.state & 0x20) != 0 + chips(2).on = (gate.state & 0x80) != 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala new file mode 100644 index 000000000..eaf2f5ad0 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.misc + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedChipModel, RedstoneTorchModel} + + +class Synchronizer(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with TExtraStateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 14 + + override def onChange(gate: SequentialGateICPart) { + val oldInput = gate.state & 0xf + val newInput = getInput(gate, 14) + val high = newInput & ~oldInput + if (oldInput != newInput) { + val oldValue = state2 + + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + if ((newInput & 4) != 0) setState2(0) + else { + if ((high & 2) != 0) setState2(state2 | 1) // right + if ((high & 8) != 0) setState2(state2 | 2) // left + } + if (right && left) gate.scheduleTick(0) + + if (state2 != oldValue) sendState2Update() + } + } + + override def scheduledTick(gate: SequentialGateICPart) { + val oldValue = state2 + if (!pulsing && right && left) { + gate.setState(gate.state | 1 << 4) + gate.onOutputChange(1) + setState2(state2 | 4) // pulsing + gate.scheduleTick(2) + } else if (pulsing) { + gate.setState(gate.state & ~0x10) + gate.onOutputChange(1) + setState2(0) // off + } + if (state2 != oldValue) sendState2Update() + } + + def right = (state2 & 1) != 0 + def left = (state2 & 2) != 0 + def pulsing = (state2 & 4) != 0 + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + if (detailLevel > 1) { + data += "0: " + (if (right) "high" else "low") + data += "1: " + (if (left) "high" else "low") + } + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} + + +class RenderSynchronizer extends ICGateRenderer[SequentialGateICPart] { + val wires = generateWireModels("SYNC", 6) + val torch = new RedstoneTorchModel(8, 3) + val chips = Seq(new RedChipModel(4.5, 9), new RedChipModel(11.5, 9)) + + override val coreModels = + Seq(new BaseComponentModel("SYNC")) ++ wires ++ chips ++ Seq(torch) + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = true + wires(2).on = false + wires(3).on = false + wires(4).on = false + wires(5).on = false + chips(0).on = false + chips(1).on = false + torch.on = false + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + val logic = gate.getLogic[Synchronizer] + wires(0).on = !logic.left + wires(1).on = !logic.right + wires(2).on = (gate.state & 4) != 0 + wires(3).on = logic.left && logic.right + wires(4).on = (gate.state & 8) != 0 + wires(5).on = (gate.state & 2) != 0 + chips(0).on = logic.left + chips(1).on = logic.right + torch.on = (gate.state & 0x10) != 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala new file mode 100644 index 000000000..1a78c96c6 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object AND extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = ~shape << 1 & 0xe + + override def deadSides = 3 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input == inputMask(gate.shape)) 1 else 0 +} + +class RenderAND extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("AND", 4) + val torches = Seq( + new RedstoneTorchModel(4, 8), + new RedstoneTorchModel(12, 8), + new RedstoneTorchModel(8, 8), + new RedstoneTorchModel(8, 2) + ) + + override val coreModels = + Seq(new BaseComponentModel("AND")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(3).disabled = (configuration & 1) != 0 + wires(1).disabled = (configuration & 2) != 0 + wires(2).disabled = (configuration & 4) != 0 + torches(2).on = !wires(1).on && !wires(1).disabled + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled + torches(3).on = false + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x11) == 0 + wires(3).on = (gate.state & 2) != 0 + wires(1).on = (gate.state & 4) != 0 + wires(2).on = (gate.state & 8) != 0 + wires(3).disabled = (gate.shape & 1) != 0 + wires(1).disabled = (gate.shape & 2) != 0 + wires(2).disabled = (gate.shape & 4) != 0 + torches(2).on = !wires(1).on && !wires(1).disabled + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled + torches(3).on = !wires(0).on + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala new file mode 100644 index 000000000..a0dd3167b --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object Buffer extends ComboICGateLogic { + override def outputMask(shape: Int) = + ~((shape & 1) << 1 | (shape & 2) << 2) & 0xb + override def inputMask(shape: Int) = 4 + override def feedbackMask(shape: Int) = outputMask(shape) + + override def deadSides = 2 + override def maxDeadSides = 2 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input != 0) 0xb else 0 +} + +class RenderBuffer extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("BUFFER", 4) + val torches = + Seq(new RedstoneTorchModel(8, 3.5), new RedstoneTorchModel(8, 9)) + + override val coreModels = + Seq(new BaseComponentModel("BUFFER")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(1).disabled = (configuration & 1) != 0 + wires(3).disabled = (configuration & 2) != 0 + torches(0).on = false + torches(1).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 4) == 0 + wires(1).on = (gate.state & 0x22) != 0 + wires(2).on = (gate.state & 0x44) != 0 + wires(3).on = (gate.state & 0x88) != 0 + wires(1).disabled = (gate.shape & 1) != 0 + wires(3).disabled = (gate.shape & 2) != 0 + torches(0).on = (gate.state & 4) != 0 + torches(1).on = (gate.state & 4) == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala new file mode 100644 index 000000000..b2e29fdb0 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object Multiplexer extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 0xe + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if ((input & 1 << 2) != 0) (input >> 3) & 1 else (input >> 1) & 1 +} + +object Pulse extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 4 + + override def calcOutput(gate: ComboICGatePart, input: Int) = 0 + + override def onChange(gate: ComboICGatePart) = { + val oldInput = gate.state & 0xf + val newInput = getInput(gate, 4) + + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + if (newInput != 0 && (gate.state & 0xf0) == 0) { + gate.setState(gate.state & 0xf | 0x10) + gate.scheduleTick(2) + gate.onOutputChange(1) + } + } + } +} + +class RenderMultiplexer extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("MULTIPLEXER", 6) + val torches = Seq( + new RedstoneTorchModel(8, 2), + new RedstoneTorchModel(9, 10.5), + new RedstoneTorchModel(4.5, 8), + new RedstoneTorchModel(11.5, 8) + ) + + override val coreModels = + Seq(new BaseComponentModel("MULTIPLEXER")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(1).on = true + wires(2).on = true + wires(3).on = false + wires(4).on = false + wires(5).on = false + torches(0).on = false + torches(1).on = true + torches(2).on = false + torches(3).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(2).on = (gate.state & 4) == 0 + wires(3).on = (gate.state & 4) != 0 + wires(4).on = (gate.state & 8) != 0 + wires(5).on = (gate.state & 2) != 0 + torches(0).on = (gate.state & 0x10) != 0 + torches(1).on = !wires(3).on + torches(2).on = (gate.state & 8) == 0 && wires(3).on + torches(3).on = (gate.state & 4) == 0 && !wires(5).on + wires(0).on = torches(2).on + wires(1).on = torches(1).on + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala new file mode 100644 index 000000000..b69b24f04 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + +object NAND extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = ~shape << 1 & 0xe + + override def deadSides = 3 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input == inputMask(gate.shape)) 0 else 1 +} + +class RenderNAND extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("NAND", 4) + val torches = Seq( + new RedstoneTorchModel(4, 8), + new RedstoneTorchModel(12, 8), + new RedstoneTorchModel(8, 8) + ) + + override val coreModels = + Seq(new BaseComponentModel("NAND")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(3).disabled = (configuration & 1) != 0 + wires(1).disabled = (configuration & 2) != 0 + wires(2).disabled = (configuration & 4) != 0 + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled + torches(2).on = !wires(1).on && !wires(1).disabled + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x11) != 0 + wires(3).on = (gate.state & 2) != 0 + wires(1).on = (gate.state & 4) != 0 + wires(2).on = (gate.state & 8) != 0 + wires(3).disabled = (gate.shape & 1) != 0 + wires(1).disabled = (gate.shape & 2) != 0 + wires(2).disabled = (gate.shape & 4) != 0 + torches(0).on = !wires(2).on && !wires(2).disabled + torches(1).on = !wires(3).on && !wires(3).disabled + torches(2).on = !wires(1).on && !wires(1).disabled + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala new file mode 100644 index 000000000..48344b251 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object NOR extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = ~shape << 1 & 0xe + override def feedbackMask(shape: Int) = 1 + + override def deadSides = 3 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input == 0) 1 else 0 +} + +class RenderNOR extends ICGateRenderer[ComboICGatePart] { + var wires = generateWireModels("NOR", 4) + var torch = new RedstoneTorchModel(8, 9) + + override val coreModels = Seq(new BaseComponentModel("NOR")) ++ wires :+ torch + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(1).disabled = (configuration & 1) != 0 + wires(2).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 + torch.on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x11) != 0 + wires(1).on = (gate.state & 2) != 0 + wires(2).on = (gate.state & 4) != 0 + wires(3).on = (gate.state & 8) != 0 + wires(1).disabled = (gate.shape & 1) != 0 + wires(2).disabled = (gate.shape & 2) != 0 + wires(3).disabled = (gate.shape & 4) != 0 + torch.on = (gate.state & 0xe) == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala new file mode 100644 index 000000000..2440a979b --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object NOT extends ComboICGateLogic { + override def outputMask(shape: Int) = + ~((shape & 1) << 1 | (shape & 2) >> 1 | (shape & 4) << 1) & 0xb + override def inputMask(shape: Int) = 4 + override def feedbackMask(shape: Int) = outputMask(shape) + + override def deadSides = 3 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input == 0) 0xb else 0 +} + +class RenderNOT extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("NOT", 4) + val torch = new RedstoneTorchModel(8, 8) + + override val coreModels = Seq(new BaseComponentModel("NOT")) ++ wires :+ torch + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = true + wires(2).on = false + wires(3).on = true + wires(0).disabled = (configuration & 2) != 0 + wires(1).disabled = (configuration & 1) != 0 + wires(3).disabled = (configuration & 4) != 0 + torch.on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x11) != 0 + wires(1).on = (gate.state & 0x22) != 0 + wires(2).on = (gate.state & 4) != 0 + wires(3).on = (gate.state & 0x88) != 0 + wires(0).disabled = (gate.shape & 2) != 0 + wires(1).disabled = (gate.shape & 1) != 0 + wires(3).disabled = (gate.shape & 4) != 0 + torch.on = (gate.state & 0xf0) != 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala new file mode 100644 index 000000000..1118fe3d1 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object OR extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = ~shape << 1 & 0xe + + override def deadSides = 3 + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input != 0) 1 else 0 +} + +class RenderOR extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("OR", 4) + val torches = + Seq(new RedstoneTorchModel(8, 9), new RedstoneTorchModel(8, 2.5)) + + override val coreModels = + Seq(new BaseComponentModel("OR")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(1).disabled = (configuration & 1) != 0 + wires(2).disabled = (configuration & 2) != 0 + wires(3).disabled = (configuration & 4) != 0 + torches(0).on = true + torches(1).on = false + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x10) == 0 + wires(1).on = (gate.state & 2) != 0 + wires(2).on = (gate.state & 4) != 0 + wires(3).on = (gate.state & 8) != 0 + wires(1).disabled = (gate.shape & 1) != 0 + wires(2).disabled = (gate.shape & 2) != 0 + wires(3).disabled = (gate.shape & 4) != 0 + torches(0).on = (gate.state & 0xe) == 0 + torches(1).on = !wires(0).on + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala new file mode 100644 index 000000000..e5fa094fa --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object XNOR extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 10 + + override def calcOutput(gate: ComboICGatePart, input: Int) = { + val side1 = (input & 1 << 1) != 0 + val side2 = (input & 1 << 3) != 0 + if (side1 == side2) 1 else 0 + } +} + +class RenderXNOR extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("XNOR", 5) + val torches = Seq( + new RedstoneTorchModel(8, 2), + new RedstoneTorchModel(4.5, 8), + new RedstoneTorchModel(11.5, 8), + new RedstoneTorchModel(8, 12) + ) + + override val coreModels = + Seq(new BaseComponentModel("XNOR")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(3).on = false + wires(2).on = false + wires(1).on = false + torches(0).on = true + torches(1).on = false + torches(2).on = false + torches(3).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 2) != 0 && (gate.state & 8) == 0 + wires(1).on = (gate.state & 8) != 0 && (gate.state & 2) == 0 + wires(2).on = (gate.state & 8) != 0 + wires(3).on = (gate.state & 2) != 0 + wires(4).on = !wires(3).on && !wires(2).on + torches(0).on = (gate.state & 0x11) != 0 + torches(1).on = !wires(4).on && (gate.state & 8) == 0 + torches(2).on = !wires(4).on && (gate.state & 2) == 0 + torches(3).on = (gate.state & 2) == 0 && (gate.state & 8) == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala new file mode 100644 index 000000000..5a907cd46 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.primitives + +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} + + +object XOR extends ComboICGateLogic { + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 10 + + override def calcOutput(gate: ComboICGatePart, input: Int) = { + val side1 = (input & 1 << 1) != 0 + val side2 = (input & 1 << 3) != 0 + if (side1 != side2) 1 else 0 + } +} + +class RenderXOR extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("XOR", 4) + val torches = Seq( + new RedstoneTorchModel(4.5, 8), + new RedstoneTorchModel(11.5, 8), + new RedstoneTorchModel(8, 12) + ) + + override val coreModels = + Seq(new BaseComponentModel("XOR")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(3).on = false + wires(2).on = false + wires(1).on = true + torches(0).on = false + torches(1).on = false + torches(2).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x11) != 0 + wires(3).on = (gate.state & 2) != 0 + wires(2).on = (gate.state & 8) != 0 + wires(1).on = !wires(3).on && !wires(2).on + torches(0).on = !wires(2).on && !wires(1).on + torches(1).on = !wires(3).on && !wires(1).on + torches(2).on = wires(1).on + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala new file mode 100644 index 000000000..604995171 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.timing + +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + +class RenderPulse extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("PULSE", 3) + val torches = Seq( + new RedstoneTorchModel(4, 9.5), + new RedstoneTorchModel(11, 9.5), + new RedstoneTorchModel(8, 3.5) + ) + + override val coreModels = + Seq(new BaseComponentModel("PULSE")) ++ wires ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + wires(2).on = false + torches(0).on = true + torches(1).on = false + torches(2).on = false + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 4) == 0 + wires(1).on = (gate.state & 4) != 0 + wires(2).on = (gate.state & 0x14) == 4 + torches(0).on = wires(0).on + torches(1).on = wires(1).on + torches(2).on = (gate.state & 0x10) != 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala new file mode 100644 index 000000000..0a927e12f --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.timing + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} + + +object Repeater extends ComboICGateLogic { + val delays = Array(2, 4, 6, 8, 16, 32, 64, 128, 256) + + override def outputMask(shape: Int) = 1 + override def inputMask(shape: Int) = 4 + + override def getDelay(shape: Int) = delays(shape) + + override def cycleShape(shape: Int) = (shape + 1) % delays.length + + override def calcOutput(gate: ComboICGatePart, input: Int) = + if (input == 0) 0 else 1 + + override def onChange(gate: ComboICGatePart) { + if (gate.schedTime < 0) super.onChange(gate) + } + + override def activate(gate: ComboICGatePart) { + gate.configure() + } + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: ComboICGatePart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + if (detailLevel > 1) data += "delay: " + delays(gate.shape) + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} + +class RenderRepeater extends ICGateRenderer[ComboICGatePart] { + val wires = generateWireModels("REPEATER", 2) + val endTorch = new RedstoneTorchModel(8, 2) + val varTorches = Seq( + new RedstoneTorchModel(12.5, 12), + new RedstoneTorchModel(12.5, 11), + new RedstoneTorchModel(12.5, 10), + new RedstoneTorchModel(12.5, 9), + new RedstoneTorchModel(12.5, 8), + new RedstoneTorchModel(12.5, 7), + new RedstoneTorchModel(12.5, 6), + new RedstoneTorchModel(12.5, 5), + new RedstoneTorchModel(12.5, 4) + ) + + var shape = 0 + + override val coreModels = + Seq(new BaseComponentModel("REPEATER")) ++ wires :+ endTorch + + override def switchModels = Seq(varTorches(shape)) + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = true + wires(1).on = false + endTorch.on = false + shape = configuration % 8 + varTorches(0).on = true + } + + override def prepareDynamic(gate: ComboICGatePart, frame: Float) { + wires(0).on = (gate.state & 0x10) == 0 + wires(1).on = (gate.state & 4) != 0 + endTorch.on = (gate.state & 0x10) != 0 + shape = gate.shape % 8 + varTorches(shape).on = (gate.state & 4) == 0 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala new file mode 100644 index 000000000..92358d2ed --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.timing + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.math.MathHelper +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.core.Configurator +import mrtjp.projectred.core.TFaceOrient.flipMaskZ +import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICTimerGateGui} +import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import net.minecraft.nbt.NBTTagCompound + + +class Sequencer(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with ITimerGuiLogic { + var pointer_max = 40 + var saveTime = -1L + + override def outputMask(shape: Int) = 0xf + + override def onChange(gate: SequentialGateICPart) {} + override def scheduledTick(gate: SequentialGateICPart) {} + + override def getTimerMax = pointer_max + override def setTimerMax(gate: GateICPart, time: Int) { + var t = time + val minTime = math.max(4, Configurator.minTimerTicks) + if (t < minTime) t = minTime + if (t != pointer_max) { + pointer_max = t + sendPointerMaxUpdate() + } + } + + override def save(tag: NBTTagCompound) { + tag.setInteger("pmax", pointer_max) + tag.setLong("tsave", getWorldTime) + } + override def load(tag: NBTTagCompound) { + pointer_max = tag.getInteger("pmax") + saveTime = tag.getLong("tsave") + } + + override def writeDesc(packet: MCDataOutput) { packet.writeInt(pointer_max) } + override def readDesc(packet: MCDataInput) { pointer_max = packet.readInt() } + + override def read(packet: MCDataInput, key: Int) = key match { + case 12 => pointer_max = packet.readInt() + case _ => + } + + def sendPointerMaxUpdate() { gate.writeStreamOf(12).writeInt(pointer_max) } + + def getWorldTime = + if (gate.world.network != null) gate.world.network.getWorld.getWorldTime + else saveTime + + override def onTick(gate: SequentialGateICPart) { + if (!gate.world.network.isRemote) { + val oldOut = gate.state >> 4 + var out = 1 << getWorldTime % (pointer_max * 4) / pointer_max + if (gate.shape == 1) out = flipMaskZ(out) + if (oldOut != out) { + gate.setState(out << 4) + gate.onOutputChange(0xf) + } + } + } + + override def cycleShape(gate: SequentialGateICPart) = { + gate.setShape(gate.shape ^ 1) + true + } + + @SideOnly(Side.CLIENT) + override def createGui(gate: SequentialGateICPart): CircuitGui = + new ICTimerGateGui(gate) + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + if (detailLevel > 1) + data += "interval: " + "%.2f".format(getTimerMax * 0.05) + "s" + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} + + +class RenderSequencer extends ICGateRenderer[SequentialGateICPart] { + val torches = Seq( + new RedstoneTorchModel(8, 8), + new RedstoneTorchModel(8, 3), + new RedstoneTorchModel(13, 8), + new RedstoneTorchModel(8, 13), + new RedstoneTorchModel(3, 8) + ) + val pointer = new PointerModel(8, 8) + + torches(0).on = true + + override val coreModels = + Seq(new BaseComponentModel("SEQUENCER"), pointer) ++ torches + + override def prepareStatic(configuration: Int): Unit = { + torches(1).on = true + torches(2).on = false + torches(3).on = false + torches(4).on = false + + pointer.angle = 0 + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + torches(1).on = (gate.state & 0x10) != 0 + torches(2).on = (gate.state & 0x20) != 0 + torches(3).on = (gate.state & 0x40) != 0 + torches(4).on = (gate.state & 0x80) != 0 + + val max = gate.getLogic[Sequencer].pointer_max * 4 + pointer.angle = (gate + .getLogic[Sequencer] + .getWorldTime % max + frame) / max * 2 * MathHelper.pi + if (gate.shape == 1) pointer.angle *= -1 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala new file mode 100644 index 000000000..aee92653f --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.timing + +import codechicken.lib.math.MathHelper +import mrtjp.projectred.core.TFaceOrient.flipMaskZ +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} +import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedChipModel, RedstoneTorchModel} + + +class StateCell(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with TTimerGateLogic + with TExtraStateLogic { + override def outputMask(shape: Int) = { + var output = 9 + if (shape == 1) output = flipMaskZ(output) + output + } + + override def inputMask(shape: Int) = { + var input = 6 + if (shape == 1) input = flipMaskZ(input) + input + } + + override def cycleShape(gate: SequentialGateICPart) = { + gate.setShape((gate.shape + 1) % 2) + true + } + + override def onChange(gate: SequentialGateICPart) { + val oldInput = gate.state & 0xf + var newInput = getInput(gate, 0xe) + if (oldInput != newInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + + if (gate.shape == 1) newInput = flipMaskZ(newInput) + if ((newInput & 4) != 0 && state2 == 0) { + setState2(1) + sendState2Update() + gate.scheduleTick(0) + } + + if (state2 != 0) + if ((newInput & 6) != 0) resetPointer() + else startPointer() + } + } + + override def pointerTick() { + resetPointer() + if (!gate.world.network.isRemote) { + setState2(0) + sendState2Update() + gate.setState(0x10 | gate.state & 0xf) + gate.onOutputChange(outputMask(gate.shape)) + gate.scheduleTick(2) + } + } + + override def scheduledTick(gate: SequentialGateICPart) { + var output = 0 + if (state2 != 0) output = 8 + if (gate.shape == 1) output = flipMaskZ(output) + + gate.setState(output << 4 | gate.state & 0xf) + gate.onOutputChange(outputMask(gate.shape)) + } +} + + +class RenderStateCell extends ICGateRenderer[SequentialGateICPart] { + val wires = generateWireModels("STATECELL", 5) + val torches = + Seq(new RedstoneTorchModel(10, 3.5), new RedstoneTorchModel(13, 8)) + val chip = new RedChipModel(6.5, 10) + val pointer = new PointerModel(13, 8) + + override val coreModels = Seq( + new BaseComponentModel("STATECELL") + ) ++ wires ++ Seq(chip, pointer) ++ torches + + override def prepareStatic(configuration: Int): Unit = { + reflect = false + wires(0).on = false + wires(1).on = false + wires(2).on = false + wires(3).on = false + wires(4).on = false + torches(0).on = false + torches(1).on = true + chip.on = false + pointer.angle = -MathHelper.pi / 2 + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + reflect = gate.shape == 1 + val logic = gate.getLogic[StateCell] + var state = gate.state + if (reflect) state = flipMaskZ(state >> 4) << 4 | flipMaskZ(state) + + wires(0).on = (state & 0x10) != 0 + wires(1).on = (state & 4) != 0 + wires(2).on = logic.state2 == 0 || (state & 4) != 0 + wires(3).on = (state & 0x88) != 0 + wires(4).on = (state & 2) != 0 + torches(0).on = (state & 0x10) != 0 + torches(1).on = logic.pointer_start >= 0 + chip.on = logic.state2 != 0 + + reflect = gate.shape == 1 + pointer.angle = + gate.getLogic[StateCell].interpPointer(frame) - MathHelper.pi / 2 + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala new file mode 100644 index 000000000..4e8673444 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.timing + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.math.MathHelper +import codechicken.multipart.handler.MultipartSaveLoad +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.core.Configurator +import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels +import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} +import mrtjp.projectred.fabrication.gui.{CircuitGui, ICTimerGateGui} +import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import net.minecraft.nbt.NBTTagCompound + + +trait ITimerGuiLogic { + def getTimerMax: Int + def setTimerMax(gate: GateICPart, t: Int) +} + + +class Timer(gate: SequentialGateICPart) + extends SequentialICGateLogic(gate) + with TTimerGateLogic { + override def outputMask(shape: Int) = 0xb + override def inputMask(shape: Int) = 0xe + + override def setup(gate: SequentialGateICPart) { startPointer() } + + override def scheduledTick(gate: SequentialGateICPart) { + gate.setState(gate.state & 0xf) + gate.onOutputChange(0xb) + onChange(gate) + } + + override def onChange(gate: SequentialGateICPart) { + val oldInput = gate.state & 0xf + val newInput = getInput(gate, 0xe) + + if (newInput != oldInput) { + gate.setState(gate.state & 0xf0 | newInput) + gate.onInputChange() + } + + if (gate.schedTime < 0) + if (newInput > 0) resetPointer() else startPointer() + } + + override def pointerTick() { + resetPointer() + if (!gate.world.network.isRemote) { + gate.scheduleTick(2) + gate.setState(0xb0 | gate.state & 0xf) + gate.onOutputChange(0xb) + } + } +} + + +trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { + var pointer_max = 38 + var pointer_start = -1L + var saveTime = -1L // used for blueprint in-hand rendering + + abstract override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setInteger("pmax", pointer_max) + tag.setLong( + "pelapsed", + if (pointer_start < 0) pointer_start else getTotalTime - pointer_start + ) + tag.setLong("tsave", getTotalTime) + } + + abstract override def load(tag: NBTTagCompound) { + super.load(tag) + pointer_max = tag.getInteger("pmax") + pointer_start = tag.getLong("pelapsed") + saveTime = tag.getLong("tsave") + if (pointer_start >= 0) pointer_start = getTotalTime - pointer_start + } + + abstract override def writeDesc(packet: MCDataOutput) { + super.writeDesc(packet) + packet.writeInt(pointer_max) + packet.writeLong(pointer_start) + } + + abstract override def readDesc(packet: MCDataInput) { + super.readDesc(packet) + pointer_max = packet.readInt() + pointer_start = packet.readLong() + } + + abstract override def read(packet: MCDataInput, key: Int) = key match { + case 12 => pointer_max = packet.readInt() + case 13 => + pointer_start = packet.readInt() + if (pointer_start >= 0) pointer_start = getTotalTime - pointer_start + case _ => super.read(packet, key) + } + + def getTotalTime = // client-side safe version of getTotalWorldTime (workaround for no client world) + { + if (gate.world.network == null) + saveTime // ic was loaded directly from stack, possibly for in-hand render + else if (gate.world.network.getWorld == null) + MultipartSaveLoad.loadingWorld.getTotalWorldTime // ic is being loaded with a workbench tile or gate + else + gate.world.network.getWorld.getTotalWorldTime // normal access during operation + } + + def pointerValue = + if (pointer_start < 0) 0 else (getTotalTime - pointer_start).toInt + + def sendPointerMaxUpdate() { gate.writeStreamOf(12).writeInt(pointer_max) } + def sendPointerUpdate() { + gate.writeStreamOf(13).writeInt(if (pointer_start < 0) -1 else pointerValue) + } + + override def getTimerMax = pointer_max + 2 + override def setTimerMax(gate: GateICPart, time: Int) { + var t = time + val minTime = math.max(4, Configurator.minTimerTicks) + if (t < minTime) t = minTime + if (t != pointer_max) { + pointer_max = t - 2 + sendPointerMaxUpdate() + } + } + + override def onTick(gate: SequentialGateICPart) { + if (pointer_start >= 0) + if (getTotalTime >= pointer_start + pointer_max) pointerTick() + else if (pointer_start > getTotalTime) + pointer_start = getTotalTime + } + + def pointerTick() + + def resetPointer() { + if (pointer_start >= 0) { + pointer_start = -1 + gate.world.network.markSave() + if (!gate.world.network.isRemote) sendPointerUpdate() + } + } + + def startPointer() { + if (pointer_start < 0) { + pointer_start = getTotalTime + gate.world.network.markSave() + if (!gate.world.network.isRemote) sendPointerUpdate() + } + } + + def interpPointer(f: Float) = + if (pointer_start < 0) 0f else (pointerValue + f) / pointer_max + + @SideOnly(Side.CLIENT) + override def createGui(gate: SequentialGateICPart): CircuitGui = + new ICTimerGateGui(gate) + + @SideOnly(Side.CLIENT) + override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { + val data = Seq.newBuilder[String] + if (detailLevel > 1) + data += "interval: " + "%.2f".format(getTimerMax * 0.05) + "s" + super.getRolloverData(gate, detailLevel) ++ data.result() + } +} + + +class RenderTimer extends ICGateRenderer[SequentialGateICPart] { + val wires = generateWireModels("TIME", 3) + val torches = Seq(new RedstoneTorchModel(8, 3), new RedstoneTorchModel(8, 8)) + val pointer = new PointerModel(8, 8) + + override val coreModels = + Seq(new BaseComponentModel("TIME")) ++ wires ++ Seq(pointer) ++ torches + + override def prepareStatic(configuration: Int): Unit = { + wires(0).on = false + wires(1).on = false + wires(2).on = false + torches(0).on = false + pointer.angle = 0 + } + + override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { + torches(0).on = (gate.state & 0x10) != 0 + wires(0).on = (gate.state & 0x88) != 0 + wires(1).on = (gate.state & 0x22) != 0 + wires(2).on = (gate.state & 4) != 0 + val ang = + gate.getLogic[TTimerGateLogic].interpPointer(frame) * MathHelper.pi * 2 + pointer.angle = ang + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala new file mode 100644 index 000000000..7dc0ed730 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.wire + +import codechicken.lib.render.ColourMultiplier +import codechicken.lib.render.uv.IconTransformation +import codechicken.lib.vec.Transformation +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.circuitparts.CircuitPartDefs +import mrtjp.projectred.fabrication.operations.CircuitOpDefs + +class AlloyWireICPart extends RedwireICPart { + override def getPartType = CircuitPartDefs.AlloyWire + + @SideOnly(Side.CLIENT) + override def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) { + RenderICAlloyWire.prepairDynamic(this) + RenderICAlloyWire.render(t, ortho) + } + + @SideOnly(Side.CLIENT) + override def getPartName = "Alloy wire" + + @SideOnly(Side.CLIENT) + override def getPickOp = CircuitOpDefs.AlloyWire.getOp +} + + +object RenderICAlloyWire { + var connMap: Byte = 0 + var signal: Byte = 0 + + def prepairInv() { + connMap = 0xf + signal = 0xff.toByte + } + + def prepairDynamic(part: AlloyWireICPart) { + connMap = part.connMap + signal = part.signal + } + + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)).render( + t, + new IconTransformation(redwireIcons(connMap & 0xff)), + ColourMultiplier.instance((signal & 0xff) / 2 + 60 << 24 | 0xff) + ) + finishRender() + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/wirepartbundled.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala similarity index 80% rename from src/main/scala/mrtjp/projectred/fabrication/wirepartbundled.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala index ed25f73c8..94204c39b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/wirepartbundled.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala @@ -3,16 +3,23 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts.wire import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.ColourMultiplier +import codechicken.lib.render.uv.IconTransformation import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.color.Colors -import mrtjp.projectred.fabrication.IWireICPart._ -import mrtjp.projectred.transmission.BundledCommons._ +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.circuitparts.IWireICPart._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, IWireICPart, TICBundledAcquisitions} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs +import mrtjp.projectred.transmission.BundledCommons.{packDigital, raiseSignal, unpackDigital} import net.minecraft.nbt.NBTTagCompound + trait IBundledCableICPart extends IWireICPart with IICBundledEmitter { def getBundledSignal: Array[Byte] def calculateSignal: Array[Byte] @@ -21,12 +28,14 @@ trait IBundledCableICPart extends IWireICPart with IICBundledEmitter { def getBundledColour: Int } + trait IICBundledEmitter { def getBundledSignal(r: Int): Array[Byte] } + class BundledCableICPart - extends WireICPart + extends WireICPart with TICBundledAcquisitions with IBundledCableICPart { var signal = new Array[Byte](16) @@ -58,7 +67,7 @@ class BundledCableICPart override def read(in: MCDataInput, key: Int) = key match { case 10 => signal = unpackDigital(signal, in.readUShort()) - case _ => super.read(in, key) + case _ => super.read(in, key) } override def onSignalUpdate() { @@ -72,11 +81,12 @@ class BundledCableICPart case b: IBundledCableICPart => b.getBundledColour == -1 || colour == -1 || b.getBundledColour == colour case ins: IInsulatedRedwireICPart => true - case be: IICBundledEmitter => true - case _ => false + case be: IICBundledEmitter => true + case _ => false } protected var propagatingMask = 0xffff + override def updateAndPropagate(prev: CircuitPart, mode: Int) { import mrtjp.projectred.transmission.BundledCommons._ val mask = getUpdateMask(prev, mode) @@ -127,12 +137,13 @@ class BundledCableICPart if (s > (tmpSignal(i.getInsulatedColour) & 0xff)) tmpSignal(i.getInsulatedColour) = s.toByte case b: IICBundledEmitter => raiseSignal(tmpSignal, b.getBundledSignal(r)) - case _ => + case _ => } tmpSignal } private val tmpSignal = new Array[Byte](16) + private def tmpSignalClear() { for (i <- 0 until 16) tmpSignal(i) = 0.toByte } @@ -174,7 +185,7 @@ class BundledCableICPart @SideOnly(Side.CLIENT) override def getPartName = (if (colour != -1) Colors(colour & 0xff).name + " " - else "") + "Bundled cable" + else "") + "Bundled cable" @SideOnly(Side.CLIENT) override def getPickOp = CircuitOpDefs @@ -194,3 +205,32 @@ class BundledCableICPart super.getRolloverData(detailLevel) ++ data.result() } } + + +object RenderICBundledCable { + var connMap: Byte = 0 + var colour: Byte = 0 + + def prepairInv(c: Int) { + connMap = 0xf + colour = c.toByte + } + + def prepairDynamic(part: BundledCableICPart) { + connMap = part.connMap + colour = part.colour + } + + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)) + .render(t, new IconTransformation(bundledwireIcons(connMap & 0xff))) + if (colour != -1) + faceModels(dynamicIdx(0, ortho)).render( + t, + new IconTransformation(bundledColourIcon), + ColourMultiplier.instance(Colors(colour & 0xff).rgba) + ) + finishRender() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/buttonpart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala similarity index 77% rename from src/main/scala/mrtjp/projectred/fabrication/buttonpart.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala index f15d0c3c5..01e982e2c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/buttonpart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala @@ -3,18 +3,23 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts.wire import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.uv.IconTransformation import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TClientNetCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumChatFormatting class ButtonICPart extends CircuitPart with TICAcquisitions - with IPoweredCircuitPart + with TPoweredCircuitPart with TClientNetCircuitPart { var on = false var sched = -1L @@ -122,14 +127,24 @@ class ButtonICPart } } -class CircuitOpButton extends SimplePlacementOp { - override def doPartRender(t: Transformation) { - RenderICButton.prepairInv() - RenderICButton.render(t, true) + +object RenderICButton { + var on = false + + def prepairInv() { + on = false } - override def createPart = CircuitPartDefs.Button.createPart + def prepairDynamic(part: ButtonICPart) { + on = part.on + } - @SideOnly(Side.CLIENT) - override def getOpName = "Button" + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)).render( + t, + new IconTransformation(if (on) buttonOnIcon else buttonOffIcon) + ) + finishRender() + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala new file mode 100644 index 000000000..a74017215 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.wire + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.ColourMultiplier +import codechicken.lib.render.uv.IconTransformation +import codechicken.lib.vec.Transformation +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.color.Colors +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs +import net.minecraft.nbt.NBTTagCompound + + +trait IInsulatedRedwireICPart extends IRedwireICPart { + def getInsulatedColour: Int +} + + +class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { + var colour: Byte = 0 + + override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("colour", colour) + } + + override def load(tag: NBTTagCompound) { + super.load(tag) + colour = tag.getByte("colour") + } + + override def writeDesc(out: MCDataOutput) { + super.writeDesc(out) + out.writeByte(colour) + } + + override def readDesc(in: MCDataInput) { + super.readDesc(in) + colour = in.readByte() + } + + override def getPartType = CircuitPartDefs.InsulatedWire + + override def resolveSignal(part: Any, r: Int) = part match { + case b: IBundledCableICPart => (b.getBundledSignal.apply(colour) & 0xff) - 1 + case _ => super.resolveSignal(part, r) + } + + override def canConnectPart(part: CircuitPart, r: Int) = part match { + case b: IBundledCableICPart => true + case iw: InsulatedWireICPart => iw.colour == colour + case _ => super.canConnectPart(part, r) + } + + override def getInsulatedColour = colour + + @SideOnly(Side.CLIENT) + override def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) { + RenderICInsulatedWire.prepairDynamic(this) + RenderICInsulatedWire.render(t, ortho) + } + + @SideOnly(Side.CLIENT) + override def getPartName = Colors(colour & 0xff).name + " Insulated wire" + + @SideOnly(Side.CLIENT) + override def getPickOp = + CircuitOpDefs + .values(CircuitOpDefs.WhiteInsulatedWire.ordinal + colour) + .getOp +} + + + +object RenderICInsulatedWire { + var connMap: Byte = 0 + var signal: Byte = 0 + var colour: Byte = 0 + + def prepairInv(c: Int) { + connMap = 0xf + signal = 255.toByte + colour = c.toByte + } + + def prepairDynamic(part: InsulatedWireICPart) { + connMap = part.connMap + signal = part.signal + colour = part.colour + } + + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)).render( + t, + new IconTransformation(redwireIcons(connMap & 0xff)), + ColourMultiplier.instance((signal & 0xff) / 2 + 60 << 24 | 0xff) + ) + faceModels(dynamicIdx(0, ortho)).render( + t, + new IconTransformation(insulatedwireIcons(connMap & 0xff)), + ColourMultiplier.instance(Colors(colour & 0xff).rgba) + ) + finishRender() + } +} + diff --git a/src/main/scala/mrtjp/projectred/fabrication/leverpart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala similarity index 71% rename from src/main/scala/mrtjp/projectred/fabrication/leverpart.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala index 084f1e6ca..3f03eb332 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/leverpart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala @@ -3,18 +3,24 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts.wire -import codechicken.lib.data.{MCDataOutput, MCDataInput} +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.uv.IconTransformation import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TClientNetCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumChatFormatting + class LeverICPart extends CircuitPart with TICAcquisitions - with IPoweredCircuitPart + with TPoweredCircuitPart with TClientNetCircuitPart { var on = false @@ -96,14 +102,22 @@ class LeverICPart } } -class CircuitOpLever extends SimplePlacementOp { - override def doPartRender(t: Transformation) { - RenderICLever.prepairInv() - RenderICLever.render(t, true) + +object RenderICLever { + var on = false + + def prepairInv() { + on = false } - override def createPart = CircuitPartDefs.Lever.createPart + def prepairDynamic(part: LeverICPart) { + on = part.on + } - @SideOnly(Side.CLIENT) - override def getOpName = "Lever" -} + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)) + .render(t, new IconTransformation(if (on) leverOnIcon else leverOffIcon)) + finishRender() + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/torchpart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala similarity index 57% rename from src/main/scala/mrtjp/projectred/fabrication/torchpart.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala index 7dd1a1a0b..f28f01cee 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/torchpart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala @@ -3,15 +3,21 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts.wire +import codechicken.lib.render.uv.IconTransformation import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs + class TorchICPart extends CircuitPart with TICAcquisitions - with IPoweredCircuitPart { + with TPoweredCircuitPart { override def getPartType = CircuitPartDefs.Torch override def onAdded() { @@ -41,11 +47,12 @@ class TorchICPart } } -class CircuitOpTorch extends SimplePlacementOp { - override def doPartRender(t: Transformation) = RenderICTorch.render(t, true) - - override def createPart = CircuitPartDefs.Torch.createPart - @SideOnly(Side.CLIENT) - override def getOpName = "Torch" +object RenderICTorch { + def render(t: Transformation, ortho: Boolean) { + prepairRender() + faceModels(dynamicIdx(0, ortho)) + .render(t, new IconTransformation(torchOnIcon)) + finishRender() + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala new file mode 100644 index 000000000..560f45a3b --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.circuitparts.wire + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TPoweredCircuitPart, TICRSAcquisitions, TRSPropagatingICPart} +import net.minecraft.nbt.NBTTagCompound + + + + + +abstract class RedwireICPart + extends WireICPart + with TICRSAcquisitions + with TRSPropagatingICPart + with IRedwireICPart { + var signal: Byte = 0 + + override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("signal", signal) + } + + override def load(tag: NBTTagCompound) { + super.load(tag) + signal = tag.getByte("signal") + } + + override def writeDesc(out: MCDataOutput) { + super.writeDesc(out) + out.writeByte(signal) + } + + override def readDesc(in: MCDataInput) { + super.readDesc(in) + signal = in.readByte() + } + + override def read(in: MCDataInput, key: Int) = key match { + case 10 => signal = in.readByte() + case _ => super.read(in, key) + } + + override def onSignalUpdate() { + super.onSignalUpdate() + writeStreamOf(10).writeByte(signal) + } + + override def discoverOverride(r: Int, part: CircuitPart) = part match { + case pow: TPoweredCircuitPart => pow.canConnectRS(rotFromStraight(r)) + case _ => super.discoverOverride(r, part) + } + + override def canConnectRS(r: Int) = ICPropagator.redwiresConnectable + + override def getRedwireSignal(r: Int) = getSignal + + override def getSignal = signal & 0xff + + override def setSignal(sig: Int) { + signal = sig.toByte + } + + override def rsOutputLevel(r: Int) = + if (ICPropagator.redwiresProvidePower && maskConnects(r)) + (signal & 0xff) + 16 + else 0 + + override def canConnectPart(part: CircuitPart, r: Int) = part match { + case re: IICRedwireEmitter => true + case pc: TPoweredCircuitPart => true + case _ => false + } + + override def resolveSignal(part: Any, r: Int) = part match { + case t: IRedwireICPart if t.diminishOnSide(r) => t.getRedwireSignal(r) - 1 + case t: IICRedwireEmitter => t.getRedwireSignal(r) + case t: TPoweredCircuitPart => t.rsOutputLevel(r) + case _ => 0 + } + + override def calculateSignal = { + var s = 0 + ICPropagator.redwiresProvidePower = false + + def raise(sig: Int) { + if (sig > s) s = sig + } + + for (r <- 0 until 4) if (maskConnects(r)) raise(calcSignal(r)) + ICPropagator.redwiresProvidePower = true + s + } + + @SideOnly(Side.CLIENT) + override def getRolloverData(detailLevel: Int) = { + val data = Seq.newBuilder[String] + + import net.minecraft.util.EnumChatFormatting._ + if (detailLevel >= 3) + data += GRAY + "signal: 0x" + Integer.toHexString(signal & 0xff) + else if (detailLevel >= 2) + data += GRAY + "state: " + (if (signal != 0) "high" else "low") + + super.getRolloverData(detailLevel) ++ data.result() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/wirepartabstracts.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala similarity index 79% rename from src/main/scala/mrtjp/projectred/fabrication/wirepartabstracts.scala rename to src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala index 1c7e3525f..9ffa0612b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/wirepartabstracts.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala @@ -3,18 +3,28 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.circuitparts.wire import codechicken.lib.data.{MCDataInput, MCDataOutput} import mrtjp.core.color.Colors -import mrtjp.projectred.fabrication.IWireICPart._ +import mrtjp.projectred.fabrication.circuitparts.IWireICPart._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TErrorCircuitPart, IWireICPart, TConnectableICPart, TPropagatingICPart} import net.minecraft.nbt.NBTTagCompound + +trait IRedwireICPart extends IWireICPart with IICRedwireEmitter + +trait IICRedwireEmitter { + def getRedwireSignal(r: Int): Int +} + + abstract class WireICPart extends CircuitPart with TConnectableICPart with TPropagatingICPart - with IErrorCircuitPart { + with TErrorCircuitPart { override def save(tag: NBTTagCompound) { tag.setByte("connMap", connMap) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/components.scala b/src/main/scala/mrtjp/projectred/fabrication/components.scala index 9c919bc67..775e73216 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/components.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/components.scala @@ -8,15 +8,11 @@ package mrtjp.projectred.fabrication import codechicken.lib.math.MathHelper import codechicken.lib.render.CCRenderState.IVertexOperation import codechicken.lib.render.uv.{IconTransformation, UVTransformation} -import codechicken.lib.render.{ - CCModel, - CCRenderState, - ColourMultiplier, - TextureUtils -} +import codechicken.lib.render.{CCModel, CCRenderState, ColourMultiplier, TextureUtils} import codechicken.lib.vec._ import mrtjp.core.color.Colors import mrtjp.core.vec.Size +import mrtjp.projectred.fabrication.circuitparts.ICGateRenderer import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.util.IIcon @@ -82,7 +78,7 @@ object ICComponentStore { buttonOffIcon = register("button_off") buttonOnIcon = register("button_on") - RenderICGate.registerIcons(reg) + ICGateRenderer.registerIcons(reg) for (m <- WireModel.wireModels) m.icon = register("surface/" + m.iconPath) for (m <- BaseComponentModel.baseModels) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepartarray.scala b/src/main/scala/mrtjp/projectred/fabrication/gatepartarray.scala deleted file mode 100644 index 424782f20..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepartarray.scala +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import cpw.mods.fml.relauncher.{SideOnly, Side} -import mrtjp.core.vec.Point -import mrtjp.projectred.transmission.IWirePart -import net.minecraft.nbt.NBTTagCompound - -trait TArrayGateICPart - extends RedstoneGateICPart - with IRedwireICPart - with TRSPropagatingICPart { - def getLogicArray = getLogic[TArrayICGateLogic[TArrayGateICPart]] - - override def getSignal = - getLogicArray.getSignal(toInternalMask(propagationMask)) - override def setSignal(signal: Int) = - getLogicArray.setSignal(toInternalMask(propagationMask), signal) - - abstract override def updateAndPropagate(prev: CircuitPart, mode: Int) { - val rd = sideDiff(prev) - var uMask = 0 - for (r <- 0 until 4) if ((rd & 1 << r) != 0) { - val pMask = getLogicArray.propogationMask(toInternal(r)) - if (pMask > 0 && (pMask & uMask) != pMask) { - propagationMask = toAbsoluteMask(pMask) - super.updateAndPropagate(prev, mode) - uMask |= pMask - } - } - if (uMask == 0) ICPropagator.addNeighborChange(Point(x, y)) - propagationMask = 0xf - } - - override def propagateOther(mode: Int) { - val nonConn = ~(connMap | connMap >> 4 | connMap >> 8) & 0xf - notify(nonConn & propagationMask) - } - - def sideDiff(part: CircuitPart): Int = { - if (part.world == null) return 0xf - val here = Point(x, y) - val there = Point(part.x, part.y) - there - here match { - case Point(0, -1) => 1 << 0 - case Point(1, 0) => 1 << 1 - case Point(0, 1) => 1 << 2 - case Point(-1, 0) => 1 << 3 - case _ => - throw new RuntimeException( - s"Circuit array gate tried to propagate from $here to #$there" - ) - } - } - - override def calculateSignal: Int = { - val ipmask = toInternalMask(propagationMask) - if (getLogicArray.overrideSignal(ipmask)) - return getLogicArray.calculateSignal(ipmask) - - var s = 0 - ICPropagator.redwiresProvidePower = false - def raise(sig: Int) { if (sig > s) s = sig } - for (r <- 0 until 4) - if ((propagationMask & 1 << r) != 0) raise(calcSignal(r)) - ICPropagator.redwiresProvidePower = true - s - } - - abstract override def onChange() { - super.onChange() - ICPropagator.propagateTo(this, IWirePart.RISING) - } - - override def onSignalUpdate() { - world.network.markSave() - super.onChange() - getLogicArray.onSignalUpdate() - } - - override def resolveSignal(part: Any, r: Int) = part match { - case re: IRedwireICPart if re.diminishOnSide(r) => - re.getRedwireSignal(r) - 1 - case _ => super.resolveSignal(part, r) - } - - override def getRedwireSignal(r: Int) = { - val ir = toInternal(r) - val pmask = getLogicArray.propogationMask(ir) - if (pmask != 0) getLogicArray.getSignal(pmask) - else getLogicRS.getOutput(this, ir) - } - - override def canConnectRS(r: Int): Boolean = { - if (super.canConnectRS(r)) return true - getLogicArray.canConnectRedwire(this, toInternal(r)) - } - - override def rsOutputLevel(r: Int): Int = { - val ir = toInternal(r) - if ((getLogicArray.redwireMask(shape) & 1 << ir) != 0) - return if (ICPropagator.redwiresProvidePower) - getLogicArray.getSignal(getLogicArray.propogationMask(ir)) - else 0 - super.rsOutputLevel(r) - } - - override def diminishOnSide(r: Int) = - (getLogicArray.redwireMask(shape) & 1 << toInternal(r)) != 0 -} - -trait TArrayICGateLogic[T <: TArrayGateICPart] extends RedstoneICGateLogic[T] { - abstract override def canConnectTo(gate: T, part: CircuitPart, r: Int) = - part match { - case re: IRedwireICPart if canConnectRedwire(gate, r) => true - case _ => super.canConnectTo(gate, part, r) - } - - def canConnectRedwire(gate: T, r: Int): Boolean = - canConnectRedwire(gate.shape, r) - def canConnectRedwire(shape: Int, r: Int): Boolean = - (redwireMask(shape) & 1 << r) != 0 - - def redwireMask(shape: Int): Int - - def propogationMask(r: Int): Int - - def getSignal(mask: Int): Int - def setSignal(mask: Int, signal: Int) - - def overrideSignal(mask: Int) = false - def calculateSignal(mask: Int) = 0 - - def canCross = false - - def onSignalUpdate() -} - -class ArrayGateICPart - extends RedstoneGateICPart - with TComplexGateICPart - with TArrayGateICPart { - private var logic: ArrayGateICLogic = null - - override def getLogic[T] = logic.asInstanceOf[T] - - override def assertLogic() { - if (logic == null) logic = ArrayGateICLogic.create(this, subID) - } - - override def getPartType = CircuitPartDefs.ArrayGate -} - -object ArrayGateICLogic { - import ICGateDefinition._ - def create(gate: ArrayGateICPart, subID: Int) = subID match { - case NullCell.ordinal => new NullCell(gate) - case InvertCell.ordinal => new InvertCell(gate) - case BufferCell.ordinal => new BufferCell(gate) - case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) - } -} - -abstract class ArrayGateICLogic(val gate: ArrayGateICPart) - extends RedstoneICGateLogic[ArrayGateICPart] - with TArrayICGateLogic[ArrayGateICPart] - with TComplexICGateLogic[ArrayGateICPart] - -abstract class ArrayGateICLogicCrossing(gate: ArrayGateICPart) - extends ArrayGateICLogic(gate) { - var signal1: Byte = 0 - var signal2: Byte = 0 - - override def redwireMask(shape: Int) = 0xf - override def propogationMask(r: Int) = if (r % 2 == 0) 0x5 else 0xa - override def inputMask(shape: Int) = 0xf - override def outputMask(shape: Int) = 0xf - - override def getSignal(mask: Int) = - (if (mask == 0x5) signal1 else signal2) & 0xff - override def setSignal(mask: Int, signal: Int) { - if (mask == 0x5) signal1 = signal.toByte else signal2 = signal.toByte - } - - override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setByte("s1", signal1) - tag.setByte("s2", signal2) - } - - override def load(tag: NBTTagCompound) { - super.load(tag) - signal1 = tag.getByte("s1") - signal2 = tag.getByte("s2") - } - - override def writeDesc(packet: MCDataOutput) { - super.writeDesc(packet) - packet.writeByte(signal1) - packet.writeByte(signal2) - } - - override def readDesc(packet: MCDataInput) { - super.readDesc(packet) - signal1 = packet.readByte() - signal2 = packet.readByte() - } - - override def read(packet: MCDataInput, key: Int) = key match { - case 11 => - signal1 = packet.readByte() - signal2 = packet.readByte() - case _ => - } - - def sendSignalUpdate() { - gate.writeStreamOf(11).writeByte(signal1).writeByte(signal2) - } - - override def onChange(gate: ArrayGateICPart) { - val oldSignal = (gate.state & 1) != 0 - val newSignal = signal1 != 0 - - if (oldSignal != newSignal) { - gate.setState(gate.state & 2 | (if (newSignal) 1 else 0)) - gate.onInputChange() - gate.scheduleTick(0) - } - } - - override def scheduledTick(gate: ArrayGateICPart) { - val input = (gate.state & 1) != 0 - val oldOutput = (gate.state & 2) != 0 - val newOutput = !input - - if (oldOutput != newOutput) { - gate.setState(gate.state & 1 | (if (newOutput) 2 else 0)) - gate.onOutputChange(0) - gate.onChange() - } - } - - override def onSignalUpdate() { sendSignalUpdate() } - - override def overrideSignal(mask: Int) = if (mask == 0xa) powerUp else false - - override def calculateSignal(mask: Int) = 255 - - def powerUp: Boolean - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: ArrayGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - - if (detailLevel >= 3) { - data += "lower: 0x" + Integer.toHexString(signal1 & 0xff) - data += "upper: 0x" + Integer.toHexString(signal2 & 0xff) - } else if (detailLevel >= 2) { - data += "lower: " + (if (signal1 != 0) "high" else "low") - data += "upper: " + (if (signal2 != 0) "high" else "low") - } - - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} - -class NullCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { - override def powerUp = false -} - -class InvertCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { - override def powerUp = (gate.state & 2) != 0 -} - -class BufferCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { - override def powerUp = (gate.state & 2) == 0 -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepartcomb.scala b/src/main/scala/mrtjp/projectred/fabrication/gatepartcomb.scala deleted file mode 100644 index 58a5aca20..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepartcomb.scala +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import java.util.Random - -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.core.TFaceOrient - -class ComboGateICPart extends RedstoneGateICPart { - override def getLogic[T] = ComboICGateLogic.instances(subID).asInstanceOf[T] - def getLogicCombo = getLogic[ComboICGateLogic] - - override def getPartType = CircuitPartDefs.SimpleGate -} - -object ComboICGateLogic { - val advanceDead = Seq(1, 2, 4, 0, 5, 6, 3) - - val instances = new Array[ComboICGateLogic](ICGateDefinition.values.length) - initialize() - - def initialize() { - import mrtjp.projectred.fabrication.{ICGateDefinition => defs} - instances(defs.OR.ordinal) = OR - instances(defs.NOR.ordinal) = NOR - instances(defs.NOT.ordinal) = NOT - instances(defs.AND.ordinal) = AND - instances(defs.NAND.ordinal) = NAND - instances(defs.XOR.ordinal) = XOR - instances(defs.XNOR.ordinal) = XNOR - instances(defs.Buffer.ordinal) = Buffer - instances(defs.Multiplexer.ordinal) = Multiplexer - instances(defs.Pulse.ordinal) = Pulse - instances(defs.Repeater.ordinal) = Repeater - instances(defs.Randomizer.ordinal) = Randomizer - instances(defs.TransparentLatch.ordinal) = TransparentLatch - instances(defs.DecRandomizer.ordinal) = DecRandomizer - } -} - -trait TSimpleRSICGateLogic[T <: RedstoneGateICPart] - extends RedstoneICGateLogic[T] { - def getDelay(shape: Int) = 0 - - def feedbackMask(shape: Int) = 0 - - def calcOutput(gate: T, input: Int) = 0 - - override def onChange(gate: T) { - val iMask = inputMask(gate.shape) - val oMask = outputMask(gate.shape) - val fMask = feedbackMask(gate.shape) - val oldInput = gate.state & 0xf - val newInput = getInput(gate, iMask | fMask) - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - } - - val newOutput = calcOutput(gate, gate.state & iMask) & oMask - if (newOutput != (gate.state >> 4)) gate.scheduleTick(getDelay(gate.shape)) - } - - override def scheduledTick(gate: T) { - val iMask = inputMask(gate.shape) - val oMask = outputMask(gate.shape) - val oldOutput = gate.state >> 4 - val newOutput = calcOutput(gate, gate.state & iMask) & oMask - if (oldOutput != newOutput) { - gate.setState(gate.state & 0xf | newOutput << 4) - gate.onOutputChange(oMask) - } - onChange(gate) - } - - override def setup(gate: T) { - val iMask = inputMask(gate.shape) - val oMask = outputMask(gate.shape) - val output = calcOutput(gate, getInput(gate, iMask)) & oMask - if (output != 0) { - gate.setState(output << 4) - gate.onOutputChange( - output - ) // use output for change mask because nothing is going low - } - } - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: T, detailLevel: Int) = { - val s = Seq.newBuilder[String] - if (detailLevel > 2) - s += "I: " + rolloverInput(gate) += "O: " + rolloverOutput(gate) - super.getRolloverData(gate, detailLevel) ++ s.result() - } - def rolloverInput(gate: T) = "0x" + Integer.toHexString(gate.state & 0xf) - def rolloverOutput(gate: T) = "0x" + Integer.toHexString(gate.state >> 4) -} - -abstract class ComboICGateLogic - extends RedstoneICGateLogic[ComboGateICPart] - with TSimpleRSICGateLogic[ComboGateICPart] { - override def cycleShape(gate: ComboGateICPart) = { - val oldShape = gate.shape - val newShape = cycleShape(oldShape) - if (newShape != oldShape) { - gate.setShape(newShape) - true - } else false - } - - def cycleShape(shape: Int): Int = { - if (deadSides == 0) return shape - - var shape1 = shape - import java.lang.Integer.{bitCount, numberOfLeadingZeros => lead} - do shape1 = ComboICGateLogic.advanceDead(shape1) while (bitCount( - shape1 - ) > maxDeadSides || 32 - lead(shape1) > deadSides) - shape1 - } - - def deadSides = 0 - def maxDeadSides = deadSides - 1 -} - -object OR extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = ~shape << 1 & 0xe - - override def deadSides = 3 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input != 0) 1 else 0 -} - -object NOR extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = ~shape << 1 & 0xe - override def feedbackMask(shape: Int) = 1 - - override def deadSides = 3 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input == 0) 1 else 0 -} - -object NOT extends ComboICGateLogic { - override def outputMask(shape: Int) = - ~((shape & 1) << 1 | (shape & 2) >> 1 | (shape & 4) << 1) & 0xb - override def inputMask(shape: Int) = 4 - override def feedbackMask(shape: Int) = outputMask(shape) - - override def deadSides = 3 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input == 0) 0xb else 0 -} - -object AND extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = ~shape << 1 & 0xe - - override def deadSides = 3 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input == inputMask(gate.shape)) 1 else 0 -} - -object NAND extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = ~shape << 1 & 0xe - - override def deadSides = 3 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input == inputMask(gate.shape)) 0 else 1 -} - -object XOR extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 10 - - override def calcOutput(gate: ComboGateICPart, input: Int) = { - val side1 = (input & 1 << 1) != 0 - val side2 = (input & 1 << 3) != 0 - if (side1 != side2) 1 else 0 - } -} - -object XNOR extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 10 - - override def calcOutput(gate: ComboGateICPart, input: Int) = { - val side1 = (input & 1 << 1) != 0 - val side2 = (input & 1 << 3) != 0 - if (side1 == side2) 1 else 0 - } -} - -object Buffer extends ComboICGateLogic { - override def outputMask(shape: Int) = - ~((shape & 1) << 1 | (shape & 2) << 2) & 0xb - override def inputMask(shape: Int) = 4 - override def feedbackMask(shape: Int) = outputMask(shape) - - override def deadSides = 2 - override def maxDeadSides = 2 - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input != 0) 0xb else 0 -} - -object Multiplexer extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 0xe - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if ((input & 1 << 2) != 0) (input >> 3) & 1 else (input >> 1) & 1 -} - -object Pulse extends ComboICGateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 4 - - override def calcOutput(gate: ComboGateICPart, input: Int) = 0 - - override def onChange(gate: ComboGateICPart) = { - val oldInput = gate.state & 0xf - val newInput = getInput(gate, 4) - - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - if (newInput != 0 && (gate.state & 0xf0) == 0) { - gate.setState(gate.state & 0xf | 0x10) - gate.scheduleTick(2) - gate.onOutputChange(1) - } - } - } -} - -object Repeater extends ComboICGateLogic { - val delays = Array(2, 4, 6, 8, 16, 32, 64, 128, 256) - - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 4 - - override def getDelay(shape: Int) = delays(shape) - - override def cycleShape(shape: Int) = (shape + 1) % delays.length - - override def calcOutput(gate: ComboGateICPart, input: Int) = - if (input == 0) 0 else 1 - - override def onChange(gate: ComboGateICPart) { - if (gate.schedTime < 0) super.onChange(gate) - } - - override def activate(gate: ComboGateICPart) { - gate.configure() - } - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: ComboGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - if (detailLevel > 1) data += "delay: " + delays(gate.shape) - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} - -object Randomizer extends ComboICGateLogic { - val rand = new Random - - override def outputMask(shape: Int) = - ~((shape & 1) << 1 | (shape & 2) >> 1 | (shape & 4) << 1) & 0xb - override def inputMask(shape: Int) = 4 - override def feedbackMask(shape: Int) = outputMask(shape) - - override def deadSides = 3 - - override def getDelay(shape: Int) = 2 - - override def calcOutput(gate: ComboGateICPart, input: Int) = { - if (input == 0) gate.state >> 4 - else - outputMask(gate.shape) & TFaceOrient.shiftMask(rand.nextInt(8), 3) - } - - override def onChange(gate: ComboGateICPart) { - super.onChange(gate) - if ((gate.state & 4) != 0) gate.scheduleTick(2) - } -} - -object TransparentLatch extends ComboICGateLogic { - override def outputMask(shape: Int) = if (shape == 0) 3 else 9 - override def inputMask(shape: Int) = if (shape == 0) 0xc else 6 - - override def cycleShape(shape: Int) = shape ^ 1 - - override def calcOutput(gate: ComboGateICPart, input: Int) = { - if ((input & 4) == 0) gate.state >> 4 - else if ((input & 0xa) == 0) 0 - else 0xf - } -} - -object DecRandomizer extends ComboICGateLogic { - val rand = new Random - - override def cycleShape(shape: Int) = shape ^ 1 - - override def outputMask(shape: Int) = if (shape == 0) 11 else 9 - override def inputMask(shape: Int) = 4 - override def feedbackMask(shape: Int) = 2 - - override def getDelay(shape: Int) = 2 - - override def calcOutput(gate: ComboGateICPart, input: Int) = { - if (input == 0) if ((gate.state >> 4) == 0) 1 else gate.state >> 4 - else Seq(1, 8, 2)(rand.nextInt((~gate.shape | 2) & 3)) - } - - override def onChange(gate: ComboGateICPart) { - super.onChange(gate) - if ((gate.state & 4) != 0) gate.scheduleTick(2) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepartio.scala b/src/main/scala/mrtjp/projectred/fabrication/gatepartio.scala deleted file mode 100644 index ba5583e29..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepartio.scala +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.color.Colors -import net.minecraft.nbt.NBTTagCompound - -trait IIOCircuitPart { - def onExtInputChanged(r: Int) - def onExtOutputChanged(r: Int) - - def getIOSide: Int - def getIOMode: Int - def getConnMode: Int -} - -object IIOCircuitPart { - val Closed = 0 - val Input = 1 - val Output = 2 - val InOut = 3 - - val NoConn = 0 - val Simple = 1 - val Analog = 2 - val Bundled = 3 -} - -class IOGateICPart - extends RedstoneGateICPart - with IIOCircuitPart - with TComplexGateICPart { - private var logic: IOICGateLogic = null - - override def getLogic[T] = logic.asInstanceOf[T] - def getLogicIO = getLogic[IOICGateLogic] - - override def assertLogic() { - if (logic == null) logic = IOICGateLogic.create(this, subID) - } - - override def readClientPacket(in: MCDataInput, key: Int) = key match { - case 5 => - getLogicIO match { - case f: TFreqIOICGateLogic => f.freqUp() - case _ => - } - case 6 => - getLogicIO match { - case f: TFreqIOICGateLogic => f.freqDown() - case _ => - } - case _ => super.readClientPacket(in, key) - } - - override def getPartType = CircuitPartDefs.IOGate - - override def onExtInputChanged(r: Int) { - if (r == rotation) getLogicIO.extInputChange(this) - } - override def onExtOutputChanged(r: Int) { - if (r == rotation) getLogicIO.extOutputChange(this) - } - override def getIOSide = rotation - override def getIOMode = getLogicIO.getIOMode(this) - override def getConnMode = getLogicIO.getConnMode(this) - - override def getRedstoneInput(r: Int): Int = { - if (r == 0) getLogicIO.resolveInputFromWorld // r is to outside world - else super.getRedstoneInput(r) - } - - override def onOutputChange(mask: Int) { - super.onOutputChange(mask) - if ((mask & 1) != 0) { - val oldOutput = world.iostate(rotation) >>> 16 - getLogicIO.setWorldOutput((state & 0x10) != 0) - val newOutput = world.iostate(rotation) >>> 16 - if (oldOutput != newOutput) world.onOutputChanged(1 << rotation) - } - } -} - -object IOICGateLogic { - import mrtjp.projectred.fabrication.{ICGateDefinition => defs} - - def create(gate: IOGateICPart, subID: Int) = subID match { - case defs.IOSimple.ordinal => new SimpleIOICGateLogic(gate) - case defs.IOAnalog.ordinal => new AnalogIOICGateLogic(gate) - case defs.IOBundled.ordinal => new BundledIOICGateLogic(gate) - case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) - } -} - -abstract class IOICGateLogic(val gate: IOGateICPart) - extends RedstoneICGateLogic[IOGateICPart] - with TComplexICGateLogic[IOGateICPart] { - import IIOCircuitPart._ - - override def inputMask(shape: Int) = shape match { - case 0 => 1 - case 1 => 4 - case 2 => 5 - } - override def outputMask(shape: Int) = shape match { - case 0 => 4 - case 1 => 1 - case 2 => 5 - } - - override def cycleShape(gate: IOGateICPart) = { - gate.setShape((gate.shape + 1) % 3) - true - } - - def extInputChange(gate: IOGateICPart) { gate.onChange() } - def extOutputChange(gate: IOGateICPart) {} - def getIOMode(gate: IOGateICPart): Int = gate.shape match { - case 0 => Input - case 1 => Output - case 2 => InOut - } - def getConnMode(gate: IOGateICPart): Int - - def resolveInputFromWorld: Int - def resolveOutputToWorld: Int - def setWorldOutput(state: Boolean) - def toggleWorldInput() - - override def onChange(gate: IOGateICPart) { - val oldInput = gate.state & 0xf - val newInput = getInput(gate, ~(gate.state >> 4) & inputMask(gate.shape)) - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - gate.scheduleTick(0) - } - } - - override def scheduledTick(gate: IOGateICPart) { - val oldOutput = gate.state >> 4 - val newOutput = - TICOrient.shiftMask(gate.state & 0xf, 2) & outputMask(gate.shape) - if (oldOutput != newOutput) { - gate.setState(gate.state & 0xf | newOutput << 4) - gate.onOutputChange(oldOutput ^ newOutput) - } - onChange(gate) - } - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: IOGateICPart, detailLevel: Int) = { - val s = Seq.newBuilder[String] - if (detailLevel >= 2) { - val f = getFreqName - if (f.nonEmpty) s += "freq: " + f - s += "mode: " + (gate.shape match { - case 0 => "I" - case 1 => "O" - case 2 => "IO" - }) - } - if (detailLevel >= 3) { - s += "I: " + (if (resolveInputFromWorld != 0) "high" else "low") - s += "O: " + (if (resolveOutputToWorld != 0) "high" else "low") - } - super.getRolloverData(gate, detailLevel) ++ s.result() - } - - def getFreqName = "" - - override def activate(gate: IOGateICPart) { - toggleWorldInput() - gate.world.onInputChanged(1 << gate.rotation) - } -} - -trait TRSIOICGateLogic extends IOICGateLogic { - override def setup(gate: IOGateICPart) { - if ((gate.world.iostate(gate.rotation) & 0xffff) == 0) { - gate.world.setInput(gate.rotation, 1) - gate.world.onInputChanged(1 << gate.rotation) - } - } - - override def extInputChange(gate: IOGateICPart) { - if ((gate.world.iostate(gate.rotation) & 0xffff) == 0) { - gate.world.setInput(gate.rotation, 1) - gate.world.onInputChanged(1 << gate.rotation) - } - super.extInputChange(gate) - } -} - -class SimpleIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) - with TRSIOICGateLogic { - override def getConnMode(gate: IOGateICPart) = IIOCircuitPart.Simple - - override def resolveInputFromWorld = - if ((gate.world.iostate(gate.rotation) & 0xfffe) != 0) 255 - else 0 - - override def resolveOutputToWorld = - if (((gate.world.iostate(gate.rotation) >> 16) & 0xfffe) != 0) 255 else 0 - - override def setWorldOutput(state: Boolean) { - gate.world.setOutput(gate.rotation, if (state) 0x8000 else 1) - } - - override def toggleWorldInput() { - gate.world.setInput( - gate.rotation, - if ((gate.world.iostate(gate.rotation) & 0x8000) != 0) 1 else 0x8000 - ) - } - - @SideOnly(Side.CLIENT) - override def createGui(gate: IOGateICPart): CircuitGui = new ICIOGateGui(gate) -} - -trait TFreqIOICGateLogic extends IOICGateLogic { - var freq = 0 - - override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setByte("freq", freq.toByte) - } - - override def load(tag: NBTTagCompound) { - super.load(tag) - freq = tag.getByte("freq") - } - - override def writeDesc(out: MCDataOutput) { - super.writeDesc(out) - out.writeByte(freq) - } - - override def readDesc(in: MCDataInput) { - super.readDesc(in) - freq = in.readUByte() - } - - override def read(in: MCDataInput, key: Int) = key match { - case 12 => freq = in.readUByte() - case _ => super.read(in, key) - } - - def sendFreqUpdate() { - gate.writeStreamOf(12).writeByte(freq) - } - - def freqUp() { - if (freq < 15) { - freq += 1 - sendFreqUpdate() - gate.onChange() - } - } - - def freqDown() { - if (freq > 0) { - freq -= 1 - sendFreqUpdate() - gate.onChange() - } - } - - override def resolveInputFromWorld = - if ((gate.world.iostate(gate.rotation) & 1 << freq) != 0) 255 - else 0 - - override def resolveOutputToWorld = - if ((gate.world.iostate(gate.rotation) >>> 16 & 1 << freq) != 0) 255 - else 0 - - override def setWorldOutput(state: Boolean) { - val s = - ((gate.world.iostate(gate.rotation) >>> 16) & ~(1 << freq)) | (if (state) - 1 - else - 0) << freq - gate.world.setOutput(gate.rotation, s) - } - - @SideOnly(Side.CLIENT) - override def createGui(gate: IOGateICPart): CircuitGui = new ICIOFreqGateGui( - gate - ) -} - -class AnalogIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) - with TFreqIOICGateLogic - with TRSIOICGateLogic { - override def getConnMode(gate: IOGateICPart) = IIOCircuitPart.Analog - - override def getFreqName = "0x" + Integer.toHexString(freq) - - override def toggleWorldInput() { - val newInput = (gate.world.iostate(gate.rotation) & 1 << freq) ^ 1 << freq - gate.world.setInput(gate.rotation, if (newInput == 0) 1 else newInput) - } -} - -class BundledIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) - with TFreqIOICGateLogic { - override def getConnMode(gate: IOGateICPart) = IIOCircuitPart.Bundled - - override def getFreqName = Colors(freq).name.toLowerCase - - override def toggleWorldInput() { - gate.world.setInput( - gate.rotation, - (gate.world.iostate(gate.rotation) & 0xffff) ^ 1 << freq - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gatepartseq.scala b/src/main/scala/mrtjp/projectred/fabrication/gatepartseq.scala deleted file mode 100644 index eac3ce4ef..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gatepartseq.scala +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.multipart.handler.MultipartSaveLoad -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.ProjectRedCore.log -import mrtjp.projectred.core.Configurator -import mrtjp.projectred.core.TFaceOrient._ -import net.minecraft.nbt.NBTTagCompound - -class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart { - var logic: SequentialICGateLogic = null - - override def assertLogic() { - if (logic == null) logic = SequentialICGateLogic.create(this, subID) - } - - override def getLogic[T]: T = logic.asInstanceOf[T] - - override def getPartType = CircuitPartDefs.ComplexGate - - override def readClientPacket(in: MCDataInput, key: Int) = key match { - case 3 => - getLogicPrimitive match { - case t: ITimerGuiLogic => - t.setTimerMax(this, t.getTimerMax + in.readShort()) - case _ => - log.error( - "Server IC stream received client packet for incorrect gate type" - ) - } - case 4 => - getLogicPrimitive match { - case t: ICounterGuiLogic => - val actionID = in.readByte() - actionID match { - case 0 => t.setCounterMax(this, t.getCounterMax + in.readShort()) - case 1 => t.setCounterIncr(this, t.getCounterIncr + in.readShort()) - case 2 => t.setCounterDecr(this, t.getCounterDecr + in.readShort()) - case _ => - log.error( - "Server IC stream received client packet for incorrect gate type" - ) - } - case _ => - log.error( - "Server IC stream received client packet for incorrect gate type" - ) - } - case _ => super.readClientPacket(in, key) - } -} - -object SequentialICGateLogic { - import mrtjp.projectred.fabrication.{ICGateDefinition => defs} - - def create(gate: SequentialGateICPart, subID: Int) = subID match { - case defs.SRLatch.ordinal => new SRLatch(gate) - case defs.ToggleLatch.ordinal => new ToggleLatch(gate) - case defs.Timer.ordinal => new Timer(gate) - case defs.Sequencer.ordinal => new Sequencer(gate) - case defs.Counter.ordinal => new Counter(gate) - case defs.StateCell.ordinal => new StateCell(gate) - case defs.Synchronizer.ordinal => new Synchronizer(gate) - case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) - } -} - -abstract class SequentialICGateLogic(val gate: SequentialGateICPart) - extends RedstoneICGateLogic[SequentialGateICPart] - with TComplexICGateLogic[SequentialGateICPart] - -trait TExtraStateLogic extends SequentialICGateLogic { - private var lState2: Byte = 0 - - def state2 = lState2 & 0xff - def setState2(state: Int) { lState2 = state.toByte } - - def clientState2 = false - - abstract override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setByte("state2", lState2) - } - - abstract override def load(tag: NBTTagCompound) { - super.load(tag) - lState2 = tag.getByte("state2") - } - - abstract override def writeDesc(packet: MCDataOutput) { - super.writeDesc(packet) - if (clientState2) packet.writeByte(lState2) - } - - abstract override def readDesc(packet: MCDataInput) { - super.readDesc(packet) - if (clientState2) lState2 = packet.readByte() - } - - abstract override def read(packet: MCDataInput, key: Int) = key match { - case 11 => lState2 = packet.readByte() - case _ => super.read(packet, key) - } - - def sendState2Update() { gate.writeStreamOf(11).writeByte(lState2) } -} - -class SRLatch(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with TExtraStateLogic { - override def outputMask(shape: Int) = if ((shape >> 1) == 0) 0xf else 5 - override def inputMask(shape: Int) = 0xa - - override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape((gate.shape + 1) % 4) - setState2(flipMaskZ(state2)) - gate.setState(flipMaskZ(gate.state)) - gate.onOutputChange(0xf) - gate.scheduleTick(0) - true - } - - override def setup(gate: SequentialGateICPart) { - setState2(2) - gate.setState(0x30) - } - - override def onChange(gate: SequentialGateICPart) { - val stateInput = state2 - - val oldInput = gate.state & 0xf - val newInput = getInput(gate, 0xa) - val oldOutput = gate.state >> 4 - - if (newInput != oldInput) - if ( - stateInput != 0xa && newInput != 0 && newInput != stateInput - ) // state needs changing - { - gate.setState(newInput) - setState2(newInput) - gate.onOutputChange(oldOutput) // always going low - gate.scheduleTick(0) - } else { - gate.setState(oldOutput << 4 | newInput) - gate.onInputChange() - } - } - - override def scheduledTick(gate: SequentialGateICPart) { - val oldOutput = gate.state >> 4 - val newOutput = calcOutput(gate) - - if (oldOutput != newOutput) { - gate.setState(gate.state & 0xf | newOutput << 4) - gate.onOutputChange(outputMask(gate.shape)) - } - onChange(gate) - } - - def calcOutput(gate: SequentialGateICPart): Int = { - var input = gate.state & 0xf - var stateInput = state2 - - if ((gate.shape & 1) != 0) // reverse - { - input = flipMaskZ(input) - stateInput = flipMaskZ(stateInput) - } - - if (stateInput == 0xa) // disabled - { - if (input == 0xa) { - gate.scheduleTick(0) - return 0 - } - - stateInput = - if (input == 0) - if (gate.world.network.getWorld.rand.nextBoolean()) 2 else 8 - else input - - setState2( - if ((gate.shape & 1) != 0) flipMaskZ(stateInput) else stateInput - ) - } - - var output = shiftMask(stateInput, 1) - if ((gate.shape & 2) == 0) output |= stateInput - if ((gate.shape & 1) != 0) output = flipMaskZ(output) // reverse - output - } -} - -class ToggleLatch(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with TExtraStateLogic { - override def outputMask(shape: Int) = 5 - override def inputMask(shape: Int) = 0xa - - override def clientState2 = true - - override def setup(gate: SequentialGateICPart) { - gate.setState(0x10) - gate.sendStateUpdate() - } - - override def onChange(gate: SequentialGateICPart) { - val oldInput = gate.state & 0xf - val newInput = getInput(gate, 0xa) - val high = newInput & ~oldInput - - if (high == 2 || high == 8) toggle(gate) - - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - } - } - - override def scheduledTick(gate: SequentialGateICPart) { - val oldOutput = gate.state >> 4 - val newOutput = if (state2 == 0) 1 else 4 - if (oldOutput != newOutput) { - gate.setState(newOutput << 4 | gate.state & 0xf) - gate.onOutputChange(5) - } - onChange(gate) - } - - override def activate(gate: SequentialGateICPart) { - toggle(gate) - } - - def toggle(gate: SequentialGateICPart) { - setState2(state2 ^ 1) - gate.scheduleTick(0) - } -} - -trait ITimerGuiLogic { - def getTimerMax: Int - def setTimerMax(gate: GateICPart, t: Int) -} - -trait ICounterGuiLogic { - def getCounterMax: Int - def setCounterMax(gate: GateICPart, i: Int) - - def getCounterIncr: Int - def setCounterIncr(gate: GateICPart, i: Int) - - def getCounterDecr: Int - def setCounterDecr(gate: GateICPart, i: Int) - - def getCounterValue: Int - def setCounterValue(gate: GateICPart, i: Int) -} - -trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { - var pointer_max = 38 - var pointer_start = -1L - var saveTime = -1L // used for blueprint in-hand rendering - - abstract override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setInteger("pmax", pointer_max) - tag.setLong( - "pelapsed", - if (pointer_start < 0) pointer_start else getTotalTime - pointer_start - ) - tag.setLong("tsave", getTotalTime) - } - - abstract override def load(tag: NBTTagCompound) { - super.load(tag) - pointer_max = tag.getInteger("pmax") - pointer_start = tag.getLong("pelapsed") - saveTime = tag.getLong("tsave") - if (pointer_start >= 0) pointer_start = getTotalTime - pointer_start - } - - abstract override def writeDesc(packet: MCDataOutput) { - super.writeDesc(packet) - packet.writeInt(pointer_max) - packet.writeLong(pointer_start) - } - - abstract override def readDesc(packet: MCDataInput) { - super.readDesc(packet) - pointer_max = packet.readInt() - pointer_start = packet.readLong() - } - - abstract override def read(packet: MCDataInput, key: Int) = key match { - case 12 => pointer_max = packet.readInt() - case 13 => - pointer_start = packet.readInt() - if (pointer_start >= 0) pointer_start = getTotalTime - pointer_start - case _ => super.read(packet, key) - } - - def getTotalTime = // client-side safe version of getTotalWorldTime (workaround for no client world) - { - if (gate.world.network == null) - saveTime // ic was loaded directly from stack, possibly for in-hand render - else if (gate.world.network.getWorld == null) - MultipartSaveLoad.loadingWorld.getTotalWorldTime // ic is being loaded with a workbench tile or gate - else - gate.world.network.getWorld.getTotalWorldTime // normal access during operation - } - - def pointerValue = - if (pointer_start < 0) 0 else (getTotalTime - pointer_start).toInt - - def sendPointerMaxUpdate() { gate.writeStreamOf(12).writeInt(pointer_max) } - def sendPointerUpdate() { - gate.writeStreamOf(13).writeInt(if (pointer_start < 0) -1 else pointerValue) - } - - override def getTimerMax = pointer_max + 2 - override def setTimerMax(gate: GateICPart, time: Int) { - var t = time - val minTime = math.max(4, Configurator.minTimerTicks) - if (t < minTime) t = minTime - if (t != pointer_max) { - pointer_max = t - 2 - sendPointerMaxUpdate() - } - } - - override def onTick(gate: SequentialGateICPart) { - if (pointer_start >= 0) - if (getTotalTime >= pointer_start + pointer_max) pointerTick() - else if (pointer_start > getTotalTime) - pointer_start = getTotalTime - } - - def pointerTick() - - def resetPointer() { - if (pointer_start >= 0) { - pointer_start = -1 - gate.world.network.markSave() - if (!gate.world.network.isRemote) sendPointerUpdate() - } - } - - def startPointer() { - if (pointer_start < 0) { - pointer_start = getTotalTime - gate.world.network.markSave() - if (!gate.world.network.isRemote) sendPointerUpdate() - } - } - - def interpPointer(f: Float) = - if (pointer_start < 0) 0f else (pointerValue + f) / pointer_max - - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICTimerGateGui(gate) - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - if (detailLevel > 1) - data += "interval: " + "%.2f".format(getTimerMax * 0.05) + "s" - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} - -class Timer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with TTimerGateLogic { - override def outputMask(shape: Int) = 0xb - override def inputMask(shape: Int) = 0xe - - override def setup(gate: SequentialGateICPart) { startPointer() } - - override def scheduledTick(gate: SequentialGateICPart) { - gate.setState(gate.state & 0xf) - gate.onOutputChange(0xb) - onChange(gate) - } - - override def onChange(gate: SequentialGateICPart) { - val oldInput = gate.state & 0xf - val newInput = getInput(gate, 0xe) - - if (newInput != oldInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - } - - if (gate.schedTime < 0) - if (newInput > 0) resetPointer() else startPointer() - } - - override def pointerTick() { - resetPointer() - if (!gate.world.network.isRemote) { - gate.scheduleTick(2) - gate.setState(0xb0 | gate.state & 0xf) - gate.onOutputChange(0xb) - } - } -} - -class Sequencer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with ITimerGuiLogic { - var pointer_max = 40 - var saveTime = -1L - - override def outputMask(shape: Int) = 0xf - - override def onChange(gate: SequentialGateICPart) {} - override def scheduledTick(gate: SequentialGateICPart) {} - - override def getTimerMax = pointer_max - override def setTimerMax(gate: GateICPart, time: Int) { - var t = time - val minTime = math.max(4, Configurator.minTimerTicks) - if (t < minTime) t = minTime - if (t != pointer_max) { - pointer_max = t - sendPointerMaxUpdate() - } - } - - override def save(tag: NBTTagCompound) { - tag.setInteger("pmax", pointer_max) - tag.setLong("tsave", getWorldTime) - } - override def load(tag: NBTTagCompound) { - pointer_max = tag.getInteger("pmax") - saveTime = tag.getLong("tsave") - } - - override def writeDesc(packet: MCDataOutput) { packet.writeInt(pointer_max) } - override def readDesc(packet: MCDataInput) { pointer_max = packet.readInt() } - - override def read(packet: MCDataInput, key: Int) = key match { - case 12 => pointer_max = packet.readInt() - case _ => - } - - def sendPointerMaxUpdate() { gate.writeStreamOf(12).writeInt(pointer_max) } - - def getWorldTime = - if (gate.world.network != null) gate.world.network.getWorld.getWorldTime - else saveTime - - override def onTick(gate: SequentialGateICPart) { - if (!gate.world.network.isRemote) { - val oldOut = gate.state >> 4 - var out = 1 << getWorldTime % (pointer_max * 4) / pointer_max - if (gate.shape == 1) out = flipMaskZ(out) - if (oldOut != out) { - gate.setState(out << 4) - gate.onOutputChange(0xf) - } - } - } - - override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape(gate.shape ^ 1) - true - } - - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICTimerGateGui(gate) - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - if (detailLevel > 1) - data += "interval: " + "%.2f".format(getTimerMax * 0.05) + "s" - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} - -class Counter(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with ICounterGuiLogic { - var value = 0 - var max = 10 - var incr = 1 - var decr = 1 - - override def outputMask(shape: Int) = 5 - override def inputMask(shape: Int) = 10 - - override def save(tag: NBTTagCompound) { - tag.setInteger("val", value) - tag.setInteger("max", max) - tag.setInteger("inc", incr) - tag.setInteger("dec", decr) - } - - override def load(tag: NBTTagCompound) { - value = tag.getInteger("val") - max = tag.getInteger("max") - incr = tag.getInteger("inc") - decr = tag.getInteger("dec") - } - - override def writeDesc(packet: MCDataOutput) { - packet.writeInt(value).writeInt(max).writeInt(incr).writeInt(decr) - } - - override def readDesc(packet: MCDataInput) { - value = packet.readInt() - max = packet.readInt() - incr = packet.readInt() - decr = packet.readInt() - } - - override def read(packet: MCDataInput, key: Int) = key match { - case 11 => value = packet.readInt() - case 12 => max = packet.readInt() - case 13 => incr = packet.readInt() - case 14 => decr = packet.readInt() - case _ => - } - - def sendValueUpdate() { gate.writeStreamOf(11).writeInt(value) } - def sendMaxUpdate() { gate.writeStreamOf(12).writeInt(max) } - def sendIncrUpdate() { gate.writeStreamOf(13).writeInt(incr) } - def sendDecrUpdate() { gate.writeStreamOf(14).writeInt(decr) } - - override def getCounterValue = value - override def getCounterMax = max - override def getCounterIncr = incr - override def getCounterDecr = decr - - override def setCounterValue(gate: GateICPart, i: Int) { - val oldVal = value - value = Math.min(max, Math.max(0, i)) - if (value != oldVal) - sendValueUpdate() - } - - override def setCounterMax(gate: GateICPart, i: Int) { - val oldMax = max - max = Math.min(32767, Math.max(1, i)) - if (max != oldMax) { - sendMaxUpdate() - val oldVal = value - value = Math.min(value, Math.max(0, i)) - if (value != oldVal) { - sendValueUpdate() - gate.scheduleTick(2) - } - } - } - - override def setCounterIncr(gate: GateICPart, i: Int) { - val oldIncr = incr - incr = Math.min(max, Math.max(1, i)) - if (incr != oldIncr) - sendIncrUpdate() - } - - override def setCounterDecr(gate: GateICPart, i: Int) { - val oldDecr = decr - decr = Math.min(max, Math.max(1, i)) - if (decr != oldDecr) - sendDecrUpdate() - } - - def onChange(gate: SequentialGateICPart) { - val oldInput = gate.state & 0xf - var newInput = getInput(gate, 0xa) - if (gate.shape == 1) newInput = flipMaskZ(newInput) - val high = newInput & ~oldInput - - if ((high & 2) != 0) setCounterValue(gate, value + incr) - if ((high & 8) != 0) setCounterValue(gate, value - decr) - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - gate.scheduleTick(2) - } - } - - override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape(if (gate.shape == 1) 0 else 1) - true - } - - def scheduledTick(gate: SequentialGateICPart) { - val oldOutput = gate.state - var newOutput = 0 - if (value == max) newOutput = 1 - else if (value == 0) newOutput = 4 - if (newOutput != oldOutput) gate.setState(gate.state & 0xf | newOutput << 4) - if (newOutput != oldOutput) gate.onOutputChange(5) - } - - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICCounterGateGui(gate) - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - if (detailLevel > 1) { - data += "state: " + getCounterValue - if (detailLevel > 2) { - data += "max: " + getCounterMax - data += "incr: " + getCounterIncr - data += "decr: " + getCounterDecr - } - } - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} - -class StateCell(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with TTimerGateLogic - with TExtraStateLogic { - override def outputMask(shape: Int) = { - var output = 9 - if (shape == 1) output = flipMaskZ(output) - output - } - - override def inputMask(shape: Int) = { - var input = 6 - if (shape == 1) input = flipMaskZ(input) - input - } - - override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape((gate.shape + 1) % 2) - true - } - - override def onChange(gate: SequentialGateICPart) { - val oldInput = gate.state & 0xf - var newInput = getInput(gate, 0xe) - if (oldInput != newInput) { - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - - if (gate.shape == 1) newInput = flipMaskZ(newInput) - if ((newInput & 4) != 0 && state2 == 0) { - setState2(1) - sendState2Update() - gate.scheduleTick(0) - } - - if (state2 != 0) - if ((newInput & 6) != 0) resetPointer() - else startPointer() - } - } - - override def pointerTick() { - resetPointer() - if (!gate.world.network.isRemote) { - setState2(0) - sendState2Update() - gate.setState(0x10 | gate.state & 0xf) - gate.onOutputChange(outputMask(gate.shape)) - gate.scheduleTick(2) - } - } - - override def scheduledTick(gate: SequentialGateICPart) { - var output = 0 - if (state2 != 0) output = 8 - if (gate.shape == 1) output = flipMaskZ(output) - - gate.setState(output << 4 | gate.state & 0xf) - gate.onOutputChange(outputMask(gate.shape)) - } -} - -class Synchronizer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) - with TExtraStateLogic { - override def outputMask(shape: Int) = 1 - override def inputMask(shape: Int) = 14 - - override def onChange(gate: SequentialGateICPart) { - val oldInput = gate.state & 0xf - val newInput = getInput(gate, 14) - val high = newInput & ~oldInput - if (oldInput != newInput) { - val oldValue = state2 - - gate.setState(gate.state & 0xf0 | newInput) - gate.onInputChange() - if ((newInput & 4) != 0) setState2(0) - else { - if ((high & 2) != 0) setState2(state2 | 1) // right - if ((high & 8) != 0) setState2(state2 | 2) // left - } - if (right && left) gate.scheduleTick(0) - - if (state2 != oldValue) sendState2Update() - } - } - - override def scheduledTick(gate: SequentialGateICPart) { - val oldValue = state2 - if (!pulsing && right && left) { - gate.setState(gate.state | 1 << 4) - gate.onOutputChange(1) - setState2(state2 | 4) // pulsing - gate.scheduleTick(2) - } else if (pulsing) { - gate.setState(gate.state & ~0x10) - gate.onOutputChange(1) - setState2(0) // off - } - if (state2 != oldValue) sendState2Update() - } - - def right = (state2 & 1) != 0 - def left = (state2 & 2) != 0 - def pulsing = (state2 & 4) != 0 - - @SideOnly(Side.CLIENT) - override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { - val data = Seq.newBuilder[String] - if (detailLevel > 1) { - data += "0: " + (if (right) "high" else "low") - data += "1: " + (if (left) "high" else "low") - } - super.getRolloverData(gate, detailLevel) ++ data.result() - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala b/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala deleted file mode 100644 index e2bd88417..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gaterenders.scala +++ /dev/null @@ -1,993 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.math.MathHelper -import codechicken.lib.render.CCRenderState -import codechicken.lib.vec.Transformation -import mrtjp.core.color.Colors -import mrtjp.projectred.core.TFaceOrient._ -import mrtjp.projectred.fabrication.ICComponentStore._ -import net.minecraft.client.renderer.texture.IIconRegister - -object RenderICGate { - var renderers = buildRenders() - - def buildRenders() = Seq[ICGateRenderer[_]]( - new RenderSimpleIO, - new RenderAnalogIO, - new RenderBundledIO, - new RenderOR, - new RenderNOR, - new RenderNOT, - new RenderAND, - new RenderNAND, - new RenderXOR, - new RenderXNOR, - new RenderBuffer, - new RenderMultiplexer, - new RenderPulse, - new RenderRepeater, - new RenderRandomizer, - new RenderSRLatch, - new RenderToggleLatch, - new RenderTransparentLatch, - new RenderTimer, - new RenderSequencer, - new RenderCounter, - new RenderStateCell, - new RenderSynchronizer, - new RenderDecRandomizer, - new RenderNullCell, - new RenderInvertCell, - new RenderBufferCell - ) - - def registerIcons(reg: IIconRegister) {} - - def renderDynamic( - gate: GateICPart, - t: Transformation, - ortho: Boolean, - frame: Float - ) { - val r = renderers(gate.subID).asInstanceOf[ICGateRenderer[GateICPart]] - r.prepareDynamic(gate, frame) - r.renderDynamic(gate.rotationT `with` t, ortho) - } - - def renderWithConfiguration(configuration: Int, t: Transformation, id: Int): Unit = { - val r = renderers(id) - r.prepareStatic(configuration) - r.renderDynamic(t, true) - } - - def renderInv(t: Transformation, id: Int) { - val r = renderers(id) - r.prepareStatic(0) - r.renderDynamic(t, true) - } -} - -abstract class ICGateRenderer[T <: GateICPart] { - var reflect = false - - def coreModels: Seq[ICComponentModel] - def switchModels = Seq[ICComponentModel]() - - def prepareStatic(configuration: Int) - def prepareDynamic(gate: T, frame: Float) {} - - def renderDynamic(t: Transformation, ortho: Boolean) { - renderModels(t, if (reflect) 1 else 0, ortho) - } - - def renderModels(t: Transformation, orient: Int, ortho: Boolean) { - prepairRender() - for (m <- coreModels ++ switchModels) m.renderModel(t, orient, ortho) - finishRender() - } -} - -abstract class RenderIO extends ICGateRenderer[IOGateICPart] { - val wires = generateWireModels("IOSIMP", 1) - val iosig = new IOSigModel - - override val coreModels = - Seq(new BaseComponentModel("IOSIMP")) ++ wires :+ iosig - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - iosig.on = false - iosig.colour = invColour - } - - override def prepareDynamic(gate: IOGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x44) != 0 - iosig.on = wires(0).on - iosig.colour = dynColour(gate) - } - - def invColour: Int - def dynColour(gate: IOGateICPart): Int -} - -class RenderSimpleIO extends RenderIO { - override def invColour = signalColour(0.toByte) - override def dynColour(gate: IOGateICPart) = signalColour( - (if (iosig.on) 255 else 0).toByte - ) -} - -class RenderAnalogIO extends RenderIO { - override def invColour = signalColour(0.toByte) - override def dynColour(gate: IOGateICPart) = signalColour( - (gate.getLogic[AnalogIOICGateLogic].freq * 17).toByte - ) -} - -class RenderBundledIO extends RenderIO { - override def invColour = Colors(0).rgba - override def dynColour(gate: IOGateICPart) = Colors( - gate.getLogic[AnalogIOICGateLogic].freq - ).rgba -} - -class RenderOR extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("OR", 4) - val torches = - Seq(new RedstoneTorchModel(8, 9), new RedstoneTorchModel(8, 2.5)) - - override val coreModels = - Seq(new BaseComponentModel("OR")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(1).disabled = (configuration & 1) != 0 - wires(2).disabled = (configuration & 2) != 0 - wires(3).disabled = (configuration & 4) != 0 - torches(0).on = true - torches(1).on = false - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x10) == 0 - wires(1).on = (gate.state & 2) != 0 - wires(2).on = (gate.state & 4) != 0 - wires(3).on = (gate.state & 8) != 0 - wires(1).disabled = (gate.shape & 1) != 0 - wires(2).disabled = (gate.shape & 2) != 0 - wires(3).disabled = (gate.shape & 4) != 0 - torches(0).on = (gate.state & 0xe) == 0 - torches(1).on = !wires(0).on - } -} - -class RenderNOR extends ICGateRenderer[ComboGateICPart] { - var wires = generateWireModels("NOR", 4) - var torch = new RedstoneTorchModel(8, 9) - - override val coreModels = Seq(new BaseComponentModel("NOR")) ++ wires :+ torch - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(1).disabled = (configuration & 1) != 0 - wires(2).disabled = (configuration & 2) != 0 - wires(3).disabled = (configuration & 4) != 0 - torch.on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x11) != 0 - wires(1).on = (gate.state & 2) != 0 - wires(2).on = (gate.state & 4) != 0 - wires(3).on = (gate.state & 8) != 0 - wires(1).disabled = (gate.shape & 1) != 0 - wires(2).disabled = (gate.shape & 2) != 0 - wires(3).disabled = (gate.shape & 4) != 0 - torch.on = (gate.state & 0xe) == 0 - } -} - -class RenderNOT extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("NOT", 4) - val torch = new RedstoneTorchModel(8, 8) - - override val coreModels = Seq(new BaseComponentModel("NOT")) ++ wires :+ torch - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = true - wires(2).on = false - wires(3).on = true - wires(0).disabled = (configuration & 2) != 0 - wires(1).disabled = (configuration & 1) != 0 - wires(3).disabled = (configuration & 4) != 0 - torch.on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x11) != 0 - wires(1).on = (gate.state & 0x22) != 0 - wires(2).on = (gate.state & 4) != 0 - wires(3).on = (gate.state & 0x88) != 0 - wires(0).disabled = (gate.shape & 2) != 0 - wires(1).disabled = (gate.shape & 1) != 0 - wires(3).disabled = (gate.shape & 4) != 0 - torch.on = (gate.state & 0xf0) != 0 - } -} - -class RenderAND extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("AND", 4) - val torches = Seq( - new RedstoneTorchModel(4, 8), - new RedstoneTorchModel(12, 8), - new RedstoneTorchModel(8, 8), - new RedstoneTorchModel(8, 2) - ) - - override val coreModels = - Seq(new BaseComponentModel("AND")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(3).disabled = (configuration & 1) != 0 - wires(1).disabled = (configuration & 2) != 0 - wires(2).disabled = (configuration & 4) != 0 - torches(2).on = !wires(1).on && !wires(1).disabled - torches(0).on = !wires(2).on && !wires(2).disabled - torches(1).on = !wires(3).on && !wires(3).disabled - torches(3).on = false - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x11) == 0 - wires(3).on = (gate.state & 2) != 0 - wires(1).on = (gate.state & 4) != 0 - wires(2).on = (gate.state & 8) != 0 - wires(3).disabled = (gate.shape & 1) != 0 - wires(1).disabled = (gate.shape & 2) != 0 - wires(2).disabled = (gate.shape & 4) != 0 - torches(2).on = !wires(1).on && !wires(1).disabled - torches(0).on = !wires(2).on && !wires(2).disabled - torches(1).on = !wires(3).on && !wires(3).disabled - torches(3).on = !wires(0).on - } -} - -class RenderNAND extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("NAND", 4) - val torches = Seq( - new RedstoneTorchModel(4, 8), - new RedstoneTorchModel(12, 8), - new RedstoneTorchModel(8, 8) - ) - - override val coreModels = - Seq(new BaseComponentModel("NAND")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(3).disabled = (configuration & 1) != 0 - wires(1).disabled = (configuration & 2) != 0 - wires(2).disabled = (configuration & 4) != 0 - torches(0).on = !wires(2).on && !wires(2).disabled - torches(1).on = !wires(3).on && !wires(3).disabled - torches(2).on = !wires(1).on && !wires(1).disabled - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x11) != 0 - wires(3).on = (gate.state & 2) != 0 - wires(1).on = (gate.state & 4) != 0 - wires(2).on = (gate.state & 8) != 0 - wires(3).disabled = (gate.shape & 1) != 0 - wires(1).disabled = (gate.shape & 2) != 0 - wires(2).disabled = (gate.shape & 4) != 0 - torches(0).on = !wires(2).on && !wires(2).disabled - torches(1).on = !wires(3).on && !wires(3).disabled - torches(2).on = !wires(1).on && !wires(1).disabled - } -} - -class RenderXOR extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("XOR", 4) - val torches = Seq( - new RedstoneTorchModel(4.5, 8), - new RedstoneTorchModel(11.5, 8), - new RedstoneTorchModel(8, 12) - ) - - override val coreModels = - Seq(new BaseComponentModel("XOR")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(3).on = false - wires(2).on = false - wires(1).on = true - torches(0).on = false - torches(1).on = false - torches(2).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x11) != 0 - wires(3).on = (gate.state & 2) != 0 - wires(2).on = (gate.state & 8) != 0 - wires(1).on = !wires(3).on && !wires(2).on - torches(0).on = !wires(2).on && !wires(1).on - torches(1).on = !wires(3).on && !wires(1).on - torches(2).on = wires(1).on - } -} - -class RenderXNOR extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("XNOR", 5) - val torches = Seq( - new RedstoneTorchModel(8, 2), - new RedstoneTorchModel(4.5, 8), - new RedstoneTorchModel(11.5, 8), - new RedstoneTorchModel(8, 12) - ) - - override val coreModels = - Seq(new BaseComponentModel("XNOR")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(3).on = false - wires(2).on = false - wires(1).on = false - torches(0).on = true - torches(1).on = false - torches(2).on = false - torches(3).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 2) != 0 && (gate.state & 8) == 0 - wires(1).on = (gate.state & 8) != 0 && (gate.state & 2) == 0 - wires(2).on = (gate.state & 8) != 0 - wires(3).on = (gate.state & 2) != 0 - wires(4).on = !wires(3).on && !wires(2).on - torches(0).on = (gate.state & 0x11) != 0 - torches(1).on = !wires(4).on && (gate.state & 8) == 0 - torches(2).on = !wires(4).on && (gate.state & 2) == 0 - torches(3).on = (gate.state & 2) == 0 && (gate.state & 8) == 0 - } -} - -class RenderBuffer extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("BUFFER", 4) - val torches = - Seq(new RedstoneTorchModel(8, 3.5), new RedstoneTorchModel(8, 9)) - - override val coreModels = - Seq(new BaseComponentModel("BUFFER")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(1).disabled = (configuration & 1) != 0 - wires(3).disabled = (configuration & 2) != 0 - torches(0).on = false - torches(1).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 4) == 0 - wires(1).on = (gate.state & 0x22) != 0 - wires(2).on = (gate.state & 0x44) != 0 - wires(3).on = (gate.state & 0x88) != 0 - wires(1).disabled = (gate.shape & 1) != 0 - wires(3).disabled = (gate.shape & 2) != 0 - torches(0).on = (gate.state & 4) != 0 - torches(1).on = (gate.state & 4) == 0 - } -} - -class RenderMultiplexer extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("MULTIPLEXER", 6) - val torches = Seq( - new RedstoneTorchModel(8, 2), - new RedstoneTorchModel(9, 10.5), - new RedstoneTorchModel(4.5, 8), - new RedstoneTorchModel(11.5, 8) - ) - - override val coreModels = - Seq(new BaseComponentModel("MULTIPLEXER")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(1).on = true - wires(2).on = true - wires(3).on = false - wires(4).on = false - wires(5).on = false - torches(0).on = false - torches(1).on = true - torches(2).on = false - torches(3).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(2).on = (gate.state & 4) == 0 - wires(3).on = (gate.state & 4) != 0 - wires(4).on = (gate.state & 8) != 0 - wires(5).on = (gate.state & 2) != 0 - torches(0).on = (gate.state & 0x10) != 0 - torches(1).on = !wires(3).on - torches(2).on = (gate.state & 8) == 0 && wires(3).on - torches(3).on = (gate.state & 4) == 0 && !wires(5).on - wires(0).on = torches(2).on - wires(1).on = torches(1).on - } -} - -class RenderPulse extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("PULSE", 3) - val torches = Seq( - new RedstoneTorchModel(4, 9.5), - new RedstoneTorchModel(11, 9.5), - new RedstoneTorchModel(8, 3.5) - ) - - override val coreModels = - Seq(new BaseComponentModel("PULSE")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - wires(2).on = false - torches(0).on = true - torches(1).on = false - torches(2).on = false - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 4) == 0 - wires(1).on = (gate.state & 4) != 0 - wires(2).on = (gate.state & 0x14) == 4 - torches(0).on = wires(0).on - torches(1).on = wires(1).on - torches(2).on = (gate.state & 0x10) != 0 - } -} - -class RenderRepeater extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("REPEATER", 2) - val endTorch = new RedstoneTorchModel(8, 2) - val varTorches = Seq( - new RedstoneTorchModel(12.5, 12), - new RedstoneTorchModel(12.5, 11), - new RedstoneTorchModel(12.5, 10), - new RedstoneTorchModel(12.5, 9), - new RedstoneTorchModel(12.5, 8), - new RedstoneTorchModel(12.5, 7), - new RedstoneTorchModel(12.5, 6), - new RedstoneTorchModel(12.5, 5), - new RedstoneTorchModel(12.5, 4) - ) - - var shape = 0 - - override val coreModels = - Seq(new BaseComponentModel("REPEATER")) ++ wires :+ endTorch - - override def switchModels = Seq(varTorches(shape)) - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = false - endTorch.on = false - shape = configuration % 8 - varTorches(0).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(0).on = (gate.state & 0x10) == 0 - wires(1).on = (gate.state & 4) != 0 - endTorch.on = (gate.state & 0x10) != 0 - shape = gate.shape % 8 - varTorches(shape).on = (gate.state & 4) == 0 - } -} - -class RenderRandomizer extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("RAND", 7) - val chips = Seq( - new YellowChipModel(8, 5.5), - new YellowChipModel(11.5, 11.5), - new YellowChipModel(4.5, 11.5) - ) - - override val coreModels = - Seq(new BaseComponentModel("RAND")) ++ wires ++ chips - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(4).on = false - wires(5).on = false - wires(6).on = false - wires(1).disabled = (configuration & 1) != 0 - wires(0).disabled = (configuration & 2) != 0 - wires(3).disabled = (configuration & 4) != 0 - wires(5).disabled = wires(1).disabled - wires(4).disabled = wires(0).disabled - wires(6).disabled = wires(3).disabled - chips(0).on = false - chips(1).on = false - chips(2).on = false - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - wires(2).on = (gate.state & 4) != 0 - wires(0).on = (gate.state & 0x11) != 0 - wires(1).on = (gate.state & 0x22) != 0 - wires(3).on = (gate.state & 0x88) != 0 - wires(4).on = wires(2).on - wires(5).on = wires(2).on - wires(6).on = wires(2).on - wires(1).disabled = (gate.shape & 1) != 0 - wires(0).disabled = (gate.shape & 2) != 0 - wires(3).disabled = (gate.shape & 4) != 0 - wires(5).disabled = wires(1).disabled - wires(4).disabled = wires(0).disabled - wires(6).disabled = wires(3).disabled - chips(0).on = (gate.state & 0x10) != 0 - chips(1).on = (gate.state & 0x20) != 0 - chips(2).on = (gate.state & 0x80) != 0 - } -} - -class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { - val wires1 = generateWireModels("RSLATCH", 2) - val wires2 = generateWireModels("RSLATCH2", 4) - val torches1 = - Seq(new RedstoneTorchModel(8, 3), new RedstoneTorchModel(8, 13)) - val torches2 = - Seq(new RedstoneTorchModel(9.5, 3), new RedstoneTorchModel(6.5, 13)) - val base1 = new BaseComponentModel("RSLATCH") - val base2 = new BaseComponentModel("RSLATCH2") - - val m1 = Seq(base1) ++ wires1 ++ torches1 - val m2 = Seq(base2) ++ wires2 ++ torches2 - - var shape = 0 - - override val coreModels = Seq() - override def switchModels = if (shape == 0) m1 else m2 - - override def prepareStatic(configuration: Int): Unit = { - reflect = false - shape = 0 - wires1(0).on = false - wires1(1).on = true - torches1(0).on = false - torches1(1).on = true - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - reflect = (gate.shape & 1) != 0 - shape = gate.shape >> 1 - var state = gate.state - if (reflect) state = flipMaskZ(state >> 4) << 4 | flipMaskZ(state) - if (shape == 0) { - wires1(0).on = (state & 0x88) != 0 - wires1(1).on = (state & 0x22) != 0 - torches1(0).on = (state & 0x10) != 0 - torches1(1).on = (state & 0x40) != 0 - } else { - wires2(1).on = (state & 2) != 0 - wires2(3).on = (state & 8) != 0 - torches2(0).on = (state & 0x10) != 0 - torches2(1).on = (state & 0x40) != 0 - wires2(0).on = torches2(1).on - wires2(2).on = torches2(0).on - } - } -} - -class RenderToggleLatch extends ICGateRenderer[SequentialGateICPart] { - val wires = generateWireModels("TOGLATCH", 2) - val torches = Seq(new RedstoneTorchModel(4, 4), new RedstoneTorchModel(4, 12)) - val lever = new LeverModel(11, 8) - - override val coreModels = - Seq(new BaseComponentModel("TOGLATCH")) ++ wires ++ torches :+ lever - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(1).on = false - torches(0).on = true - torches(1).on = false - lever.on = true - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - wires(0).on = (gate.state & 8) != 0 - wires(1).on = (gate.state & 2) != 0 - torches(0).on = (gate.state & 0x10) != 0 - torches(1).on = (gate.state & 0x40) != 0 - lever.on = (gate.state & 0x10) != 0 - } -} - -class RenderTransparentLatch extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("TRANSLATCH", 5) - val torches = Seq( - new RedstoneTorchModel(4, 12.5), - new RedstoneTorchModel(4, 8), - new RedstoneTorchModel(8, 8), - new RedstoneTorchModel(8, 2), - new RedstoneTorchModel(14, 8) - ) - - override val coreModels = - Seq(new BaseComponentModel("TRANSLATCH")) ++ wires ++ torches - - override def prepareStatic(configuration: Int): Unit = { - reflect = false - wires(0).on = true - wires(1).on = false - wires(2).on = true - wires(3).on = false - wires(4).on = false - torches(0).on = true - torches(1).on = false - torches(2).on = true - torches(3).on = false - torches(4).on = false - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - reflect = gate.shape == 1 - val on = (gate.state & 0x10) != 0 - wires(0).on = !on - wires(1).on = (gate.state & 4) != 0 - wires(2).on = (gate.state & 4) == 0 - wires(3).on = on - wires(4).on = (gate.state & 0xa) != 0 - torches(0).on = wires(2).on - torches(1).on = !wires(2).on && !wires(4).on - torches(2).on = !wires(1).on && !wires(3).on - torches(3).on = on - torches(4).on = on - } -} - -class RenderTimer extends ICGateRenderer[SequentialGateICPart] { - val wires = generateWireModels("TIME", 3) - val torches = Seq(new RedstoneTorchModel(8, 3), new RedstoneTorchModel(8, 8)) - val pointer = new PointerModel(8, 8) - - override val coreModels = - Seq(new BaseComponentModel("TIME")) ++ wires ++ Seq(pointer) ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(1).on = false - wires(2).on = false - torches(0).on = false - pointer.angle = 0 - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - torches(0).on = (gate.state & 0x10) != 0 - wires(0).on = (gate.state & 0x88) != 0 - wires(1).on = (gate.state & 0x22) != 0 - wires(2).on = (gate.state & 4) != 0 - val ang = - gate.getLogic[TTimerGateLogic].interpPointer(frame) * MathHelper.pi * 2 - pointer.angle = ang - } -} - -class RenderSequencer extends ICGateRenderer[SequentialGateICPart] { - val torches = Seq( - new RedstoneTorchModel(8, 8), - new RedstoneTorchModel(8, 3), - new RedstoneTorchModel(13, 8), - new RedstoneTorchModel(8, 13), - new RedstoneTorchModel(3, 8) - ) - val pointer = new PointerModel(8, 8) - - torches(0).on = true - - override val coreModels = - Seq(new BaseComponentModel("SEQUENCER"), pointer) ++ torches - - override def prepareStatic(configuration: Int): Unit = { - torches(1).on = true - torches(2).on = false - torches(3).on = false - torches(4).on = false - - pointer.angle = 0 - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - torches(1).on = (gate.state & 0x10) != 0 - torches(2).on = (gate.state & 0x20) != 0 - torches(3).on = (gate.state & 0x40) != 0 - torches(4).on = (gate.state & 0x80) != 0 - - val max = gate.getLogic[Sequencer].pointer_max * 4 - pointer.angle = (gate - .getLogic[Sequencer] - .getWorldTime % max + frame) / max * 2 * MathHelper.pi - if (gate.shape == 1) pointer.angle *= -1 - } -} - -class RenderCounter extends ICGateRenderer[SequentialGateICPart] { - val wires = generateWireModels("COUNT", 2) - val torches = Seq( - new RedstoneTorchModel(11, 8), - new RedstoneTorchModel(8, 3), - new RedstoneTorchModel(8, 13) - ) - val pointer = new PointerModel(11, 8, 1.2d) - - torches(0).on = true - - override val coreModels = - Seq(new BaseComponentModel("COUNT")) ++ wires ++ Seq(pointer) ++ torches - - override def prepareStatic(configuration: Int): Unit = { - reflect = false - wires(0).on = false - wires(1).on = false - torches(1).on = false - torches(2).on = true - pointer.angle = 220 * MathHelper.torad - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - reflect = gate.shape == 1 - wires(0).on = (gate.state & 8) != 0 - wires(1).on = (gate.state & 2) != 0 - torches(1).on = (gate.state & 0x10) != 0 - torches(2).on = (gate.state & 0x40) != 0 - - val max = gate.getLogic[Counter].max - val value = gate.getLogic[Counter].value - pointer.angle = - (value / max.toDouble * (340 - 220) + 210) * MathHelper.torad - if (gate.shape == 1) reflect = true - } -} - -class RenderStateCell extends ICGateRenderer[SequentialGateICPart] { - val wires = generateWireModels("STATECELL", 5) - val torches = - Seq(new RedstoneTorchModel(10, 3.5), new RedstoneTorchModel(13, 8)) - val chip = new RedChipModel(6.5, 10) - val pointer = new PointerModel(13, 8) - - override val coreModels = Seq( - new BaseComponentModel("STATECELL") - ) ++ wires ++ Seq(chip, pointer) ++ torches - - override def prepareStatic(configuration: Int): Unit = { - reflect = false - wires(0).on = false - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(4).on = false - torches(0).on = false - torches(1).on = true - chip.on = false - pointer.angle = -MathHelper.pi / 2 - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - reflect = gate.shape == 1 - val logic = gate.getLogic[StateCell] - var state = gate.state - if (reflect) state = flipMaskZ(state >> 4) << 4 | flipMaskZ(state) - - wires(0).on = (state & 0x10) != 0 - wires(1).on = (state & 4) != 0 - wires(2).on = logic.state2 == 0 || (state & 4) != 0 - wires(3).on = (state & 0x88) != 0 - wires(4).on = (state & 2) != 0 - torches(0).on = (state & 0x10) != 0 - torches(1).on = logic.pointer_start >= 0 - chip.on = logic.state2 != 0 - - reflect = gate.shape == 1 - pointer.angle = - gate.getLogic[StateCell].interpPointer(frame) - MathHelper.pi / 2 - } -} - -class RenderSynchronizer extends ICGateRenderer[SequentialGateICPart] { - val wires = generateWireModels("SYNC", 6) - val torch = new RedstoneTorchModel(8, 3) - val chips = Seq(new RedChipModel(4.5, 9), new RedChipModel(11.5, 9)) - - override val coreModels = - Seq(new BaseComponentModel("SYNC")) ++ wires ++ chips ++ Seq(torch) - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = true - wires(1).on = true - wires(2).on = false - wires(3).on = false - wires(4).on = false - wires(5).on = false - chips(0).on = false - chips(1).on = false - torch.on = false - } - - override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { - val logic = gate.getLogic[Synchronizer] - wires(0).on = !logic.left - wires(1).on = !logic.right - wires(2).on = (gate.state & 4) != 0 - wires(3).on = logic.left && logic.right - wires(4).on = (gate.state & 8) != 0 - wires(5).on = (gate.state & 2) != 0 - chips(0).on = logic.left - chips(1).on = logic.right - torch.on = (gate.state & 0x10) != 0 - } -} - -class RenderDecRandomizer extends ICGateRenderer[ComboGateICPart] { - val wires = generateWireModels("DECRAND", 6) - val chips = Seq( - new YellowChipModel(5, 13), - new YellowChipModel(11, 13), - new RedChipModel(5.5, 8) - ) - val torches = Seq( - new RedstoneTorchModel(8, 2.5), - new RedstoneTorchModel(14, 8), - new RedstoneTorchModel(2, 8), - new RedstoneTorchModel(9, 8) - ) - - override val coreModels = - Seq(new BaseComponentModel("DECRAND")) ++ wires ++ chips ++ torches - - override def prepareStatic(configuration: Int): Unit = { - wires(0).on = false - wires(1).on = false - wires(2).on = false - wires(3).on = false - wires(4).on = true - wires(5).on = true - wires(0).disabled = configuration != 0 - wires(3).disabled = configuration != 0 - torches(0).on = true - torches(1).on = false - torches(2).on = false - torches(3).on = false - chips(0).on = false - chips(1).on = true - chips(2).on = true - } - - override def prepareDynamic(gate: ComboGateICPart, frame: Float) { - val state = gate.state - wires(0).on = (state >> 4) == 2 - wires(1).on = (state >> 4) == 8 - wires(2).on = (state & 4) != 0 - wires(3).on = (state & 4) != 0 - wires(4).on = (state >> 4) == 1 || (state >> 4) == 2 - wires(5).on = (state >> 4) == 1 - wires(0).disabled = gate.shape != 0 - wires(3).disabled = gate.shape != 0 - torches(0).on = (state >> 4) == 1 - torches(1).on = (state >> 4) == 2 - torches(2).on = (state >> 4) == 8 - torches(3).on = !wires(4).on - chips(0).on = (state >> 4) == 2 - chips(1).on = (state >> 4) == 1 || (state >> 4) == 2 - chips(2).on = true - } -} - -class RenderNullCell extends ICGateRenderer[ArrayGateICPart] { - val top = new CellTopWireModel - val bottom = new NullCellBottomWireModel - - override val coreModels = - Seq(new BaseComponentModel("NULLCELL"), bottom, new CellStandModel, top) - - override def prepareStatic(configuration: Int): Unit = { - bottom.signal = 0 - top.signal = 0 - } - - override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { - bottom.signal = gate.getLogic[NullCell].signal1 - top.signal = gate.getLogic[NullCell].signal2 - } -} - -class RenderInvertCell extends ICGateRenderer[ArrayGateICPart] { - val wires = generateWireModels("INVCELL", 1) - val torch = new RedstoneTorchModel(8, 8) - val top = new CellTopWireModel - val bottom = new InvertCellBottomWireModel - - override val coreModels = Seq( - new BaseComponentModel("INVCELL") - ) ++ wires ++ Seq(bottom, torch, new CellStandModel, top) - - override def prepareStatic(configuration: Int): Unit = { - bottom.signal = 0 - top.signal = 255.toByte - wires(0).on = false - torch.on = true - } - - override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { - val logic = gate.getLogic[InvertCell] - bottom.signal = logic.signal1 - top.signal = logic.signal2 - wires(0).on = logic.signal1 != 0 - torch.on = logic.signal1 == 0 - } -} - -class RenderBufferCell extends ICGateRenderer[ArrayGateICPart] { - val wires = generateWireModels("BUFFCELL", 2) - val torches = - Seq(new RedstoneTorchModel(11, 13), new RedstoneTorchModel(8, 8)) - val top = new CellTopWireModel - val bottom = new InvertCellBottomWireModel - - override val coreModels = - Seq(new BaseComponentModel("BUFFCELL")) ++ wires ++ Seq( - bottom - ) ++ torches ++ Seq(new CellStandModel, top) - - override def prepareStatic(configuration: Int): Unit = { - bottom.signal = 0 - top.signal = 0 - wires(0).on = false - wires(1).on = true - torches(0).on = true - torches(1).on = false - } - - override def prepareDynamic(gate: ArrayGateICPart, frame: Float) { - val logic = gate.getLogic[BufferCell] - bottom.signal = logic.signal1 - top.signal = logic.signal2 - torches(0).on = logic.signal1 == 0 - torches(1).on = logic.signal1 != 0 - wires(0).on = logic.signal1 != 0 - wires(1).on = logic.signal1 == 0 - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala new file mode 100644 index 000000000..7bc097247 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.gui.GuiDraw +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.color.Colors +import mrtjp.core.gui.{GuiLib, MCButtonNode, TNode} +import mrtjp.core.vec.{Point, Rect, Size} +import mrtjp.projectred.fabrication.circuitparts.TClientNetCircuitPart +import net.minecraft.client.gui.Gui +import org.lwjgl.input.Keyboard +import org.lwjgl.opengl.GL11 + +trait IGuiCircuitPart extends TClientNetCircuitPart { + @SideOnly(Side.CLIENT) + def createGui: CircuitGui +} + + +class CircuitGui(val part: IGuiCircuitPart) extends Gui with TNode { + var size = Size.zeroSize + + override def frame = Rect(position, size) + + var lineColor = Colors.LIME.argb(0xaa) + var linePointerCalc = { () => Point.zeroPoint } + + private def moverFrame = Rect(position + Point(4, 9), Size(4, 6)) + + private var mouseDown = false + private var mouseInit = Point.zeroPoint + + { + val close = new MCButtonNode + close.position = Point(4, 4) + close.size = Size(5, 5) + close.clickDelegate = { () => removeFromParent() } + addChild(close) + } + + override def frameUpdate_Impl(mouse: Point, rframe: Float) { + if (mouseDown) { + position += mouse - mouseInit + mouseInit = mouse + } + + if (part.world == null) removeFromParent() + } + + override def drawBack_Impl(mouse: Point, rframe: Float) { + GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) + GuiDraw.drawRect( + moverFrame.x, + moverFrame.y, + moverFrame.width, + moverFrame.height, + Colors.LIGHT_GREY.argb + ) + } + + override def drawFront_Impl(mouse: Point, rframe: Float) { + val from = linePointerCalc() + val to = from.clamp(frame) + GL11.glColor4d(1, 1, 1, 1) + GuiLib.drawLine(from.x, from.y, to.x, to.y, lineColor) + GuiDraw.drawRect(to.x - 3, to.y - 3, 6, 6, lineColor) + } + + override def mouseClicked_Impl( + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { + if (parent == null) + false // we cant check for consume here, so manually check if closed + else + hitTest(p).find(_.isInstanceOf[CircuitGui]) match { + case Some(gui) if gui == this => + val guis = parent.childrenByZ.collect { case g: CircuitGui => g } + val otherGuis = guis.filter(_ != this) + for (i <- otherGuis.indices) + otherGuis(i).pushZTo(0.1 * i) + pushZTo(0.1 * otherGuis.size) + + if (moverFrame.contains(p)) { + mouseDown = true + mouseInit = p + } + true + case _ => false + } + } + + override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { + mouseDown = false + false + } + + override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = + if (!consumed && keycode == Keyboard.KEY_ESCAPE) { + removeFromParent() + true + } else false +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala new file mode 100644 index 000000000..6909f5d49 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.data.MCDataInput +import codechicken.lib.gui.GuiDraw +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.color.Colors +import mrtjp.core.gui._ +import mrtjp.core.vec.{Point, Size} +import mrtjp.core.world.WorldLib +import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, PrefboardNode} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs +import mrtjp.projectred.fabrication.{FabricationProxy, IntegratedCircuit, TileICWorkbench} +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.Gui +import net.minecraft.entity.player.EntityPlayer +import org.lwjgl.input.Keyboard +import org.lwjgl.opengl.GL11 + +import java.math.MathContext + + +class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { + var pref: PrefboardNode = null + var toolSets = Seq[ICToolsetNode]() + + override def onAddedToParent_Impl() { + val clip = new ClipNode + clip.position = Point(7, 18) + clip.size = Size(252, 197) + addChild(clip) + + val pan = new PanNode + pan.size = Size(252, 197) + pan.clampSlack = 35 + pan.dragTestFunction = { () => Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) } + clip.addChild(pan) + + pref = new PrefboardNode(tile.circuit) + pref.position = Point(pan.size / 2 - pref.size / 2) + pref.zPosition = -0.01 // Must be below pan/clip nodes + pref.opPickDelegate = { op => + if (op == null) pref.currentOp = null + toolSets.foreach(_.pickOp(op)) + } + pan.addChild(pref) + + val toolbar = new TNode {} + + { + import CircuitOpDefs._ + def addToolsetRange(name: String, from: OpDef, to: OpDef) { + addToolset(name, (from.getID to to.getID).map(CircuitOpDefs(_))) + } + + def addToolset(name: String, opset: Seq[OpDef]) { + val toolset = new ICToolsetNode + toolset.position = Point(17, 0) * toolbar.children.size + toolset.title = name + toolset.opSet = opset.map(_.getOp) + toolset.setup() + toolset.opSelectDelegate = { op => + pref.currentOp = op + pref.currentOpConfiguration = 0 + } + toolbar.addChild(toolset) + toolSets :+= toolset + } + + addToolset("", Seq(Erase)) + addToolset("Debug", Seq(Torch, Lever, Button)) + addToolset("", Seq(AlloyWire)) + addToolsetRange("Insulated wires", WhiteInsulatedWire, BlackInsulatedWire) + addToolsetRange("Bundled cables", NeutralBundledCable, BlackBundledCable) + addToolset("IOs", Seq(SimpleIO, BundledIO, AnalogIO)) + addToolset( + "Primatives", + Seq( + ORGate, + NORGate, + NOTGate, + ANDGate, + NANDGate, + XORGate, + XNORGate, + BufferGate, + MultiplexerGate + ) + ) + addToolset( + "Timing and Clocks", + Seq( + PulseFormerGate, + RepeaterGate, + TimerGate, + SequencerGate, + StateCellGate + ) + ) + addToolset( + "Latches", + Seq(SRLatchGate, ToggleLatchGate, TransparentLatchGate) + ) + addToolset("Cells", Seq(NullCellGate, InvertCellGate, BufferCellGate)) + addToolset( + "Misc", + Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) + ) + } + + addChild(toolbar) + toolbar.position = + Point(size.width / 2 - toolbar.calculateAccumulatedFrame.width / 2, 235) + + val dminus = new MCButtonNode + dminus.position = Point(269, 175) + dminus.size = Size(10, 10) + dminus.text = "-" + dminus.clickDelegate = { () => pref.decDetail() } + addChild(dminus) + + val dplus = new MCButtonNode + dplus.position = Point(309, 175) + dplus.size = Size(10, 10) + dplus.text = "+" + dplus.clickDelegate = { () => pref.incDetail() } + addChild(dplus) + + val sminus = new MCButtonNode + sminus.position = Point(269, 207) + sminus.size = Size(10, 10) + sminus.text = "-" + sminus.clickDelegate = { () => pref.decScale() } + addChild(sminus) + + val splus = new MCButtonNode + splus.position = Point(309, 207) + splus.size = Size(10, 10) + splus.text = "+" + splus.clickDelegate = { () => pref.incScale() } + addChild(splus) + + val reqNew = new MCButtonNode + reqNew.position = Point(272, 133) + reqNew.size = Size(44, 12) + reqNew.text = "redraw" + reqNew.clickDelegate = { () => + if (tile.hasBP) { + val nic = new NewICNode + nic.position = Point(size / 2) - Point(nic.size / 2) + nic.completionDelegate = { () => + val ic = new IntegratedCircuit + ic.name = nic.getName + ic.size = nic.selectedBoardSize * 16 + tile.sendNewICToServer(ic) + } + addChild(nic) + nic.pushZTo(5) + } + } + addChild(reqNew) + + val info = new InfoNode + info.position = Point(241, 18) + info.zPosition = 1 + addChild(info) + } + + override def drawBack_Impl(mouse: Point, frame: Float) { + GL11.glColor4f(1, 1, 1, 1) + PRResources.guiPrototyper.bind() + Gui.func_146110_a(0, 0, 0, 0, size.width, size.height, 512, 512) + + GuiDraw.drawString("IC Workbench", 8, 6, Colors.GREY.argb, false) + + GuiDraw.drawStringC("detail", 273, 162, 42, 14, Colors.GREY.argb, false) + GuiDraw.drawStringC( + pref.detailLevel + "", + 279, + 175, + 30, + 10, + Colors.GREY.argb, + false + ) + + GuiDraw.drawStringC("scale", 273, 193, 42, 14, Colors.GREY.argb, false) + GuiDraw.drawStringC( + BigDecimal(pref.scale, new MathContext(2)) + "", + 279, + 207, + 30, + 10, + Colors.GREY.argb, + false + ) + } +} + +object GuiICWorkbench extends TGuiBuilder { + override def getID = FabricationProxy.icWorkbenchGui + + @SideOnly(Side.CLIENT) + override def buildGui(player: EntityPlayer, data: MCDataInput) = { + WorldLib.getTileEntity( + Minecraft.getMinecraft.theWorld, + data.readCoord() + ) match { + case t: TileICWorkbench => + t.circuit.readDesc(data) + new GuiICWorkbench(t) + case _ => null + } + } +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala new file mode 100644 index 000000000..946248f3f --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.SequentialGateICPart +import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic + +class ICCounterGateGui(override val gate: SequentialGateICPart) + extends CircuitGui(gate) + with TGateGui { + var valID = 0 + + { + size = Size(160, 94) + + val ax = 54 + val aw = 50 + val ah = 15 + + val rotate = new MCButtonNode + rotate.position = Point(ax, 5) + rotate.size = Size(aw, ah) + rotate.text = "rotate" + rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } + addChild(rotate) + + val conf = new MCButtonNode + conf.position = Point(ax + aw + 1, 5) + conf.size = Size(aw, ah) + conf.text = "configure" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) + + val sw = new MCButtonNode + sw.position = Point(54, 28) + sw.size = Size(20, 12) + sw.text = "var" + sw.clickDelegate = { () => valID = (valID + 1) % 3 } + addChild(sw) + + def createButton(x: Int, y: Int, w: Int, h: Int, delta: Int) { + val b = new MCButtonNode + b.position = Point(x, y) + b.size = Size(w, h) + b.text = (if (delta < 0) "" else "+") + delta + b.clickDelegate = { () => + gate.sendClientPacket(_.writeByte(4).writeByte(valID).writeShort(delta)) + } + addChild(b) + } + + val bw = 32 + val bh = 12 + val r1x = 69 + val r2x = r1x + 35 + val by = 48 + val bdy = 14 + + createButton(r1x, by + (0 * bdy), bw, bh, -1) + createButton(r1x, by + (1 * bdy), bw, bh, -5) + createButton(r1x, by + (2 * bdy), bw, bh, -10) + + createButton(r2x, by + (0 * bdy), bw, bh, 1) + createButton(r2x, by + (1 * bdy), bw, bh, 5) + createButton(r2x, by + (2 * bdy), bw, bh, 10) + } + + def getLogic = gate.getLogic[ICounterGuiLogic] + + override def drawBack_Impl(mouse: Point, rframe: Float) { + super.drawBack_Impl(mouse, rframe) + val s = "State: " + getLogic.getCounterValue + GuiDraw.drawStringC( + s, + position.x + 102, + position.y + 24, + Colors.GREY.argb, + false + ) + + val m = valID match { + case 0 => "Max: " + getLogic.getCounterMax + case 1 => "Incr: " + getLogic.getCounterIncr + case 2 => "Decr: " + getLogic.getCounterDecr + } + GuiDraw.drawStringC( + m, + position.x + 102, + position.y + 36, + Colors.GREY.argb, + false + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala new file mode 100644 index 000000000..5f1be4d53 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.GateICPart + +class ICGateGui(override val gate: GateICPart) + extends CircuitGui(gate) + with TGateGui { + { + size = Size(120, 55) + + val rotate = new MCButtonNode + rotate.position = Point(58, 12) + rotate.size = Size(50, 15) + rotate.text = "rotate" + rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } + addChild(rotate) + + val conf = new MCButtonNode + conf.position = Point(58, 28) + conf.size = Size(50, 15) + conf.text = "configure" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala new file mode 100644 index 000000000..b4636afdf --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.io.{IOGateICPart, TFreqIOICGateLogic} + + +class ICIOFreqGateGui(override val gate: IOGateICPart) + extends CircuitGui(gate) + with TGateGui { + { + size = Size(138, 55) + + val conf = new MCButtonNode + conf.position = Point(52, 7) + conf.size = Size(46, 15) + conf.text = "io mode" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) + + val minus = new MCButtonNode + minus.position = Point(52, 33) + minus.size = Size(14, 14) + minus.text = "-" + minus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(6)) } + addChild(minus) + + val plus = new MCButtonNode + plus.position = Point(117, 33) + plus.size = Size(14, 14) + plus.text = "+" + plus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(5)) } + addChild(plus) + } + + override def drawBack_Impl(mouse: Point, rframe: Float) { + super.drawBack_Impl(mouse, rframe) + + GuiDraw.drawStringC( + gate.shape match { + case 0 => "input" + case 1 => "output" + case 2 => "inout" + }, + position.x + 117, + position.y + 11, + Colors.GREY.argb, + false + ) + + GuiDraw.drawStringC( + "freq", + position.x + 66, + position.y + 22, + 50, + 14, + Colors.GREY.argb, + false + ) + GuiDraw.drawStringC( + gate.getLogic[TFreqIOICGateLogic].getFreqName, + position.x + 66, + position.y + 33, + 50, + 14, + Colors.GREY.argb, + false + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala new file mode 100644 index 000000000..adcd3aa2d --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart + +class ICIOGateGui(override val gate: IOGateICPart) + extends CircuitGui(gate) + with TGateGui { + { + size = Size(124, 55) + + val conf = new MCButtonNode + conf.position = Point(62, 33) + conf.size = Size(46, 15) + conf.text = "io mode" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) + } + + override def drawBack_Impl(mouse: Point, rframe: Float) { + super.drawBack_Impl(mouse, rframe) + + GuiDraw.drawStringC( + gate.shape match { + case 0 => "input" + case 1 => "output" + case 2 => "inout" + }, + position.x + 85, + position.y + 16, + Colors.GREY.argb, + false + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala new file mode 100644 index 000000000..ad0305ab7 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.SequentialGateICPart +import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic + +class ICTimerGateGui(override val gate: SequentialGateICPart) + extends CircuitGui(gate) + with TGateGui { + { + size = Size(160, 80) + + val ax = 54 + val aw = 50 + val ah = 15 + + val rotate = new MCButtonNode + rotate.position = Point(ax, 5) + rotate.size = Size(aw, ah) + rotate.text = "rotate" + rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } + addChild(rotate) + + val conf = new MCButtonNode + conf.position = Point(ax + aw + 1, 5) + conf.size = Size(aw, ah) + conf.text = "configure" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) + + def createButton(x: Int, y: Int, w: Int, h: Int, text: String, delta: Int) { + val b = new MCButtonNode + b.position = Point(x, y) + b.size = Size(w, h) + b.text = text + b.clickDelegate = { () => + gate.sendClientPacket(_.writeByte(3).writeShort(delta)) + } + addChild(b) + } + + val bw = 32 + val bh = 12 + val r1x = 69 + val r2x = r1x + 35 + val by = 34 + val bdy = 14 + + createButton(r1x, by + (0 * bdy), bw, bh, "-50ms", -1) + createButton(r1x, by + (1 * bdy), bw, bh, "-1s", -20) + createButton(r1x, by + (2 * bdy), bw, bh, "-10s", -200) + + createButton(r2x, by + (0 * bdy), bw, bh, "+50ms", 1) + createButton(r2x, by + (1 * bdy), bw, bh, "+1s", 20) + createButton(r2x, by + (2 * bdy), bw, bh, "+10s", 200) + } + + def getLogic = gate.getLogic[ITimerGuiLogic] + + override def drawBack_Impl(mouse: Point, rframe: Float) { + super.drawBack_Impl(mouse, rframe) + val s = "Interval: " + "%.2f".format(getLogic.getTimerMax * 0.05) + "s" + GuiDraw.drawStringC( + s, + position.x + 102, + position.y + 24, + Colors.GREY.argb, + false + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala new file mode 100644 index 000000000..4ae2ae04a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.render.uv.UVScale +import codechicken.lib.render.{CCModel, CCRenderState} +import codechicken.lib.vec.{Scale, Transformation, TransformationList, Translation} +import mrtjp.projectred.fabrication.ICComponentStore.faceModels +import mrtjp.projectred.fabrication.IntegratedCircuit +import net.minecraft.client.Minecraft +import net.minecraft.util.ResourceLocation + +import scala.collection.JavaConversions._ + + +object PrefboardRenderer { + private var boardModels = Map[(Int, Int), Seq[CCModel]]() + private var cornerModels = Map[(Int, Int), Seq[CCModel]]() + private var edgeModels = Map[(Int, Int), Seq[CCModel]]() + + private def createBoardModel(w: Int, h: Int): Seq[CCModel] = + faceModels.map(_.copy.apply(new UVScale(w, h))) + + private def createCornerModel(w: Int, h: Int): Seq[CCModel] = { + val corners = Seq((0, 0), (0, h - 1), (w - 1, h - 1), (w - 1, 0)).map { + pair => + new TransformationList( + new Scale(1.0 / w, 1, 1.0 / h), + new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) + ) + } + + faceModels.map { m => + var models = Seq[CCModel]() + for (t <- corners) + models :+= m.copy.apply(t) + CCModel.combine(models) + } + } + + private def createEdgeModel(w: Int, h: Int): Seq[CCModel] = { + val edges = + Seq((0, 0, 1, h), (0, 0, w, 1), (w - 1, 0, 1, h), (0, h - 1, w, 1)).map { + pair => + ( + new TransformationList( + new Scale(1.0 / w, 1, 1.0 / h), + new Scale(pair._3, 1, pair._4), + new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) + ), + new UVScale(pair._3, pair._4) + ) + } + + faceModels.map { m => + var models = Seq[CCModel]() + for ((t, uvt) <- edges) + models :+= m.copy.apply(t).apply(uvt) + CCModel.combine(models) + } + } + + private def getBoardModel(w: Int, h: Int) = { + if (!boardModels.contains((w, h))) + boardModels += (w, h) -> createBoardModel(w, h) + boardModels((w, h)) + } + + private def getCornerModel(w: Int, h: Int) = { + if (!cornerModels.contains((w, h))) + cornerModels += (w, h) -> createCornerModel(w, h) + cornerModels((w, h)) + } + + private def getEdgeModel(w: Int, h: Int) = { + if (!edgeModels.contains((w, h))) + edgeModels += (w, h) -> createEdgeModel(w, h) + edgeModels((w, h)) + } + + def render(circuit: IntegratedCircuit, t: Transformation, ortho: Boolean) { + val w = circuit.size.width + val h = circuit.size.height + + def bind(s: String) { + val r = new ResourceLocation( + "projectred", + "textures/blocks/fabrication/" + s + ".png" + ) + Minecraft.getMinecraft.getTextureManager.bindTexture(r) + } + + val state = CCRenderState.instance + state.resetInstance() + state.pullLightmapInstance() + state.setDynamicInstance() + + for ( + (tex, models) <- Seq( + ("prefboard", getBoardModel(w, h)), + ("prefboard_edge", getEdgeModel(w, h)), + ("prefboard_corner", getCornerModel(w, h)) + ) + ) { + bind(tex) + state.startDrawingInstance() + models(if (ortho) 1 else 0).render(t) + state.drawInstance() + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala new file mode 100644 index 000000000..e9ba2ed28 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui + +import codechicken.lib.vec.Translation +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.ICComponentStore +import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer} + +trait TGateGui extends CircuitGui { + var gateRenderSize = Size(40, 40) + var gateRenderX = 10 + + def gate: GateICPart + + abstract override def drawBack_Impl(mouse: Point, rframe: Float) { + super.drawBack_Impl(mouse, rframe) + + ICGateRenderer.renderDynamic( + gate, + ICComponentStore + .orthoGridT(gateRenderSize.width, gateRenderSize.height) `with` + new Translation( + position.x + gateRenderX, + position.y + (size / 2 - gateRenderSize / 2).height, + 0 + ), + true, + rframe + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala new file mode 100644 index 000000000..ebbd70b89 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.gui.{ButtonNode, IconButtonNode, TNode} +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.operations.CircuitOp + +import scala.collection.immutable.ListMap +import scala.collection.JavaConversions._ + + +class ICToolsetNode extends TNode { + var opSet = Seq.empty[CircuitOp] + var title = "" + var buttonSize = Size(16, 16) + var buttonGap = 1 + + var opSelectDelegate = { _: CircuitOp => () } + + private var focused = false + private var buttonOpMap = ListMap.empty[ButtonNode, CircuitOp] + + private var leadingButton: ButtonNode = null + private var groupButton: ButtonNode = null + + def setup() { + for (op <- opSet) { + val b = createButtonFor(op) + b.size = buttonSize + b.hidden = true + addChild(b) + buttonOpMap += b -> op + } + + val delta = opSet.size * (buttonSize.width + buttonGap) + val firstPoint = + Point(-delta / 2 + buttonSize.width / 2, -buttonSize.height - buttonGap) + for ((b, i) <- buttonOpMap.keys.zipWithIndex) + b.position = firstPoint.add(i * (buttonSize.width + buttonGap), 0) + + leadingButton = buttonOpMap.head._1 + + groupButton = new IconButtonNode { + override def drawButton(mouseover: Boolean) = { + val op = buttonOpMap(leadingButton) + op.renderImage( + position.x + 2, + position.y + 2, + size.width - 4, + size.height - 4 + ) + } + } + groupButton.size = buttonSize + groupButton.tooltipBuilder = { + _ += buttonOpMap(leadingButton).getOpName + } + groupButton.clickDelegate = { () => leadingButton.clickDelegate() } + addChild(groupButton) + } + + private def buttonClicked(op: CircuitOp, button: ButtonNode) { + setFocused() + opSelectDelegate(op) + parent.children + .collect { + case t: ICToolsetNode if t != this => t + } + .foreach(_.setUnfocused()) + leadingButton.mouseoverLock = false + leadingButton = button + leadingButton.mouseoverLock = true + } + + def setUnfocused() { + if (focused) hideSubTools() + focused = false + groupButton.mouseoverLock = false + } + + def setFocused() { + if (!focused) unhideSubTools() + focused = true + groupButton.mouseoverLock = true + } + + private def unhideSubTools() { + if (buttonOpMap.size > 1) + for (b <- buttonOpMap.keys) + b.hidden = false + } + + private def hideSubTools() { + if (buttonOpMap.size > 1) + for (b <- buttonOpMap.keys) + b.hidden = true + } + + private def createButtonFor(op: CircuitOp) = { + val b = new IconButtonNode { + override def drawButton(mouseover: Boolean) { + op.renderImage( + position.x + 2, + position.y + 2, + size.width - 4, + size.height - 4 + ) + } + } + b.tooltipBuilder = { + _ += op.getOpName + } + b.clickDelegate = { () => buttonClicked(op, b) } + b + } + + def pickOp(op: CircuitOp) { + setUnfocused() + buttonOpMap.find(_._2 == op) match { + case Some((b, _)) => b.clickDelegate() + case _ => + } + } + + override def drawFront_Impl(mouse: Point, rframe: Float) { + if ( + title.nonEmpty && groupButton.rayTest(parent.convertPointTo(mouse, this)) + ) { + import net.minecraft.util.EnumChatFormatting._ + translateToScreen() + val Point(mx, my) = parent.convertPointToScreen(mouse) + GuiDraw.drawMultilineTip( + mx + 12, + my - 32, + Seq(AQUA.toString + ITALIC.toString + title) + ) + translateFromScreen() + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala new file mode 100644 index 000000000..a7b983fbb --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.gui._ +import mrtjp.core.vec.{Point, Rect, Size} +import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.gui.GuiICWorkbench +import net.minecraft.client.gui.Gui + + +class InfoNode extends TNode { + val size = Size(18, 18) + override def frame = Rect(position, size) + + private def getTile = parent.asInstanceOf[GuiICWorkbench].tile + + override def drawBack_Impl(mouse: Point, rframe: Float) { + PRResources.guiPrototyper.bind() + if (!getTile.hasBP || getTile.getIC.isEmpty) + Gui.func_146110_a( + position.x, + position.y, + 330, + 0, + size.width, + size.height, + 512, + 512 + ) + } + + override def drawFront_Impl(mouse: Point, rframe: Float) { + val text = + if (!getTile.hasBP) + "Lay down a blueprint on the workbench." + else if (getTile.getIC.isEmpty) + "Blueprint is empty. Redraw it." + else "" + if (text.nonEmpty && rayTest(mouse)) { + translateToScreen() + val Point(mx, my) = parent.convertPointToScreen(mouse) + import scala.collection.JavaConversions._ + GuiDraw.drawMultilineTip(mx + 12, my - 12, Seq(text)) + translateFromScreen() + } + } +} + + + + diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala new file mode 100644 index 000000000..a7fa212b4 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.{GuiLib, MCButtonNode, SimpleTextboxNode, TNode} +import mrtjp.core.vec.{Point, Rect, Size} +import mrtjp.projectred.fabrication.gui.GuiICWorkbench +import org.lwjgl.input.Keyboard + +class NewICNode extends TNode { + val size = Size(100, 120) + + override def frame = Rect(position, size) + + var sizerRenderSize = Size(50, 50) + var sizerRenderOffset = Point(0, -16) + var sizerRenderGap = 2 + + var maxBoardSize = Size(4, 4) + var selectedBoardSize = Size(1, 1) + + var completionDelegate = { () => () } + + var outsideColour = Colors.LIGHT_GREY.argb + var insideColour = Colors.CYAN.rgb | 0x88000000 + var hoverColour = Colors.BLUE.argb + + def getName = { + val t = textbox.text + if (t.isEmpty) "untitled" else t + } + + private var textbox: SimpleTextboxNode = null + private var sizerMap: Map[(Int, Int), Rect] = null + + private def sizerPos = + position + Point(size / 2 - sizerRenderSize / 2) + sizerRenderOffset + + private def calcSizerRects = { + val p = sizerPos + val d = sizerRenderSize / maxBoardSize + + val rcol = GuiLib.createGrid( + p.x, + p.y, + maxBoardSize.width, + maxBoardSize.height, + d.width, + d.height + ) + val icol = + GuiLib.createGrid(0, 0, maxBoardSize.width, maxBoardSize.height, 1, 1) + val zcol = rcol.zip(icol) + + var rects = Map[(Int, Int), Rect]() + for (((px, py), (x, y)) <- zcol) { + val rect = + Rect(Point(px, py) + sizerRenderGap / 2, d - sizerRenderGap / 2) + rects += (x, y) -> rect + } + rects + } + + private def getMouseoverPos(mouse: Point) = + sizerMap.find(_._2 contains mouse) match { + case Some(((x, y), r)) => Point(x, y) + case None => null + } + + override def traceHit(absPoint: Point) = true + + override def onAddedToParent_Impl() { + sizerMap = calcSizerRects + + val close = new MCButtonNode + close.size = Size(8, 8) + close.position = Point(4, 4) + close.clickDelegate = { () => removeFromParent() } + addChild(close) + + val fin = new MCButtonNode + fin.size = Size(40, 15) + fin.position = Point( + size.width / 2 - fin.size.width / 2, + size.height - fin.size.height - 4 + ) + fin.clickDelegate = { () => + removeFromParent() + completionDelegate() + } + fin.text = "start" + addChild(fin) + + textbox = new SimpleTextboxNode + textbox.size = Size(80, 14) + textbox.position = Point(size / 2 - textbox.size / 2) + Point(0, 24) + textbox.phantom = "untitled" + addChild(textbox) + } + + override def frameUpdate_Impl(mouse: Point, rframe: Float) { + if (!parent.asInstanceOf[GuiICWorkbench].tile.hasBP) + removeFromParent() + } + + override def drawBack_Impl(mouse: Point, rframe: Float) { + GuiDraw.drawGradientRect( + 0, + 0, + parent.frame.width, + parent.frame.height, + -1072689136, + -804253680 + ) + GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) + + val mousePos = getMouseoverPos(mouse) + for (((x, y), rect) <- sizerMap) { + GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, outsideColour) + + if (x <= selectedBoardSize.width - 1 && y <= selectedBoardSize.height - 1) + GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, insideColour) + + if (mousePos != null && x == mousePos.x && y == mousePos.y) + GuiDraw.drawRect(rect.midX - 2, rect.midY - 2, 4, 4, hoverColour) + } + } + + override def drawFront_Impl(mouse: Point, rframe: Float) { + if (rayTest(mouse)) { + val mousePos = getMouseoverPos(mouse) + if (mousePos != null) { + translateToScreen() + val Point(mx, my) = parent.convertPointToScreen(mouse) + import scala.collection.JavaConversions._ + GuiDraw.drawMultilineTip( + mx + 12, + my - 12, + Seq((mousePos.x + 1) * 16 + " x " + (mousePos.y + 1) * 16) + ) + translateFromScreen() + } + } + } + + override def mouseClicked_Impl( + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { + if (!consumed) { + val mousePos = getMouseoverPos(p) + if (mousePos != null) { + selectedBoardSize = Size(mousePos + 1) + return true + } + } + false + } + + override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { + if (!consumed) keycode match { + case Keyboard.KEY_ESCAPE => + removeFromParent() + true + case Keyboard.KEY_RETURN => + removeFromParent() + completionDelegate() + true + case _ => false + } + else false + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala new file mode 100644 index 000000000..1d5cfc404 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.gui.GuiDraw +import codechicken.lib.render.ColourMultiplier +import codechicken.lib.render.uv.{UVScale, UVTranslation} +import mrtjp.core.color.Colors +import mrtjp.core.gui.{ClipNode, TNode} +import mrtjp.core.vec.{Point, Rect, Size} +import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} +import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs} +import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} +import net.minecraft.util.EnumChatFormatting +import org.lwjgl.input.{Keyboard, Mouse} + +import scala.collection.JavaConversions._ +import scala.collection.convert.WrapAsJava + +class PrefboardNode(circuit: IntegratedCircuit) extends TNode { + var currentOp: CircuitOp = null + var currentOpRotation: Int = 0 + var currentOpConfiguration: Int = 0 + + /** 0 - off 1 - name only 2 - minor details 3 - all details + */ + var detailLevel = 1 + var scale = 1.0 + var sizeMult = 8 + + def size = circuit.size * sizeMult + + override def frame = Rect( + position, + Size((size.width * scale).toInt, (size.height * scale).toInt) + ) + + var opPickDelegate = { _: CircuitOp => () } + + private var leftMouseDown = false + private var rightMouseDown = false + private var mouseStart = Point(0, 0) + + private def isCircuitValid = circuit.nonEmpty + + private def toGridPoint(p: Point) = { + val f = frame + val rpos = p - position + Point( + (rpos.x * circuit.size.width * 1.0 / f.width).toInt + .min(circuit.size.width - 1) + .max(0), + (rpos.y * circuit.size.height * 1.0 / f.height).toInt + .min(circuit.size.height - 1) + .max(0) + ) + } + + private def toCenteredGuiPoint(gridP: Point) = { + val dp = frame.size.vectorize / circuit.size.vectorize + Point(gridP.vectorize * dp + dp / 2) + } + + override def update_Impl() { + if (mcInst.theWorld.getTotalWorldTime % 20 == 0) + circuit.refreshErrors() + } + + override def drawBack_Impl(mouse: Point, rframe: Float) { + if (isCircuitValid) { + val f = frame + RenderCircuit.renderOrtho( + circuit, + f.x, + f.y, + size.width * scale, + size.height * scale, + rframe + ) + + if (currentOp != null) { + if (frame.contains(mouse) && rayTest(mouse) && !leftMouseDown) { + currentOp.renderHover( + circuit, + toGridPoint(mouse), + currentOpRotation, + currentOpConfiguration, + f.x, + f.y, + size.width * scale, + size.height * scale + ) + } else if (leftMouseDown) + currentOp.renderDrag( + circuit, + mouseStart, + toGridPoint(mouse), + f.x, + f.y, + size.width * scale, + size.height * scale + ) + } + + if ( + mcInst.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty + ) { + prepairRender() + PRResources.guiPrototyper.bind() + for ((Point(x, y), (_, c)) <- circuit.errors) { + val t = orthoPartT( + f.x, + f.y, + size.width * scale, + size.height * scale, + circuit.size, + x, + y + ) + faceModels(dynamicIdx(0, true)).render( + t, + new UVScale(64) `with` new UVTranslation( + 330, + 37 + ) `with` new UVScale(1 / 512d), + ColourMultiplier.instance(Colors(c).rgba) + ) + } + finishRender() + } + } + } + + override def drawFront_Impl(mouse: Point, rframe: Float) { + if ( + isCircuitValid && !leftMouseDown && frame.contains(mouse) && rayTest( + mouse + ) + ) { + val point = toGridPoint(mouse) + val part = circuit.getPart(point) + if (part != null) { + val data = part.getRolloverData(detailLevel) + if (data.nonEmpty) { + ClipNode.tempDisableScissoring() + translateToScreen() + val Point(mx, my) = parent.convertPointToScreen(mouse) + GuiDraw.drawMultilineTip( + mx + 12, + my - 12, + WrapAsJava.seqAsJavaList(data) + ) + if (circuit.errors.contains(point)) + GuiDraw.drawMultilineTip( + mx + 12, + my - 32, + Seq(EnumChatFormatting.RED.toString + circuit.errors(point)._1) + ) + translateFromScreen() + ClipNode.tempEnableScissoring() + } + } + } + } + + override def mouseClicked_Impl( + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { + if (isCircuitValid && !consumed && rayTest(p)) button match { + case 0 => + leftMouseDown = true + mouseStart = toGridPoint(p) + return true + case 1 => + rightMouseDown = true + val gridP = toGridPoint(p) + circuit.getPart(gridP) match { + case gp: IGuiCircuitPart => + val currentlyOpen = children.collect { case cg: CircuitGui => cg } + if (!currentlyOpen.exists(_.part == gp)) { + val gui = gp.createGui + gui.position = + convertPointFrom(Point(4, 4) * (currentlyOpen.size + 1), parent) + gui.linePointerCalc = () => toCenteredGuiPoint(gridP) + addChild(gui) + gui.pushZTo(currentlyOpen.size * 0.1) + } + case _ => + } + return true + case _ if button == mcInst.gameSettings.keyBindPickBlock.getKeyCode => + doPickOp() + return true + case _ => + } + false + } + + override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { + if (leftMouseDown) { + leftMouseDown = false + val mouseEnd = toGridPoint(p) + val opUsed = + currentOp != null && circuit.sendOpUse(currentOp, currentOpRotation, currentOpConfiguration, mouseStart, mouseEnd) + if (!opUsed && mouseEnd == mouseStart) { + val part = circuit.getPart(mouseEnd) + if (part != null) part.onClicked() + } + } + if (rightMouseDown) { + rightMouseDown = false + val mouseEnd = toGridPoint(p) + if (mouseEnd == mouseStart) { + val part = circuit.getPart(mouseEnd) + if (part != null) part.onActivated() + } + } + false + } + + override def mouseScrolled_Impl(p: Point, dir: Int, consumed: Boolean) = { + if (!consumed && rayTest(p)) { + if (dir > 0) rescaleAt(p, math.min(scale + 0.1, 3.0)) + else if (dir < 0) rescaleAt(p, math.max(scale - 0.1, 0.5)) + true + } else false + } + + override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { + import Keyboard._ + if (!consumed) keycode match { + case KEY_ESCAPE if leftMouseDown => + leftMouseDown = false + true + case KEY_ESCAPE if currentOp != null => + opPickDelegate(null) + true + case KEY_Q => + doPickOp() + true + case KEY_R if currentOp != null => + currentOpRotation += 1 + if (currentOpRotation == 4) currentOpRotation = 0 + true + case KEY_C if currentOp != null => + currentOpConfiguration += 1 + true + case _ if keycode == mcInst.gameSettings.keyBindInventory.getKeyCode => + opPickDelegate(CircuitOpDefs.Erase.getOp) + true + case _ => false + } + else false + } + + def doPickOp() { + val root = getRoot + val i = Mouse.getX * root.width / root.mc.displayWidth + val j = root.height - Mouse.getY * root.height / root.mc.displayHeight - 1 + val absPos = Point(i, j) + + val pos = parent.convertPointFromScreen(absPos) + if (rayTest(pos)) { + val part = circuit.getPart(toGridPoint(pos)) + opPickDelegate(if (part != null) part.getPickOp else null) + } + } + + def incDetail() { + detailLevel = math.min(detailLevel + 1, 3) + } + + def decDetail() { + detailLevel = math.max(detailLevel - 1, 0) + } + + def incScale() { + rescaleAt(frame.midPoint, math.min(scale + 0.2, 3.0)) + } + + def decScale() { + rescaleAt(frame.midPoint, math.max(scale - 0.2, 0.5)) + } + + def rescaleAt(point: Point, newScale: Double) { + val p = parent.convertPointTo(point, this).vectorize + val newP = (p / scale) * newScale + val dp = newP - p + scale = newScale + position -= Point(dp) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/icguis.scala b/src/main/scala/mrtjp/projectred/fabrication/icguis.scala deleted file mode 100644 index d5f2109f1..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/icguis.scala +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.gui.GuiDraw -import codechicken.lib.vec.Translation -import mrtjp.core.color.Colors -import mrtjp.core.gui.{GuiLib, MCButtonNode, TNode} -import mrtjp.core.vec.{Point, Rect, Size} -import net.minecraft.client.gui.Gui -import org.lwjgl.input.Keyboard -import org.lwjgl.opengl.GL11 - -class CircuitGui(val part: IGuiCircuitPart) extends Gui with TNode { - var size = Size.zeroSize - override def frame = Rect(position, size) - - var lineColor = Colors.LIME.argb(0xaa) - var linePointerCalc = { () => Point.zeroPoint } - - private def moverFrame = Rect(position + Point(4, 9), Size(4, 6)) - private var mouseDown = false - private var mouseInit = Point.zeroPoint - - { - val close = new MCButtonNode - close.position = Point(4, 4) - close.size = Size(5, 5) - close.clickDelegate = { () => removeFromParent() } - addChild(close) - } - - override def frameUpdate_Impl(mouse: Point, rframe: Float) { - if (mouseDown) { - position += mouse - mouseInit - mouseInit = mouse - } - - if (part.world == null) removeFromParent() - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) - GuiDraw.drawRect( - moverFrame.x, - moverFrame.y, - moverFrame.width, - moverFrame.height, - Colors.LIGHT_GREY.argb - ) - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - val from = linePointerCalc() - val to = from.clamp(frame) - GL11.glColor4d(1, 1, 1, 1) - GuiLib.drawLine(from.x, from.y, to.x, to.y, lineColor) - GuiDraw.drawRect(to.x - 3, to.y - 3, 6, 6, lineColor) - } - - override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { - if (parent == null) - false // we cant check for consume here, so manually check if closed - else - hitTest(p).find(_.isInstanceOf[CircuitGui]) match { - case Some(gui) if gui == this => - val guis = parent.childrenByZ.collect { case g: CircuitGui => g } - val otherGuis = guis.filter(_ != this) - for (i <- otherGuis.indices) - otherGuis(i).pushZTo(0.1 * i) - pushZTo(0.1 * otherGuis.size) - - if (moverFrame.contains(p)) { - mouseDown = true - mouseInit = p - } - true - case _ => false - } - } - - override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { - mouseDown = false - false - } - - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = - if (!consumed && keycode == Keyboard.KEY_ESCAPE) { - removeFromParent() - true - } else false -} - -trait TGateGui extends CircuitGui { - var gateRenderSize = Size(40, 40) - var gateRenderX = 10 - - def gate: GateICPart - - abstract override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - RenderICGate.renderDynamic( - gate, - ICComponentStore - .orthoGridT(gateRenderSize.width, gateRenderSize.height) `with` - new Translation( - position.x + gateRenderX, - position.y + (size / 2 - gateRenderSize / 2).height, - 0 - ), - true, - rframe - ) - } -} - -class ICGateGui(override val gate: GateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(120, 55) - - val rotate = new MCButtonNode - rotate.position = Point(58, 12) - rotate.size = Size(50, 15) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(58, 28) - conf.size = Size(50, 15) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - } -} - -class ICTimerGateGui(override val gate: SequentialGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(160, 80) - - val ax = 54 - val aw = 50 - val ah = 15 - - val rotate = new MCButtonNode - rotate.position = Point(ax, 5) - rotate.size = Size(aw, ah) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(ax + aw + 1, 5) - conf.size = Size(aw, ah) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - def createButton(x: Int, y: Int, w: Int, h: Int, text: String, delta: Int) { - val b = new MCButtonNode - b.position = Point(x, y) - b.size = Size(w, h) - b.text = text - b.clickDelegate = { () => - gate.sendClientPacket(_.writeByte(3).writeShort(delta)) - } - addChild(b) - } - - val bw = 32 - val bh = 12 - val r1x = 69 - val r2x = r1x + 35 - val by = 34 - val bdy = 14 - - createButton(r1x, by + (0 * bdy), bw, bh, "-50ms", -1) - createButton(r1x, by + (1 * bdy), bw, bh, "-1s", -20) - createButton(r1x, by + (2 * bdy), bw, bh, "-10s", -200) - - createButton(r2x, by + (0 * bdy), bw, bh, "+50ms", 1) - createButton(r2x, by + (1 * bdy), bw, bh, "+1s", 20) - createButton(r2x, by + (2 * bdy), bw, bh, "+10s", 200) - } - - def getLogic = gate.getLogic[ITimerGuiLogic] - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - val s = "Interval: " + "%.2f".format(getLogic.getTimerMax * 0.05) + "s" - GuiDraw.drawStringC( - s, - position.x + 102, - position.y + 24, - Colors.GREY.argb, - false - ) - } -} - -class ICCounterGateGui(override val gate: SequentialGateICPart) - extends CircuitGui(gate) - with TGateGui { - var valID = 0 - - { - size = Size(160, 94) - - val ax = 54 - val aw = 50 - val ah = 15 - - val rotate = new MCButtonNode - rotate.position = Point(ax, 5) - rotate.size = Size(aw, ah) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(ax + aw + 1, 5) - conf.size = Size(aw, ah) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - val sw = new MCButtonNode - sw.position = Point(54, 28) - sw.size = Size(20, 12) - sw.text = "var" - sw.clickDelegate = { () => valID = (valID + 1) % 3 } - addChild(sw) - - def createButton(x: Int, y: Int, w: Int, h: Int, delta: Int) { - val b = new MCButtonNode - b.position = Point(x, y) - b.size = Size(w, h) - b.text = (if (delta < 0) "" else "+") + delta - b.clickDelegate = { () => - gate.sendClientPacket(_.writeByte(4).writeByte(valID).writeShort(delta)) - } - addChild(b) - } - - val bw = 32 - val bh = 12 - val r1x = 69 - val r2x = r1x + 35 - val by = 48 - val bdy = 14 - - createButton(r1x, by + (0 * bdy), bw, bh, -1) - createButton(r1x, by + (1 * bdy), bw, bh, -5) - createButton(r1x, by + (2 * bdy), bw, bh, -10) - - createButton(r2x, by + (0 * bdy), bw, bh, 1) - createButton(r2x, by + (1 * bdy), bw, bh, 5) - createButton(r2x, by + (2 * bdy), bw, bh, 10) - } - - def getLogic = gate.getLogic[ICounterGuiLogic] - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - val s = "State: " + getLogic.getCounterValue - GuiDraw.drawStringC( - s, - position.x + 102, - position.y + 24, - Colors.GREY.argb, - false - ) - - val m = valID match { - case 0 => "Max: " + getLogic.getCounterMax - case 1 => "Incr: " + getLogic.getCounterIncr - case 2 => "Decr: " + getLogic.getCounterDecr - } - GuiDraw.drawStringC( - m, - position.x + 102, - position.y + 36, - Colors.GREY.argb, - false - ) - } -} - -class ICIOGateGui(override val gate: IOGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(124, 55) - - val conf = new MCButtonNode - conf.position = Point(62, 33) - conf.size = Size(46, 15) - conf.text = "io mode" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - GuiDraw.drawStringC( - gate.shape match { - case 0 => "input" - case 1 => "output" - case 2 => "inout" - }, - position.x + 85, - position.y + 16, - Colors.GREY.argb, - false - ) - } -} - -class ICIOFreqGateGui(override val gate: IOGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(138, 55) - - val conf = new MCButtonNode - conf.position = Point(52, 7) - conf.size = Size(46, 15) - conf.text = "io mode" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - val minus = new MCButtonNode - minus.position = Point(52, 33) - minus.size = Size(14, 14) - minus.text = "-" - minus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(6)) } - addChild(minus) - - val plus = new MCButtonNode - plus.position = Point(117, 33) - plus.size = Size(14, 14) - plus.text = "+" - plus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(5)) } - addChild(plus) - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - GuiDraw.drawStringC( - gate.shape match { - case 0 => "input" - case 1 => "output" - case 2 => "inout" - }, - position.x + 117, - position.y + 11, - Colors.GREY.argb, - false - ) - - GuiDraw.drawStringC( - "freq", - position.x + 66, - position.y + 22, - 50, - 14, - Colors.GREY.argb, - false - ) - GuiDraw.drawStringC( - gate.getLogic[TFreqIOICGateLogic].getFreqName, - position.x + 66, - position.y + 33, - 50, - 14, - Colors.GREY.argb, - false - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/icrenders.scala b/src/main/scala/mrtjp/projectred/fabrication/icrenders.scala deleted file mode 100644 index 18254e2f8..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/icrenders.scala +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.render.uv.{IconTransformation, UVScale} -import codechicken.lib.render.{CCModel, CCRenderState, ColourMultiplier} -import codechicken.lib.vec._ -import mrtjp.core.color.Colors -import net.minecraft.client.Minecraft -import net.minecraft.client.renderer.texture.IIconRegister -import net.minecraft.util.ResourceLocation -import org.lwjgl.opengl.GL11 -import org.lwjgl.opengl.GL11._ - -import scala.collection.JavaConversions._ - -object RenderCircuit { - def registerIcons(reg: IIconRegister) { - ICComponentStore.registerIcons(reg) - } - - def renderOrtho( - circuit: IntegratedCircuit, - x: Double, - y: Double, - xSize: Double, - ySize: Double, - frame: Float - ) { - val t = - ICComponentStore.orthoGridT(xSize, ySize) `with` new Translation(x, y, 0) - renderBoard(circuit, t, true) - renderCircuit(circuit, t, true, frame) - } - - def renderDynamic( - circuit: IntegratedCircuit, - t: Transformation, - frame: Float - ) { - glDisable(GL_DEPTH_TEST) - renderBoard(circuit, t, true) - renderCircuit(circuit, t, true, frame) - glEnable(GL_DEPTH_TEST) - } - - def renderBoard( - circuit: IntegratedCircuit, - t: Transformation, - ortho: Boolean - ) { - PrefboardRenderer.render(circuit, t, ortho) - } - - def renderCircuit( - circuit: IntegratedCircuit, - t: Transformation, - ortho: Boolean, - frame: Float - ) { - for (((x, y), part) <- circuit.parts) { - val tlist = new TransformationList( - new Scale(1.0 / circuit.size.width, 1, 1.0 / circuit.size.height), - new Translation( - x * 1.0 / circuit.size.width, - 0, - y * 1.0 / circuit.size.height - ), - t - ) - part.renderDynamic(tlist, ortho, frame) - } - } -} - -import mrtjp.projectred.fabrication.ICComponentStore._ -object PrefboardRenderer { - private var boardModels = Map[(Int, Int), Seq[CCModel]]() - private var cornerModels = Map[(Int, Int), Seq[CCModel]]() - private var edgeModels = Map[(Int, Int), Seq[CCModel]]() - - private def createBoardModel(w: Int, h: Int): Seq[CCModel] = - faceModels.map(_.copy.apply(new UVScale(w, h))) - - private def createCornerModel(w: Int, h: Int): Seq[CCModel] = { - val corners = Seq((0, 0), (0, h - 1), (w - 1, h - 1), (w - 1, 0)).map { - pair => - new TransformationList( - new Scale(1.0 / w, 1, 1.0 / h), - new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) - ) - } - - faceModels.map { m => - var models = Seq[CCModel]() - for (t <- corners) - models :+= m.copy.apply(t) - CCModel.combine(models) - } - } - - private def createEdgeModel(w: Int, h: Int): Seq[CCModel] = { - val edges = - Seq((0, 0, 1, h), (0, 0, w, 1), (w - 1, 0, 1, h), (0, h - 1, w, 1)).map { - pair => - ( - new TransformationList( - new Scale(1.0 / w, 1, 1.0 / h), - new Scale(pair._3, 1, pair._4), - new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) - ), - new UVScale(pair._3, pair._4) - ) - } - - faceModels.map { m => - var models = Seq[CCModel]() - for ((t, uvt) <- edges) - models :+= m.copy.apply(t).apply(uvt) - CCModel.combine(models) - } - } - - private def getBoardModel(w: Int, h: Int) = { - if (!boardModels.contains((w, h))) - boardModels += (w, h) -> createBoardModel(w, h) - boardModels((w, h)) - } - - private def getCornerModel(w: Int, h: Int) = { - if (!cornerModels.contains((w, h))) - cornerModels += (w, h) -> createCornerModel(w, h) - cornerModels((w, h)) - } - - private def getEdgeModel(w: Int, h: Int) = { - if (!edgeModels.contains((w, h))) - edgeModels += (w, h) -> createEdgeModel(w, h) - edgeModels((w, h)) - } - - def render(circuit: IntegratedCircuit, t: Transformation, ortho: Boolean) { - val w = circuit.size.width - val h = circuit.size.height - - def bind(s: String) { - val r = new ResourceLocation( - "projectred", - "textures/blocks/fabrication/" + s + ".png" - ) - Minecraft.getMinecraft.getTextureManager.bindTexture(r) - } - val state = CCRenderState.instance - state.resetInstance() - state.pullLightmapInstance() - state.setDynamicInstance() - - for ( - (tex, models) <- Seq( - ("prefboard", getBoardModel(w, h)), - ("prefboard_edge", getEdgeModel(w, h)), - ("prefboard_corner", getCornerModel(w, h)) - ) - ) { - bind(tex) - state.startDrawingInstance() - models(if (ortho) 1 else 0).render(t) - state.drawInstance() - } - } -} - -object RenderICAlloyWire { - var connMap: Byte = 0 - var signal: Byte = 0 - - def prepairInv() { - connMap = 0xf - signal = 0xff.toByte - } - - def prepairDynamic(part: AlloyWireICPart) { - connMap = part.connMap - signal = part.signal - } - - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)).render( - t, - new IconTransformation(redwireIcons(connMap & 0xff)), - ColourMultiplier.instance((signal & 0xff) / 2 + 60 << 24 | 0xff) - ) - finishRender() - } -} - -object RenderICInsulatedWire { - var connMap: Byte = 0 - var signal: Byte = 0 - var colour: Byte = 0 - - def prepairInv(c: Int) { - connMap = 0xf - signal = 255.toByte - colour = c.toByte - } - - def prepairDynamic(part: InsulatedWireICPart) { - connMap = part.connMap - signal = part.signal - colour = part.colour - } - - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)).render( - t, - new IconTransformation(redwireIcons(connMap & 0xff)), - ColourMultiplier.instance((signal & 0xff) / 2 + 60 << 24 | 0xff) - ) - faceModels(dynamicIdx(0, ortho)).render( - t, - new IconTransformation(insulatedwireIcons(connMap & 0xff)), - ColourMultiplier.instance(Colors(colour & 0xff).rgba) - ) - finishRender() - } -} - -object RenderICBundledCable { - var connMap: Byte = 0 - var colour: Byte = 0 - - def prepairInv(c: Int) { - connMap = 0xf - colour = c.toByte - } - - def prepairDynamic(part: BundledCableICPart) { - connMap = part.connMap - colour = part.colour - } - - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)) - .render(t, new IconTransformation(bundledwireIcons(connMap & 0xff))) - if (colour != -1) - faceModels(dynamicIdx(0, ortho)).render( - t, - new IconTransformation(bundledColourIcon), - ColourMultiplier.instance(Colors(colour & 0xff).rgba) - ) - finishRender() - } -} - -object RenderICTorch { - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)) - .render(t, new IconTransformation(torchOnIcon)) - finishRender() - } -} - -object RenderICLever { - var on = false - - def prepairInv() { - on = false - } - - def prepairDynamic(part: LeverICPart) { - on = part.on - } - - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)) - .render(t, new IconTransformation(if (on) leverOnIcon else leverOffIcon)) - finishRender() - } -} - -object RenderICButton { - var on = false - - def prepairInv() { - on = false - } - - def prepairDynamic(part: ButtonICPart) { - on = part.on - } - - def render(t: Transformation, ortho: Boolean) { - prepairRender() - faceModels(dynamicIdx(0, ortho)).render( - t, - new IconTransformation(if (on) buttonOnIcon else buttonOffIcon) - ) - finishRender() - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala new file mode 100644 index 000000000..2559942d7 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.gui.GuiDraw +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.IntegratedCircuit + + +trait CircuitOp { + var id = -1 + + def checkOp(circuit: IntegratedCircuit, start: Point, end: Point): Boolean + + def writeOp( + circuit: IntegratedCircuit, + start: Point, + end: Point, + rotation: Int, + configuration: Int, + out: MCDataOutput + ) + + def readOp(circuit: IntegratedCircuit, in: MCDataInput) + + @SideOnly(Side.CLIENT) + def getOpName: String + + @SideOnly(Side.CLIENT) + def renderHover( + circuit: IntegratedCircuit, + point: Point, + rot: Int, + configuration: Int, + x: Double, + y: Double, + xSize: Double, + ySize: Double + ) + + @SideOnly(Side.CLIENT) + def renderDrag( + circuit: IntegratedCircuit, + start: Point, + end: Point, + x: Double, + y: Double, + xSize: Double, + ySize: Double + ) + + @SideOnly(Side.CLIENT) + def renderImage(x: Double, y: Double, width: Double, height: Double) +} + +object CircuitOp { + def getOperation(id: Int) = CircuitOpDefs(id).getOp + + def renderHolo( + x: Double, + y: Double, + xSize: Double, + ySize: Double, + csize: Size, + point: Point, + colour: Int + ) { + val x1 = (x + xSize / csize.width * point.x).toInt + val y1 = (y + ySize / csize.height * point.y).toInt + val x2 = (x + xSize / csize.width * (point.x + 1)).toInt + val y2 = (y + ySize / csize.height * (point.y + 1)).toInt + + GuiDraw.drawRect(x1, y1, x2 - x1, y2 - y1, colour) + } + + def isOnBorder(cSize: Size, point: Point) = + point.x == 0 || point.y == 0 || point.x == cSize.width - 1 || point.y == cSize.height - 1 + + def isOnEdge(cSize: Size, point: Point) = + point == Point(0, 0) || point == Point( + 0, + cSize.height - 1 + ) || point == Point(cSize.width - 1, 0) || point == Point( + cSize.width - 1, + cSize.height - 1 + ) +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/op.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala similarity index 52% rename from src/main/scala/mrtjp/projectred/fabrication/op.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala index 57a2775ca..14930cf49 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/op.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala @@ -3,16 +3,11 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.operations -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.gui.GuiDraw -import codechicken.lib.vec.{Transformation, Translation} -import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.util.Enum -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.CircuitOp._ -import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition + object CircuitOpDefs extends Enum { type EnumVal = OpDef @@ -115,168 +110,5 @@ object CircuitOpDefs extends Enum { } } -object CircuitOp { - def getOperation(id: Int) = CircuitOpDefs(id).getOp - - def renderHolo( - x: Double, - y: Double, - xSize: Double, - ySize: Double, - csize: Size, - point: Point, - colour: Int - ) { - val x1 = (x + xSize / csize.width * point.x).toInt - val y1 = (y + ySize / csize.height * point.y).toInt - val x2 = (x + xSize / csize.width * (point.x + 1)).toInt - val y2 = (y + ySize / csize.height * (point.y + 1)).toInt - - GuiDraw.drawRect(x1, y1, x2 - x1, y2 - y1, colour) - } - - def isOnBorder(cSize: Size, point: Point) = - point.x == 0 || point.y == 0 || point.x == cSize.width - 1 || point.y == cSize.height - 1 - - def isOnEdge(cSize: Size, point: Point) = - point == Point(0, 0) || point == Point( - 0, - cSize.height - 1 - ) || point == Point(cSize.width - 1, 0) || point == Point( - cSize.width - 1, - cSize.height - 1 - ) -} - -trait CircuitOp { - var id = -1 - - def checkOp(circuit: IntegratedCircuit, start: Point, end: Point): Boolean - - def writeOp( - circuit: IntegratedCircuit, - start: Point, - end: Point, - rotation: Int, - configuration: Int, - out: MCDataOutput - ) - def readOp(circuit: IntegratedCircuit, in: MCDataInput) - - @SideOnly(Side.CLIENT) - def getOpName: String - @SideOnly(Side.CLIENT) - def renderHover( - circuit: IntegratedCircuit, - point: Point, - rot: Int, - configuration: Int, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) - @SideOnly(Side.CLIENT) - def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) - @SideOnly(Side.CLIENT) - def renderImage(x: Double, y: Double, width: Double, height: Double) -} - -abstract class SimplePlacementOp extends CircuitOp { - override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = - circuit.getPart(end.x, end.y) == null - override def writeOp( - circuit: IntegratedCircuit, - start: Point, - end: Point, - rotation: Int, - configuration: Int, - out: MCDataOutput - ) { - out.writeByte(end.x).writeByte(end.y) - } - - override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { - val point = Point(in.readUByte(), in.readUByte()) - if (circuit.getPart(point.x, point.y) == null) - circuit.setPart(point.x, point.y, createPart) - } - - @SideOnly(Side.CLIENT) - override def renderImage( - x: Double, - y: Double, - width: Double, - height: Double - ) { - val t = orthoGridT(width, height) `with` new Translation(x, y, 0) - doPartRender(t) - } - - @SideOnly(Side.CLIENT) - override def renderHover( - circuit: IntegratedCircuit, - point: Point, - rot: Int, - configuration: Int, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(point) != null) return - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - if (!isOnBorder(circuit.size, point)) 0x33ffffff else 0x33ff0000 - ) - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) - doPartRender(t) - } - - @SideOnly(Side.CLIENT) - override def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(end) != null) return - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - end, - if (!isOnBorder(circuit.size, end)) 0x44ffffff else 0x44ff0000 - ) - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, end.x, end.y) - doPartRender(t) - } - - def doPartRender(t: Transformation) - - def createPart: CircuitPart -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/oputils.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala similarity index 94% rename from src/main/scala/mrtjp/projectred/fabrication/oputils.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala index 472fb8636..d3190fb22 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/oputils.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala @@ -3,16 +3,16 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.gui.GuiDraw -import codechicken.lib.render.uv.{UVScale, UVTranslation, IconTransformation} +import codechicken.lib.render.uv.{UVScale, UVTranslation} import codechicken.lib.vec.Translation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.Point import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.IntegratedCircuit class CircuitOpErase extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = diff --git a/src/main/scala/mrtjp/projectred/fabrication/opgates.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala similarity index 88% rename from src/main/scala/mrtjp/projectred/fabrication/opgates.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala index a571e6f6e..71b26ed46 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/opgates.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala @@ -3,14 +3,17 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.vec.{Vector3, Rotation, Transformation, Translation} +import codechicken.lib.vec.{Rotation, Transformation, Translation, Vector3} import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.{Point, Vec2} -import mrtjp.projectred.fabrication.CircuitOp._ import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, GateICPart, ICGateDefinition, ICGateRenderer} +import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, isOnEdge, renderHolo} + abstract class OpGateCommons(meta: Int) extends CircuitOp { @@ -113,7 +116,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { @SideOnly(Side.CLIENT) def doRender(t: Transformation, rot: Int, configuration: Int) { - RenderICGate.renderWithConfiguration(configuration, Rotation.quarterRotations(rot).at(Vector3.center) `with` t, meta) + ICGateRenderer.renderWithConfiguration(configuration, Rotation.quarterRotations(rot).at(Vector3.center) `with` t, meta) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala new file mode 100644 index 000000000..dff0b97fc --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.vec.Transformation +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.projectred.fabrication.circuitparts.CircuitPartDefs +import mrtjp.projectred.fabrication.circuitparts.wire.{RenderICButton, RenderICLever, RenderICTorch} + + +class CircuitOpTorch extends SimplePlacementOp { + override def doPartRender(t: Transformation) = RenderICTorch.render(t, true) + + override def createPart = CircuitPartDefs.Torch.createPart + + @SideOnly(Side.CLIENT) + override def getOpName = "Torch" +} + + +class CircuitOpButton extends SimplePlacementOp { + override def doPartRender(t: Transformation) { + RenderICButton.prepairInv() + RenderICButton.render(t, true) + } + + override def createPart = CircuitPartDefs.Button.createPart + + @SideOnly(Side.CLIENT) + override def getOpName = "Button" +} + + +class CircuitOpLever extends SimplePlacementOp { + override def doPartRender(t: Transformation) { + RenderICLever.prepairInv() + RenderICLever.render(t, true) + } + + override def createPart = CircuitPartDefs.Lever.createPart + + @SideOnly(Side.CLIENT) + override def getOpName = "Lever" +} \ No newline at end of file diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala new file mode 100644 index 000000000..7edea3598 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.vec.{Transformation, Translation} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.ICComponentStore.{orthoGridT, orthoPartT} +import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, renderHolo} +import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.projectred.fabrication.circuitparts.CircuitPart + + +abstract class SimplePlacementOp extends CircuitOp { + override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = + circuit.getPart(end.x, end.y) == null + + override def writeOp( + circuit: IntegratedCircuit, + start: Point, + end: Point, + rotation: Int, + configuration: Int, + out: MCDataOutput + ) { + out.writeByte(end.x).writeByte(end.y) + } + + override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { + val point = Point(in.readUByte(), in.readUByte()) + if (circuit.getPart(point.x, point.y) == null) + circuit.setPart(point.x, point.y, createPart) + } + + @SideOnly(Side.CLIENT) + override def renderImage( + x: Double, + y: Double, + width: Double, + height: Double + ) { + val t = orthoGridT(width, height) `with` new Translation(x, y, 0) + doPartRender(t) + } + + @SideOnly(Side.CLIENT) + override def renderHover( + circuit: IntegratedCircuit, + point: Point, + rot: Int, + configuration: Int, + x: Double, + y: Double, + xSize: Double, + ySize: Double + ) { + if (circuit.getPart(point) != null) return + + renderHolo( + x, + y, + xSize, + ySize, + circuit.size, + point, + if (!isOnBorder(circuit.size, point)) 0x33ffffff else 0x33ff0000 + ) + + val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) + doPartRender(t) + + } + + @SideOnly(Side.CLIENT) + override def renderDrag( + circuit: IntegratedCircuit, + start: Point, + end: Point, + x: Double, + y: Double, + xSize: Double, + ySize: Double + ) { + if (circuit.getPart(end) != null) return + + renderHolo( + x, + y, + xSize, + ySize, + circuit.size, + end, + if (!isOnBorder(circuit.size, end)) 0x44ffffff else 0x44ff0000 + ) + + val t = orthoPartT(x, y, xSize, ySize, circuit.size, end.x, end.y) + doPartRender(t) + } + + def doPartRender(t: Transformation) + + def createPart: CircuitPart +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/opwires.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala similarity index 93% rename from src/main/scala/mrtjp/projectred/fabrication/opwires.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala index 8bbd1c91f..cc6c3180f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/opwires.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala @@ -3,15 +3,19 @@ * Created by MrTJP. * All rights reserved. */ -package mrtjp.projectred.fabrication +package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.vec.{Transformation, Translation} import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.color.Colors import mrtjp.core.vec.Point -import mrtjp.projectred.fabrication.CircuitOp._ import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs} +import mrtjp.projectred.fabrication.circuitparts.wire.{BundledCableICPart, InsulatedWireICPart, RenderICAlloyWire, RenderICBundledCable, RenderICInsulatedWire} +import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, renderHolo} + abstract class OpWire extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = diff --git a/src/main/scala/mrtjp/projectred/fabrication/partabstracts.scala b/src/main/scala/mrtjp/projectred/fabrication/partabstracts.scala deleted file mode 100644 index 64ccbbf0e..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/partabstracts.scala +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.vec.{Vector3, Rotation} -import mrtjp.core.vec.Point -import mrtjp.projectred.fabrication.IWireICPart._ - -trait TICOrient extends CircuitPart { - var orientation: Byte = 0 - - def rotation = orientation & 0x3 - - def setRotation(r: Int) { - orientation = (orientation & 0xfc | r).toByte - } - - def rotationT = - Rotation.quarterRotations(rotation).at(new Vector3(0.5, 0, 0.5)) - - // internal r from absRot - def toInternal(absRot: Int) = (absRot + 4 - rotation) % 4 - // absRot from internal r - def toAbsolute(r: Int) = (r + rotation) % 4 - - def toInternalMask(mask: Int) = TICOrient.shiftMask(mask, toInternal(0)) - def toAbsoluteMask(mask: Int) = TICOrient.shiftMask(mask, toAbsolute(0)) -} - -object TICOrient { - def shiftMask(mask: Int, r: Int) = - (mask & ~0xf) | (mask << r | mask >> 4 - r) & 0xf - def flipMaskZ(mask: Int) = mask & 5 | mask << 2 & 8 | mask >> 2 & 2 -} - -trait TICAcquisitions extends CircuitPart { - def getStraight(r: Int) = world.getPart(posOfStraight(r)) - def posOfStraight(r: Int) = Point(x, y).offset(r) - def rotFromStraight(r: Int) = (r + 2) % 4 - - def notifyToDir(r: Int) { world.notifyNeighbor(posOfStraight(r)) } - def notify(mask: Int) { world.notifyNeighbors(x, y, mask) } -} - -trait TICRSAcquisitions extends TICAcquisitions with IPoweredCircuitPart { - def calcSignal(r: Int): Int = - resolveSignal(getStraight(r), rotFromStraight(r)) - - def resolveSignal(part: Any, r: Int): Int -} - -trait TICBundledAcquisitions extends TICAcquisitions { - def calcArray(r: Int): Array[Byte] = - resolveArray(getStraight(r), rotFromStraight(r)) - - def resolveArray(part: Any, r: Int): Array[Byte] -} - -trait TConnectableICPart extends CircuitPart with TICAcquisitions { - var connMap: Byte = 0 - - def maskConnects(r: Int) = (connMap & 1 << r) != 0 - - def discover(r: Int) = getStraight(r) match { - case c: TConnectableICPart => - canConnectPart(c, r) && c.connect(this, rotFromStraight(r)) - case c => discoverOverride(r, c) - } - - def discoverOverride(r: Int, part: CircuitPart) = false - - def connect(part: CircuitPart, r: Int) = { - if (canConnectPart(part, r)) { - val oldConn = connMap - connMap = (connMap | 1 << r).toByte - if (oldConn != connMap) onMaskChanged() - true - } else false - } - - def updateConns() = { - var newConn = 0 - for (r <- 0 until 4) if (discover(r)) newConn |= 1 << r - if (newConn != connMap) { - connMap = newConn.toByte - onMaskChanged() - true - } else false - } - - def canConnectPart(part: CircuitPart, r: Int): Boolean - - def onMaskChanged() {} -} - -trait TPropagatingICPart - extends CircuitPart - with TConnectableICPart - with IWireICPart { - var propagationMask = 0xf - - def propagate(prev: CircuitPart, mode: Int) { - if (mode != FORCED) ICPropagator.addPartChange(this) - for (r <- 0 until 4) - if ((propagationMask & 1 << r) != 0) - if (maskConnects(r)) - propagateExternal(getStraight(r), posOfStraight(r), prev, mode) - - propagateOther(mode) - } - - def propagateOther(mode: Int) {} - - def propagateExternal( - to: CircuitPart, - at: Point, - from: CircuitPart, - mode: Int - ) { - if (to != null) { - if (to == from) return - if (propagateTo(to, mode)) return - } - ICPropagator.addNeighborChange(at) - } - - def propagateTo(part: CircuitPart, mode: Int) = part match { - case w: IWireICPart => - ICPropagator.propagateTo(w, this, mode) - true - case _ => false - } -} - -trait TRSPropagatingICPart extends TPropagatingICPart { - def calculateSignal: Int - - def getSignal: Int - def setSignal(signal: Int) - - override def updateAndPropagate(prev: CircuitPart, mode: Int) { - if (mode == DROPPING && getSignal == 0) return - val newSignal = calculateSignal - if (newSignal < getSignal) { - if (newSignal > 0) ICPropagator.propagateAnalogDrop(this) - setSignal(0) - propagate(prev, DROPPING) - } else if (newSignal > getSignal) { - setSignal(newSignal) - if (mode == DROPPING) propagate(null, RISING) - else propagate(prev, RISING) - } else if (mode == DROPPING) propagateTo(prev, RISING) - else if (mode == FORCE) propagate(prev, FORCED) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/wirepartrs.scala b/src/main/scala/mrtjp/projectred/fabrication/wirepartrs.scala deleted file mode 100644 index d2bb7dbbf..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/wirepartrs.scala +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.vec.Transformation -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.color.Colors -import net.minecraft.nbt.NBTTagCompound - -trait IRedwireICPart extends IWireICPart with IICRedwireEmitter - -trait IICRedwireEmitter { - def getRedwireSignal(r: Int): Int -} - -trait IInsulatedRedwireICPart extends IRedwireICPart { - def getInsulatedColour: Int -} - -abstract class RedwireICPart - extends WireICPart - with TICRSAcquisitions - with TRSPropagatingICPart - with IRedwireICPart { - var signal: Byte = 0 - - override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setByte("signal", signal) - } - - override def load(tag: NBTTagCompound) { - super.load(tag) - signal = tag.getByte("signal") - } - - override def writeDesc(out: MCDataOutput) { - super.writeDesc(out) - out.writeByte(signal) - } - - override def readDesc(in: MCDataInput) { - super.readDesc(in) - signal = in.readByte() - } - - override def read(in: MCDataInput, key: Int) = key match { - case 10 => signal = in.readByte() - case _ => super.read(in, key) - } - - override def onSignalUpdate() { - super.onSignalUpdate() - writeStreamOf(10).writeByte(signal) - } - - override def discoverOverride(r: Int, part: CircuitPart) = part match { - case pow: IPoweredCircuitPart => pow.canConnectRS(rotFromStraight(r)) - case _ => super.discoverOverride(r, part) - } - - override def canConnectRS(r: Int) = ICPropagator.redwiresConnectable - - override def getRedwireSignal(r: Int) = getSignal - - override def getSignal = signal & 0xff - override def setSignal(sig: Int) { signal = sig.toByte } - - override def rsOutputLevel(r: Int) = - if (ICPropagator.redwiresProvidePower && maskConnects(r)) - (signal & 0xff) + 16 - else 0 - - override def canConnectPart(part: CircuitPart, r: Int) = part match { - case re: IICRedwireEmitter => true - case pc: IPoweredCircuitPart => true - case _ => false - } - - override def resolveSignal(part: Any, r: Int) = part match { - case t: IRedwireICPart if t.diminishOnSide(r) => t.getRedwireSignal(r) - 1 - case t: IICRedwireEmitter => t.getRedwireSignal(r) - case t: IPoweredCircuitPart => t.rsOutputLevel(r) - case _ => 0 - } - - override def calculateSignal = { - var s = 0 - ICPropagator.redwiresProvidePower = false - def raise(sig: Int) { if (sig > s) s = sig } - for (r <- 0 until 4) if (maskConnects(r)) raise(calcSignal(r)) - ICPropagator.redwiresProvidePower = true - s - } - - @SideOnly(Side.CLIENT) - override def getRolloverData(detailLevel: Int) = { - val data = Seq.newBuilder[String] - - import net.minecraft.util.EnumChatFormatting._ - if (detailLevel >= 3) - data += GRAY + "signal: 0x" + Integer.toHexString(signal & 0xff) - else if (detailLevel >= 2) - data += GRAY + "state: " + (if (signal != 0) "high" else "low") - - super.getRolloverData(detailLevel) ++ data.result() - } -} - -class AlloyWireICPart extends RedwireICPart { - override def getPartType = CircuitPartDefs.AlloyWire - - @SideOnly(Side.CLIENT) - override def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) { - RenderICAlloyWire.prepairDynamic(this) - RenderICAlloyWire.render(t, ortho) - } - - @SideOnly(Side.CLIENT) - override def getPartName = "Alloy wire" - - @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs.AlloyWire.getOp -} - -class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { - var colour: Byte = 0 - - override def save(tag: NBTTagCompound) { - super.save(tag) - tag.setByte("colour", colour) - } - - override def load(tag: NBTTagCompound) { - super.load(tag) - colour = tag.getByte("colour") - } - - override def writeDesc(out: MCDataOutput) { - super.writeDesc(out) - out.writeByte(colour) - } - - override def readDesc(in: MCDataInput) { - super.readDesc(in) - colour = in.readByte() - } - - override def getPartType = CircuitPartDefs.InsulatedWire - - override def resolveSignal(part: Any, r: Int) = part match { - case b: IBundledCableICPart => (b.getBundledSignal.apply(colour) & 0xff) - 1 - case _ => super.resolveSignal(part, r) - } - - override def canConnectPart(part: CircuitPart, r: Int) = part match { - case b: IBundledCableICPart => true - case iw: InsulatedWireICPart => iw.colour == colour - case _ => super.canConnectPart(part, r) - } - - override def getInsulatedColour = colour - - @SideOnly(Side.CLIENT) - override def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) { - RenderICInsulatedWire.prepairDynamic(this) - RenderICInsulatedWire.render(t, ortho) - } - - @SideOnly(Side.CLIENT) - override def getPartName = Colors(colour & 0xff).name + " Insulated wire" - - @SideOnly(Side.CLIENT) - override def getPickOp = - CircuitOpDefs - .values(CircuitOpDefs.WhiteInsulatedWire.ordinal + colour) - .getOp -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala b/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala index 7ac20f92d..cd879d30b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala @@ -6,9 +6,9 @@ package mrtjp.projectred.fabrication import java.util.{Stack => JStack} - -import cpw.mods.fml.relauncher.{SideOnly, Side} +import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, IWireICPart} import scala.collection.immutable.HashSet @@ -154,60 +154,6 @@ class ICPropagation(part: IWireICPart, from: CircuitPart, mode: Int) { def go() { part.updateAndPropagate(from, mode) } } -object IWireICPart { - - /** Standard operation procedure, no special propogation rules. The propogator - * signal may not have increased. - */ - final val RISING = 0 - /** Used when the propogator signal dropped (to 0). Propagation should - * continue until a rising or constant change is encountered at which point a - * RISING should be propogated back to this wire. - */ - final val DROPPING = 1 - /** Used when a wire's connection state has changed. Even if the signal - * remains the same, new connections still need to be recalculated - */ - final val FORCE = 2 - /** Used when the propogator did not change signal, but a new connection may - * have been established and signal needs recalculating - */ - final val FORCED = 3 -} - -trait IWireICPart { - - /** Recalculates the signal of this wire and calls the appropriate propogation - * methods in WirePropagator. DO NOT CALL THIS YOURSELF. Use - * WirePropagator.propagateTo - * - * @param prev - * The part which called this propogation (should be connected) may be - * null. - * @param mode - * One of RISING, DROPPING, FORCE and FORCED specified above - */ - def updateAndPropagate(prev: CircuitPart, mode: Int) - - /** Called at the end of a propogation run for partChanged events. Marks the - * end of a state change for this part. - */ - def onSignalUpdate() - - /** @param r - * The rotation of this part to test for wire connection. - * @return - * true if the specified side of this block is connected to, for example, a - * 'wire' where signal should decrease by one. - */ - def diminishOnSide(r: Int): Boolean - - /** The world in which this part resides - * - * @return - */ - def world: IntegratedCircuit -} From 92a3a093aadea94089c1ef8e97987ccac1c6430c Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 03/21] Display Preview in IC Workbench --- .../fabrication/IntegratedCircuit.scala | 4 +- .../circuitparts/latches/SRLatch.scala | 2 - .../fabrication/gui/GuiICWorkbench.scala | 24 ++++++++--- .../fabrication/gui/nodes/ICToolsetNode.scala | 2 +- .../fabrication/gui/nodes/OpPreviewNode.scala | 31 ++++++++++++++ .../fabrication/gui/nodes/PrefboardNode.scala | 40 ++++++++++++++----- .../fabrication/operations/CircuitOp.scala | 18 +++++++-- .../operations/CircuitOpErase.scala | 8 ++-- .../fabrication/operations/GateOps.scala | 24 +++++++---- .../operations/SimplePlacementOp.scala | 12 +++--- .../fabrication/operations/WireOps.scala | 8 ++-- 11 files changed, 127 insertions(+), 46 deletions(-) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index 67533e58a..36dfa78a8 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -161,9 +161,9 @@ class IntegratedCircuit { network.getICStreamOf(2).writeByte(x).writeByte(y) } - def sendOpUse(op: CircuitOp, rotation: Int, configuration: Int, start: Point, end: Point) = { + def sendOpUse(op: CircuitOp, start: Point, end: Point) = { if (op.checkOp(this, start, end)) { - op.writeOp(this, start, end, rotation, configuration, network.getICStreamOf(3).writeByte(op.id)) + op.writeOp(this, start, end, network.getICStreamOf(3).writeByte(op.id)) true } else false } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala index 22cd2d2b4..c054efe1d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala @@ -119,8 +119,6 @@ class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { override def switchModels = if (shape == 0) m1 else m2 override def prepareStatic(configuration: Int): Unit = { - reflect = false - shape = 0 wires1(0).on = false wires1(1).on = true torches1(0).on = false diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 6909f5d49..4c3614225 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -13,8 +13,8 @@ import mrtjp.core.gui._ import mrtjp.core.vec.{Point, Size} import mrtjp.core.world.WorldLib import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, PrefboardNode} -import mrtjp.projectred.fabrication.operations.CircuitOpDefs +import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, OpPreviewNode, PrefboardNode} +import mrtjp.projectred.fabrication.operations.{CircuitOpDefs, OpGateCommons} import mrtjp.projectred.fabrication.{FabricationProxy, IntegratedCircuit, TileICWorkbench} import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui @@ -41,11 +41,25 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { pan.dragTestFunction = { () => Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) } clip.addChild(pan) - pref = new PrefboardNode(tile.circuit) + val opPreview = new OpPreviewNode() + opPreview.position = Point(269, 30) + addChild(opPreview) + + pref = new PrefboardNode(tile.circuit, op => {opPreview.updatePreview(op)}) pref.position = Point(pan.size / 2 - pref.size / 2) pref.zPosition = -0.01 // Must be below pan/clip nodes pref.opPickDelegate = { op => - if (op == null) pref.currentOp = null + if (op == null) { + // Reset rotation and configuration of selected Gate + pref.currentOp match { + case op: OpGateCommons => + op.rotation = 0 + op.configuration = 0 + case _ => + } + pref.currentOp = null + pref.updatePreview() + } toolSets.foreach(_.pickOp(op)) } pan.addChild(pref) @@ -66,7 +80,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolset.setup() toolset.opSelectDelegate = { op => pref.currentOp = op - pref.currentOpConfiguration = 0 + pref.updatePreview() } toolbar.addChild(toolset) toolSets :+= toolset diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index ebbd70b89..3e6abefe9 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -48,7 +48,7 @@ class ICToolsetNode extends TNode { groupButton = new IconButtonNode { override def drawButton(mouseover: Boolean) = { val op = buttonOpMap(leadingButton) - op.renderImage( + op.renderImageStatic( position.x + 2, position.y + 2, size.width - 4, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala new file mode 100644 index 000000000..fa8ca08cb --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import mrtjp.core.gui.TNode +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.operations.CircuitOp + + +class OpPreviewNode extends TNode { + + var currentOp: CircuitOp = null + + def updatePreview(op: CircuitOp): Unit = { + currentOp = op + } + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + if (currentOp != null) { + currentOp.renderImage( + position.x, + position.y, + 50, + 50 + ) + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 1d5cfc404..65cd7f2e5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -13,8 +13,9 @@ import mrtjp.core.gui.{ClipNode, TNode} import mrtjp.core.vec.{Point, Rect, Size} import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} -import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs} +import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs, OpGateCommons} import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} import net.minecraft.util.EnumChatFormatting import org.lwjgl.input.{Keyboard, Mouse} @@ -22,10 +23,8 @@ import org.lwjgl.input.{Keyboard, Mouse} import scala.collection.JavaConversions._ import scala.collection.convert.WrapAsJava -class PrefboardNode(circuit: IntegratedCircuit) extends TNode { +class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitOp) => Unit) extends TNode { var currentOp: CircuitOp = null - var currentOpRotation: Int = 0 - var currentOpConfiguration: Int = 0 /** 0 - off 1 - name only 2 - minor details 3 - all details */ @@ -35,6 +34,10 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { def size = circuit.size * sizeMult + def updatePreview(): Unit = { + previewUpdateDelegate(currentOp) + } + override def frame = Rect( position, Size((size.width * scale).toInt, (size.height * scale).toInt) @@ -88,8 +91,6 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { currentOp.renderHover( circuit, toGridPoint(mouse), - currentOpRotation, - currentOpConfiguration, f.x, f.y, size.width * scale, @@ -207,8 +208,7 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { if (leftMouseDown) { leftMouseDown = false val mouseEnd = toGridPoint(p) - val opUsed = - currentOp != null && circuit.sendOpUse(currentOp, currentOpRotation, currentOpConfiguration, mouseStart, mouseEnd) + val opUsed = currentOp != null && circuit.sendOpUse(currentOp, mouseStart, mouseEnd) if (!opUsed && mouseEnd == mouseStart) { val part = circuit.getPart(mouseEnd) if (part != null) part.onClicked() @@ -234,6 +234,7 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { } override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { + updatePreview() import Keyboard._ if (!consumed) keycode match { case KEY_ESCAPE if leftMouseDown => @@ -246,11 +247,10 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { doPickOp() true case KEY_R if currentOp != null => - currentOpRotation += 1 - if (currentOpRotation == 4) currentOpRotation = 0 + doRotate() true case KEY_C if currentOp != null => - currentOpConfiguration += 1 + doConfigure() true case _ if keycode == mcInst.gameSettings.keyBindInventory.getKeyCode => opPickDelegate(CircuitOpDefs.Erase.getOp) @@ -260,6 +260,23 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { else false } + def doRotate(): Unit = { + currentOp match { + case op: OpGateCommons => + op.rotation += 1 + if (op.rotation == 4) op.rotation = 0 + case _ => + } + } + + def doConfigure(): Unit = { + currentOp match { + case op: OpGateCommons => + op.configuration += 1 + case _ => + } + } + def doPickOp() { val root = getRoot val i = Mouse.getX * root.width / root.mc.displayWidth @@ -270,6 +287,7 @@ class PrefboardNode(circuit: IntegratedCircuit) extends TNode { if (rayTest(pos)) { val part = circuit.getPart(toGridPoint(pos)) opPickDelegate(if (part != null) part.getPickOp else null) + updatePreview() } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index 2559942d7..5c000ddbc 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -17,12 +17,14 @@ trait CircuitOp { def checkOp(circuit: IntegratedCircuit, start: Point, end: Point): Boolean + def getRotation(): Int + + def getConfiguration(): Int + def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, - rotation: Int, - configuration: Int, out: MCDataOutput ) @@ -35,8 +37,6 @@ trait CircuitOp { def renderHover( circuit: IntegratedCircuit, point: Point, - rot: Int, - configuration: Int, x: Double, y: Double, xSize: Double, @@ -54,8 +54,18 @@ trait CircuitOp { ySize: Double ) + /** + * Render the part, that will be placed by this operation + */ @SideOnly(Side.CLIENT) def renderImage(x: Double, y: Double, width: Double, height: Double) + + /** + * Same as renderImage, however it ignores configuration and rotation (e.g. toolbar) + */ + @SideOnly(Side.CLIENT) + def renderImageStatic(x: Double, y: Double, width: Double, height: Double): Unit = + renderImage(x, y ,width, height) } object CircuitOp { diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala index d3190fb22..549beeb2d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala @@ -18,12 +18,14 @@ class CircuitOpErase extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = true + override def getRotation(): Int = 0 + + override def getConfiguration(): Int = 0 + override def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, - rotation: Int, - configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) @@ -63,8 +65,6 @@ class CircuitOpErase extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, - rot: Int, - configuration: Int, x: Double, y: Double, xSize: Double, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala index 71b26ed46..4fb2ec7b8 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala @@ -17,18 +17,25 @@ import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, isOnEdge, abstract class OpGateCommons(meta: Int) extends CircuitOp { + var rotation: Int = 0 + var configuration: Int = 0 + + def getID: Int = meta + def canPlace(circuit: IntegratedCircuit, point: Point): Boolean def findRot(circuit: IntegratedCircuit, start: Point, end: Point): Int override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = canPlace(circuit, start) && circuit.getPart(start) == null + override def getRotation(): Int = rotation + + override def getConfiguration(): Int = configuration + override def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, - rotation: Int, - configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) @@ -38,8 +45,8 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { val point = Point(in.readByte(), in.readByte()) - val rotation = in.readUByte() - val configuration = in.readUByte() + rotation = in.readUByte() + configuration = in.readUByte() if (circuit.getPart(point) == null && canPlace(circuit, point)) { val part = CircuitPart @@ -54,8 +61,6 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, - rot: Int, - configuration: Int, x: Double, y: Double, xSize: Double, @@ -64,7 +69,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { if (circuit.getPart(point) != null) return val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) - doRender(t, rot, configuration) + doRender(t, rotation, configuration) renderHolo( x, @@ -110,6 +115,11 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { width: Double, height: Double ) { + val t = orthoGridT(width, height) `with` new Translation(x, y, 0) + doRender(t, rotation, configuration) + } + + override def renderImageStatic(x: Double, y: Double, width: Double, height: Double): Unit = { val t = orthoGridT(width, height) `with` new Translation(x, y, 0) doRender(t, 0, 0) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala index 7edea3598..3015ca9bd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala @@ -6,7 +6,7 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.vec.{Transformation, Translation} +import codechicken.lib.vec.{Rotation, Transformation, Translation} import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.Point import mrtjp.projectred.fabrication.ICComponentStore.{orthoGridT, orthoPartT} @@ -19,12 +19,14 @@ abstract class SimplePlacementOp extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = circuit.getPart(end.x, end.y) == null + override def getRotation(): Int = 0 + + override def getConfiguration(): Int = 0 + override def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, - rotation: Int, - configuration: Int, out: MCDataOutput ) { out.writeByte(end.x).writeByte(end.y) @@ -42,7 +44,7 @@ abstract class SimplePlacementOp extends CircuitOp { y: Double, width: Double, height: Double - ) { + ): Unit = { val t = orthoGridT(width, height) `with` new Translation(x, y, 0) doPartRender(t) } @@ -51,8 +53,6 @@ abstract class SimplePlacementOp extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, - rot: Int, - configuration: Int, x: Double, y: Double, xSize: Double, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala index cc6c3180f..17e1803fe 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala @@ -21,12 +21,14 @@ abstract class OpWire extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = circuit.getPart(start.x, start.y) == null + override def getRotation(): Int = 0 + + override def getConfiguration(): Int = 0 + override def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, - rotation: Int, - configuration: Int, out: MCDataOutput ) { out.writeByte(start.x).writeByte(start.y) @@ -51,8 +53,6 @@ abstract class OpWire extends CircuitOp { override def renderHover( circuit: IntegratedCircuit, point: Point, - rot: Int, - configuration: Int, x: Double, y: Double, xSize: Double, From 849149223b0e588a4c2011327b30ed9571c4bd35 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 04/21] Fixed implementation for prerotated and preconfigured Gates before placing --- .../circuitparts/io/IOICGateLogic.scala | 8 ++- .../circuitparts/latches/SRLatch.scala | 28 +++++++++-- .../latches/TransparentLatch.scala | 2 +- .../circuitparts/misc/Counter.scala | 8 ++- .../circuitparts/timing/Repeater.scala | 4 +- .../circuitparts/timing/Sequencer.scala | 8 ++- .../circuitparts/timing/StateCell.scala | 8 ++- .../fabrication/gui/nodes/ICToolsetNode.scala | 21 ++++---- .../fabrication/gui/nodes/PrefboardNode.scala | 50 ++++++++++++++++++- .../fabrication/operations/GateOps.scala | 2 +- 10 files changed, 114 insertions(+), 25 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala index 4a6f07df3..470173206 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala @@ -16,6 +16,10 @@ object IOICGateLogic { case ICGateDefinition.IOBundled.ordinal => new BundledIOICGateLogic(gate) case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) } + + def cycleShape(shape: Int): Int = { + (shape + 1) % 3 + } } abstract class IOICGateLogic(val gate: IOGateICPart) @@ -36,8 +40,8 @@ abstract class IOICGateLogic(val gate: IOGateICPart) case 2 => 5 } - override def cycleShape(gate: IOGateICPart) = { - gate.setShape((gate.shape + 1) % 3) + override def cycleShape(gate: IOGateICPart): Boolean = { + gate.setShape(IOICGateLogic.cycleShape(gate.shape)) true } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala index c054efe1d..4eb17a07d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala @@ -10,6 +10,11 @@ import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} +object SRLatch { + def cycleShape(shape: Int): Int = { + (shape + 1) % 4 + } +} class SRLatch(gate: SequentialGateICPart) extends SequentialICGateLogic(gate) @@ -18,7 +23,7 @@ class SRLatch(gate: SequentialGateICPart) override def inputMask(shape: Int) = 0xa override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape((gate.shape + 1) % 4) + gate.setShape(SRLatch.cycleShape(gate.shape)) setState2(flipMaskZ(state2)) gate.setState(flipMaskZ(gate.state)) gate.onOutputChange(0xf) @@ -119,10 +124,23 @@ class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { override def switchModels = if (shape == 0) m1 else m2 override def prepareStatic(configuration: Int): Unit = { - wires1(0).on = false - wires1(1).on = true - torches1(0).on = false - torches1(1).on = true + reflect = (configuration & 1) != 0 + shape = configuration >> 1 + var state = Seq(96, 48, 64, 16)(configuration) + if (reflect) state = flipMaskZ(state >> 4) << 4 | flipMaskZ(state) + if (shape == 0) { + wires1(0).on = (state & 0x88) != 0 + wires1(1).on = (state & 0x22) != 0 + torches1(0).on = (state & 0x10) != 0 + torches1(1).on = (state & 0x40) != 0 + } else { + wires2(1).on = (state & 2) != 0 + wires2(3).on = (state & 8) != 0 + torches2(0).on = (state & 0x10) != 0 + torches2(1).on = (state & 0x40) != 0 + wires2(0).on = torches2(1).on + wires2(2).on = torches2(0).on + } } override def prepareDynamic(gate: SequentialGateICPart, frame: Float) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala index e93a07ac5..b47107648 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala @@ -37,7 +37,7 @@ class RenderTransparentLatch extends ICGateRenderer[ComboICGatePart] { Seq(new BaseComponentModel("TRANSLATCH")) ++ wires ++ torches override def prepareStatic(configuration: Int): Unit = { - reflect = false + reflect = configuration == 1 wires(0).on = true wires(1).on = false wires(2).on = true diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala index a69f313f2..70439d053 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala @@ -30,6 +30,12 @@ trait ICounterGuiLogic { def setCounterValue(gate: GateICPart, i: Int) } +object Counter { + def cycleShape(shape: Int): Int = { + if (shape == 1) 0 else 1 + } +} + class Counter(gate: SequentialGateICPart) extends SequentialICGateLogic(gate) @@ -136,7 +142,7 @@ class Counter(gate: SequentialGateICPart) } override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape(if (gate.shape == 1) 0 else 1) + gate.setShape(Counter.cycleShape(gate.shape)) true } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala index 0a927e12f..3efdda4e7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala @@ -66,8 +66,8 @@ class RenderRepeater extends ICGateRenderer[ComboICGatePart] { wires(0).on = true wires(1).on = false endTorch.on = false - shape = configuration % 8 - varTorches(0).on = true + shape = configuration + varTorches(configuration).on = true } override def prepareDynamic(gate: ComboICGatePart, frame: Float) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala index 92358d2ed..fd28ebe02 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala @@ -16,6 +16,12 @@ import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneT import net.minecraft.nbt.NBTTagCompound +object Sequencer { + def cycleShape(shape: Int): Int = { + shape ^ 1 + } +} + class Sequencer(gate: SequentialGateICPart) extends SequentialICGateLogic(gate) with ITimerGuiLogic { @@ -74,7 +80,7 @@ class Sequencer(gate: SequentialGateICPart) } override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape(gate.shape ^ 1) + gate.setShape(Sequencer.cycleShape(gate.shape)) true } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala index aee92653f..bb3a462ab 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala @@ -11,6 +11,12 @@ import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedChipModel, RedstoneTorchModel} +object StateCell { + def cycleShape(shape: Int): Int = { + (shape + 1) % 2 + } +} + class StateCell(gate: SequentialGateICPart) extends SequentialICGateLogic(gate) @@ -29,7 +35,7 @@ class StateCell(gate: SequentialGateICPart) } override def cycleShape(gate: SequentialGateICPart) = { - gate.setShape((gate.shape + 1) % 2) + gate.setShape(StateCell.cycleShape(gate.shape)) true } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index 3e6abefe9..856773dc6 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -25,8 +25,9 @@ class ICToolsetNode extends TNode { private var focused = false private var buttonOpMap = ListMap.empty[ButtonNode, CircuitOp] - private var leadingButton: ButtonNode = null + private var selectedButton: ButtonNode = null private var groupButton: ButtonNode = null + private var groupButtonOperation: CircuitOp = null def setup() { for (op <- opSet) { @@ -43,12 +44,12 @@ class ICToolsetNode extends TNode { for ((b, i) <- buttonOpMap.keys.zipWithIndex) b.position = firstPoint.add(i * (buttonSize.width + buttonGap), 0) - leadingButton = buttonOpMap.head._1 + selectedButton = buttonOpMap.head._1 + groupButtonOperation = buttonOpMap.head._2 groupButton = new IconButtonNode { override def drawButton(mouseover: Boolean) = { - val op = buttonOpMap(leadingButton) - op.renderImageStatic( + groupButtonOperation.renderImageStatic( position.x + 2, position.y + 2, size.width - 4, @@ -58,9 +59,9 @@ class ICToolsetNode extends TNode { } groupButton.size = buttonSize groupButton.tooltipBuilder = { - _ += buttonOpMap(leadingButton).getOpName + _ += buttonOpMap(selectedButton).getOpName } - groupButton.clickDelegate = { () => leadingButton.clickDelegate() } + groupButton.clickDelegate = { () => selectedButton.clickDelegate() } addChild(groupButton) } @@ -72,9 +73,9 @@ class ICToolsetNode extends TNode { case t: ICToolsetNode if t != this => t } .foreach(_.setUnfocused()) - leadingButton.mouseoverLock = false - leadingButton = button - leadingButton.mouseoverLock = true + selectedButton.mouseoverLock = false + button.mouseoverLock = true + selectedButton = button } def setUnfocused() { @@ -104,7 +105,7 @@ class ICToolsetNode extends TNode { private def createButtonFor(op: CircuitOp) = { val b = new IconButtonNode { override def drawButton(mouseover: Boolean) { - op.renderImage( + op.renderImageStatic( position.x + 2, position.y + 2, size.width - 4, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 65cd7f2e5..c07bbfad5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -14,6 +14,11 @@ import mrtjp.core.vec.{Point, Rect, Size} import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition +import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, TransparentLatch} +import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, DecRandomizer, Randomizer} +import mrtjp.projectred.fabrication.circuitparts.primitives._ +import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} +import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs, OpGateCommons} import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} @@ -272,7 +277,50 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO def doConfigure(): Unit = { currentOp match { case op: OpGateCommons => - op.configuration += 1 + op.getID match { + case ICGateDefinition.OR.ordinal => + op.configuration = OR.cycleShape(op.configuration) + case ICGateDefinition.NOR.ordinal => + op.configuration = NOR.cycleShape(op.configuration) + case ICGateDefinition.NOT.ordinal => + op.configuration = NOT.cycleShape(op.configuration) + case ICGateDefinition.AND.ordinal => + op.configuration = AND.cycleShape(op.configuration) + case ICGateDefinition.NAND.ordinal => + op.configuration = NAND.cycleShape(op.configuration) + case ICGateDefinition.XOR.ordinal => + op.configuration = XOR.cycleShape(op.configuration) + case ICGateDefinition.XNOR.ordinal => + op.configuration = XNOR.cycleShape(op.configuration) + case ICGateDefinition.Buffer.ordinal => + op.configuration = Buffer.cycleShape(op.configuration) + case ICGateDefinition.Multiplexer.ordinal => + op.configuration = Multiplexer.cycleShape(op.configuration) + case ICGateDefinition.Pulse.ordinal => + op.configuration = Pulse.cycleShape(op.configuration) + case ICGateDefinition.Repeater.ordinal => + op.configuration = Repeater.cycleShape(op.configuration) + case ICGateDefinition.Randomizer.ordinal => + op.configuration = Randomizer.cycleShape(op.configuration) + case ICGateDefinition.TransparentLatch.ordinal => + op.configuration = TransparentLatch.cycleShape(op.configuration) + case ICGateDefinition.DecRandomizer.ordinal => + op.configuration = DecRandomizer.cycleShape(op.configuration) + case ICGateDefinition.IOAnalog.ordinal + | ICGateDefinition.IOSimple.ordinal + | ICGateDefinition.IOBundled.ordinal => + op.configuration = IOICGateLogic.cycleShape(op.configuration) + case ICGateDefinition.Sequencer.ordinal => + op.configuration = Sequencer.cycleShape(op.configuration) + case ICGateDefinition.StateCell.ordinal => + op.configuration = StateCell.cycleShape(op.configuration) + case ICGateDefinition.SRLatch.ordinal => + op.configuration = SRLatch.cycleShape(op.configuration) + case ICGateDefinition.Counter.ordinal => + op.configuration = Counter.cycleShape(op.configuration) + case _ => + op.configuration = 0 + } case _ => } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala index 4fb2ec7b8..da6b6226d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala @@ -95,7 +95,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { if (circuit.getPart(start) != null) return val t = orthoPartT(x, y, xSize, ySize, circuit.size, start.x, start.y) - doRender(t, findRot(circuit, start, end), 0) + doRender(t, rotation, configuration) renderHolo( x, From 4918938062edea0d513f44316887cdc30cab4f1a Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 05/21] Added configuration indication to IO gates, IO gates can be placed freely, only rotation matters --- .../textures/blocks/fabrication/in.png | Bin 0 -> 246 bytes .../textures/blocks/fabrication/inout.png | Bin 0 -> 253 bytes .../textures/blocks/fabrication/out.png | Bin 0 -> 250 bytes .../circuitparts/io/RenderIO.scala | 7 ++- .../projectred/fabrication/components.scala | 26 ++++++++++ .../fabrication/gui/GuiICWorkbench.scala | 4 +- .../fabrication/gui/nodes/PrefboardNode.scala | 6 +-- .../operations/CircuitOpDefs.scala | 6 +-- .../{GateOps.scala => OpGate.scala} | 45 ++---------------- 9 files changed, 44 insertions(+), 50 deletions(-) create mode 100644 src/main/resources/assets/projectred/textures/blocks/fabrication/in.png create mode 100644 src/main/resources/assets/projectred/textures/blocks/fabrication/inout.png create mode 100644 src/main/resources/assets/projectred/textures/blocks/fabrication/out.png rename src/main/scala/mrtjp/projectred/fabrication/operations/{GateOps.scala => OpGate.scala} (69%) diff --git a/src/main/resources/assets/projectred/textures/blocks/fabrication/in.png b/src/main/resources/assets/projectred/textures/blocks/fabrication/in.png new file mode 100644 index 0000000000000000000000000000000000000000..c36b845d73cc7987616b2fc52ded3775d9e0f20f GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%C&rs6b?Si}mUKs7M+SzC z{oH>NSwSk3J%W507^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f-TA0 z-G$*l2rk&Wd@@jkv%n*=n1O*?7=#%aX3dcR3bL1Y`ns~eWMdLkQa|4H{47w&%G1R$ zB;xSfa|byY3^-U0uD-wQY&esn;)?lmwI75rF)TRsWa-Qr{Y77Gx+N^@U3=!;7u0@k e$i%=NSwSk3J%W507^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f-TA0 z-G$*l2rk&Wd@@jkv%n*=n1O*?7=#%aX3dcR3bL1Y`ns~eWMdN4&~w?j{V`C;(bL5- zB;xSf3kNwF6nKta$a!~n>1!sh>WxiLM9NSwSk3J%W507^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f-TA0 z-G$*l2rk&Wd@@jkv%n*=n1O*?7=#%aX3dcR3bL1Y`ns~eWMdMP7Ad>Ood^`N^K@|x zi8%cB(nd}O10H6_+<6zDp7K>#!V$spPpm?85(7iU1{L?m(_|zs7OK0w`FK%q`HvGF h(RWVzGcbJE%9MT5$ new IconTransformation(arrowIn) + case 1 => new IconTransformation(arrowOut) + case 2 => new IconTransformation(arrowInOut) + } + ) + } +} + class LeverModel(x: Double, z: Double) extends OnOffModel(new Vector3(x, 0, z)) { override def getIcons = Seq(tLeverOffIcon, tLeverOnIcon) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 4c3614225..9a69c9c13 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -14,7 +14,7 @@ import mrtjp.core.vec.{Point, Size} import mrtjp.core.world.WorldLib import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, OpPreviewNode, PrefboardNode} -import mrtjp.projectred.fabrication.operations.{CircuitOpDefs, OpGateCommons} +import mrtjp.projectred.fabrication.operations.{CircuitOpDefs, OpGate} import mrtjp.projectred.fabrication.{FabricationProxy, IntegratedCircuit, TileICWorkbench} import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui @@ -52,7 +52,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { if (op == null) { // Reset rotation and configuration of selected Gate pref.currentOp match { - case op: OpGateCommons => + case op: OpGate => op.rotation = 0 op.configuration = 0 case _ => diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index c07bbfad5..c63927ccf 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -20,7 +20,7 @@ import mrtjp.projectred.fabrication.circuitparts.primitives._ import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} -import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs, OpGateCommons} +import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs, OpGate} import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} import net.minecraft.util.EnumChatFormatting import org.lwjgl.input.{Keyboard, Mouse} @@ -267,7 +267,7 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO def doRotate(): Unit = { currentOp match { - case op: OpGateCommons => + case op: OpGate => op.rotation += 1 if (op.rotation == 4) op.rotation = 0 case _ => @@ -276,7 +276,7 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO def doConfigure(): Unit = { currentOp match { - case op: OpGateCommons => + case op: OpGate => op.getID match { case ICGateDefinition.OR.ordinal => op.configuration = OR.cycleShape(op.configuration) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala index 14930cf49..e79101441 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala @@ -61,9 +61,9 @@ object CircuitOpDefs extends Enum { val BlackBundledCable = OpDef(new OpBundledCable(15)) // ios - val SimpleIO = OpDef(new OpIOGate(ICGateDefinition.IOSimple.ordinal)) - val AnalogIO = OpDef(new OpIOGate(ICGateDefinition.IOAnalog.ordinal)) - val BundledIO = OpDef(new OpIOGate(ICGateDefinition.IOBundled.ordinal)) + val SimpleIO = OpDef(new OpGate(ICGateDefinition.IOSimple.ordinal)) + val AnalogIO = OpDef(new OpGate(ICGateDefinition.IOAnalog.ordinal)) + val BundledIO = OpDef(new OpGate(ICGateDefinition.IOBundled.ordinal)) // gates val ORGate = OpDef(new OpGate(ICGateDefinition.OR.ordinal)) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala similarity index 69% rename from src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index da6b6226d..548ba7ccd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/GateOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -15,18 +15,15 @@ import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, GateICPart, ICGat import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, isOnEdge, renderHolo} -abstract class OpGateCommons(meta: Int) extends CircuitOp { +class OpGate(meta: Int) extends CircuitOp { var rotation: Int = 0 var configuration: Int = 0 def getID: Int = meta - def canPlace(circuit: IntegratedCircuit, point: Point): Boolean - def findRot(circuit: IntegratedCircuit, start: Point, end: Point): Int - override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = - canPlace(circuit, start) && circuit.getPart(start) == null + circuit.getPart(start) == null override def getRotation(): Int = rotation @@ -48,7 +45,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { rotation = in.readUByte() configuration = in.readUByte() - if (circuit.getPart(point) == null && canPlace(circuit, point)) { + if (circuit.getPart(point) == null) { val part = CircuitPart .createPart(ICGateDefinition(meta).gateType) .asInstanceOf[GateICPart] @@ -78,7 +75,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { ySize, circuit.size, point, - if (canPlace(circuit, point)) 0x33ffffff else 0x33ff0000 + 0x33ffffff ) } @@ -104,7 +101,7 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { ySize, circuit.size, start, - if (canPlace(circuit, start)) 0x44ffffff else 0x44ff0000 + 0x44ffffff ) } @@ -132,35 +129,3 @@ abstract class OpGateCommons(meta: Int) extends CircuitOp { @SideOnly(Side.CLIENT) override def getOpName = ICGateDefinition(meta).unlocal } - -class OpGate(meta: Int) extends OpGateCommons(meta) { - override def findRot(circuit: IntegratedCircuit, start: Point, end: Point) = { - (end - start).vectorize.axialProject.normalize match { - case Vec2(0, -1) => 0 - case Vec2(1, 0) => 1 - case Vec2(0, 1) => 2 - case Vec2(-1, 0) => 3 - case _ => 0 - } - } - - override def canPlace(circuit: IntegratedCircuit, point: Point) = - !isOnBorder(circuit.size, point) -} - -class OpIOGate(meta: Int) extends OpGateCommons(meta) { - override def canPlace(circuit: IntegratedCircuit, point: Point) = - isOnBorder(circuit.size, point) && !isOnEdge(circuit.size, point) - - override def findRot(circuit: IntegratedCircuit, start: Point, end: Point) = { - val wm = circuit.size.width - 1 - val hm = circuit.size.height - 1 - start match { - case Point(_, 0) => 0 - case Point(`wm`, _) => 1 - case Point(_, `hm`) => 2 - case Point(0, _) => 3 - case _ => 0 - } - } -} From db1c0421af2caae501932e16e5b240625a130a15 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 06/21] Quite janky panning with keyboard --- .../fabrication/gui/GuiICWorkbench.scala | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 9a69c9c13..c4c3a3b04 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -10,7 +10,7 @@ import codechicken.lib.gui.GuiDraw import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.color.Colors import mrtjp.core.gui._ -import mrtjp.core.vec.{Point, Size} +import mrtjp.core.vec.{Point, Size, Vec2} import mrtjp.core.world.WorldLib import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, OpPreviewNode, PrefboardNode} @@ -27,6 +27,7 @@ import java.math.MathContext class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var pref: PrefboardNode = null + var pan: PanNode = null var toolSets = Seq[ICToolsetNode]() override def onAddedToParent_Impl() { @@ -35,7 +36,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { clip.size = Size(252, 197) addChild(clip) - val pan = new PanNode + pan = new PanNode pan.size = Size(252, 197) pan.clampSlack = 35 pan.dragTestFunction = { () => Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) } @@ -185,6 +186,26 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { addChild(info) } + override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean): Boolean = { + import Keyboard._ + if (!consumed) keycode match { + case KEY_W => + pan.panChildren(Vec2(0, 10)) + true + case KEY_A => + pan.panChildren(Vec2(10, 0)) + true + case KEY_S => + pan.panChildren(Vec2(0, -10)) + true + case KEY_D => + pan.panChildren(Vec2(-10, 0)) + true + case _ => + false + } else false + } + override def drawBack_Impl(mouse: Point, frame: Float) { GL11.glColor4f(1, 1, 1, 1) PRResources.guiPrototyper.bind() From 791854996dd98dcfbdd4364545c5b917d6b14808 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:18:15 +0200 Subject: [PATCH 07/21] Circuits have infinite size, GUI Changes --- .../projectred/fabrication/ICWorkbench.scala | 13 +- .../fabrication/IntegratedCircuit.scala | 59 +++--- .../mrtjp/projectred/fabrication/Items.scala | 25 +-- .../fabrication/RenderCircuit.scala | 78 ++++--- .../projectred/fabrication/WorldCircuit.scala | 4 +- .../circuitparts/CircuitPart.scala | 8 +- .../projectred/fabrication/components.scala | 10 +- .../fabrication/gui/GuiICWorkbench.scala | 70 +++---- .../fabrication/gui/PrefboardRenderer.scala | 114 +++-------- .../fabrication/gui/nodes/InfoNode.scala | 8 +- .../fabrication/gui/nodes/NewICNode.scala | 179 ---------------- .../fabrication/gui/nodes/PrefboardNode.scala | 192 +++++++++--------- .../fabrication/operations/CircuitOp.scala | 81 +++++--- .../operations/CircuitOpErase.scala | 54 ++--- .../fabrication/operations/OpGate.scala | 52 +---- .../operations/SimplePlacementOp.scala | 56 +---- .../fabrication/operations/WireOps.scala | 133 ++++++------ 17 files changed, 388 insertions(+), 748 deletions(-) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala index df7148cb3..877e9a1ca 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala @@ -134,9 +134,7 @@ class TileICWorkbench extends TileICMachine with NetWorldCircuit { case 2 => circuit.readDesc(in) case 3 => readPartStream(in) case 4 => readICStream(in) - case 5 => - if (!hasBP) new IntegratedCircuit().readDesc(in) - else { circuit.readDesc(in); sendICDesc() } + case 5 => circuit.name = in.readString() case _ => super.read(in, key) } @@ -155,9 +153,9 @@ class TileICWorkbench extends TileICMachine with NetWorldCircuit { } } - def sendNewICToServer(ic: IntegratedCircuit) { + def sendICNameToServer(name: String) { val stream = writeStream(5) - ic.writeDesc(stream) + stream.writeString(name) stream.sendToServer() } @@ -205,7 +203,7 @@ class TileICWorkbench extends TileICMachine with NetWorldCircuit { sendHasBPUpdate() } else if (hasBP && player.isSneaking) { val stack = new ItemStack(ProjectRedFabrication.itemICBlueprint) - if (circuit.nonEmpty) { + if (circuit.parts.nonEmpty) { saveIC(circuit, stack) circuit.clear() sendICDesc() @@ -241,7 +239,8 @@ class TileICWorkbench extends TileICMachine with NetWorldCircuit { super.onBlockRemoval() if (hasBP) { val stack = new ItemStack(ProjectRedFabrication.itemICBlueprint) - if (circuit.nonEmpty) saveIC(circuit, stack) + if (circuit.parts.nonEmpty) + saveIC(circuit, stack) WorldLib.dropItem(world, x, y, z, stack) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index 36dfa78a8..e98d7f5f5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -6,10 +6,10 @@ package mrtjp.projectred.fabrication import codechicken.lib.data.{MCDataInput, MCDataOutput} -import mrtjp.core.vec.{Point, Size} +import mrtjp.core.vec.{Point, Rect, Size} import mrtjp.projectred.ProjectRedCore.log import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TErrorCircuitPart, TClientNetCircuitPart} +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TClientNetCircuitPart, TErrorCircuitPart} import mrtjp.projectred.fabrication.operations.CircuitOp import net.minecraft.nbt.{NBTTagCompound, NBTTagList} @@ -19,7 +19,6 @@ class IntegratedCircuit { var network: WorldCircuit = null var name = "untitled" - var size = Size.zeroSize var parts = MMap[(Int, Int), CircuitPart]() var errors = Map.empty[Point, (String, Int)] @@ -60,16 +59,14 @@ class IntegratedCircuit { def save(tag: NBTTagCompound) { tag.setString("name", name) - tag.setByte("sw", size.width.toByte) - tag.setByte("sh", size.height.toByte) tag.setIntArray("iost", iostate) val tagList = new NBTTagList for (part <- parts.values) { val partTag = new NBTTagCompound partTag.setByte("id", part.id.toByte) - partTag.setByte("xpos", part.x.toByte) - partTag.setByte("ypos", part.y.toByte) + partTag.setInteger("xpos", part.x) + partTag.setInteger("ypos", part.y) part.save(partTag) tagList.appendTag(partTag) } @@ -81,7 +78,6 @@ class IntegratedCircuit { def load(tag: NBTTagCompound) { clear() name = tag.getString("name") - size = Size(tag.getByte("sw") & 0xff, tag.getByte("sh") & 0xff) val ta = tag.getIntArray("iost") for (i <- 0 until 4) iostate(i) = ta(i) @@ -90,8 +86,8 @@ class IntegratedCircuit { val partTag = partList.getCompoundTagAt(i) val part = CircuitPart.createPart(partTag.getByte("id") & 0xff) setPart_do( - partTag.getByte("xpos") & 0xff, - partTag.getByte("ypos") & 0xff, + partTag.getInteger("xpos"), + partTag.getInteger("ypos"), part ) part.load(partTag) @@ -102,12 +98,11 @@ class IntegratedCircuit { def writeDesc(out: MCDataOutput) { out.writeString(name) - out.writeByte(size.width).writeByte(size.height) for (i <- 0 until 4) out.writeInt(iostate(i)) for (((x, y), part) <- parts) { out.writeByte(part.id) - out.writeByte(x).writeByte(y) + out.writeInt(x).writeInt(y) part.writeDesc(out) } out.writeByte(255) @@ -118,13 +113,12 @@ class IntegratedCircuit { def readDesc(in: MCDataInput) { clear() name = in.readString() - size = Size(in.readUByte(), in.readUByte()) for (i <- 0 until 4) iostate(i) = in.readInt() var id = in.readUByte() while (id != 255) { val part = CircuitPart.createPart(id) - setPart_do(in.readUByte(), in.readUByte(), part) + setPart_do(in.readInt(), in.readInt(), part) part.readDesc(in) id = in.readUByte() } @@ -135,12 +129,12 @@ class IntegratedCircuit { case 0 => readDesc(in) case 1 => val part = CircuitPart.createPart(in.readUByte()) - setPart_do(in.readUByte(), in.readUByte(), part) + setPart_do(in.readInt(), in.readInt(), part) part.readDesc(in) - case 2 => removePart(in.readUByte(), in.readUByte()) + case 2 => removePart(in.readInt(), in.readInt()) case 3 => CircuitOp.getOperation(in.readUByte()).readOp(this, in) case 4 => - getPart(in.readUByte(), in.readUByte()) match { + getPart(in.readInt(), in.readInt()) match { case g: TClientNetCircuitPart => g.readClientPacket(in) case _ => log.error("Server IC stream received invalid client packet") } @@ -153,12 +147,12 @@ class IntegratedCircuit { def sendPartAdded(part: CircuitPart) { val out = network.getICStreamOf(1) out.writeByte(part.id) - out.writeByte(part.x).writeByte(part.y) + out.writeInt(part.x).writeInt(part.y) part.writeDesc(out) } def sendRemovePart(x: Int, y: Int) { - network.getICStreamOf(2).writeByte(x).writeByte(y) + network.getICStreamOf(2).writeInt(x).writeInt(y) } def sendOpUse(op: CircuitOp, start: Point, end: Point) = { @@ -172,7 +166,7 @@ class IntegratedCircuit { part: TClientNetCircuitPart, writer: MCDataOutput => Unit ) { - val s = network.getICStreamOf(4).writeByte(part.x).writeByte(part.y) + val s = network.getICStreamOf(4).writeInt(part.x).writeInt(part.y) writer(s) } @@ -195,21 +189,9 @@ class IntegratedCircuit { parts = MMap() scheduledTicks = MMap() name = "untitled" - size = Size.zeroSize for (i <- 0 until 4) iostate(i) = 0 } - def isEmpty = size == Size.zeroSize - - def nonEmpty = !isEmpty - - private def assertCoords(x: Int, y: Int) { - if (!(0 until size.width contains x) || !(0 until size.height contains y)) - throw new IndexOutOfBoundsException( - "Circuit does not contain " + Point(x, y) - ) - } - def tick() { val t = network.getWorld.getTotalWorldTime var rem = Seq[(Int, Int)]() @@ -235,6 +217,17 @@ class IntegratedCircuit { errors = elist.result() } + def getPartsBoundingBox(): Rect = { + val keys = parts.keys + val ((x2, y2), (x1, y1)) = if(keys.nonEmpty) { + (keys.reduce((p1, p2) => (math.max(p1._1, p2._1), math.max(p1._2, p2._2))), + keys.reduce((p1, p2) => (math.min(p1._1, p2._1), math.min(p1._2, p2._2)))) + } else { + ((1, 1), (0, 0)) + } + Rect(Point(x1, y1), Size(x2 - x1, y2 - y1)) + } + def setPart(x: Int, y: Int, part: CircuitPart) { setPart_do(x, y, part) part.onAdded() @@ -242,7 +235,6 @@ class IntegratedCircuit { } private def setPart_do(x: Int, y: Int, part: CircuitPart) { - assertCoords(x, y) part.bind(this, x, y) parts += (x, y) -> part } @@ -250,7 +242,6 @@ class IntegratedCircuit { def getPart(x: Int, y: Int): CircuitPart = parts.getOrElse((x, y), null) def removePart(x: Int, y: Int) { - assertCoords(x, y) val part = getPart(x, y) if (part != null) { if (!network.isRemote) sendRemovePart(x, y) diff --git a/src/main/scala/mrtjp/projectred/fabrication/Items.scala b/src/main/scala/mrtjp/projectred/fabrication/Items.scala index d9050d454..c94b31fa9 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/Items.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/Items.scala @@ -5,12 +5,10 @@ */ package mrtjp.projectred.fabrication -import java.util.{List => JList} import codechicken.lib.gui.GuiDraw import cpw.mods.fml.common.registry.GameRegistry import mrtjp.core.color.Colors import mrtjp.core.item.ItemCore -import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart._ @@ -29,6 +27,8 @@ import net.minecraftforge.client.IItemRenderer import net.minecraftforge.client.IItemRenderer.{ItemRenderType, ItemRendererHelper} import org.lwjgl.opengl.GL11._ +import java.util.{List => JList} + class ItemICBlueprint extends ItemMap // extend ItemMap so minecraft will handle the FP render for us @@ -68,9 +68,7 @@ class ItemICBlueprint val slist = list.asInstanceOf[JList[String]] if (ItemICBlueprint.hasICInside(stack)) { - val size = ItemICBlueprint.getICSize(stack) slist.add(GRAY + ItemICBlueprint.getICName(stack)) - slist.add(GRAY + s"${size.width} x ${size.height}") } else slist.add(GRAY + "empty blueprint") } } @@ -92,8 +90,6 @@ object ItemICBlueprint { ic.save(tag2) tag1.setTag("icdata", tag2) tag1.setString("icname", ic.name) - tag1.setByte("icw", ic.size.width.toByte) - tag1.setByte("ich", ic.size.height.toByte) } def loadIC(stack: ItemStack): IntegratedCircuit = { @@ -112,11 +108,6 @@ object ItemICBlueprint { stack.getTagCompound.getString("icname") } - def getICSize(stack: ItemStack) = { - val tag = stack.getTagCompound - Size(tag.getByte("icw"), tag.getByte("ich")) - } - def hasICInside(stack: ItemStack) = { stack.hasTagCompound && stack.getTagCompound.hasKey("icdata") } @@ -220,7 +211,7 @@ object ItemRenderICBlueprint extends IItemRenderer { if (ItemICBlueprint.hasICInside(stack)) { val ic = ItemICBlueprint.loadIC(stack) - if (ic.nonEmpty) overlayIC(ic) + overlayIC(ic) } glEnable(GL_LIGHTING) @@ -241,10 +232,12 @@ object ItemRenderICBlueprint extends IItemRenderer { } private def overlayIC(ic: IntegratedCircuit) { - val sf = 128 / math.max(ic.size.width, ic.size.height) - val rs = ic.size * sf - val rp = Point(Size(128, 128) / 2 - rs / 2) - RenderCircuit.renderOrtho(ic, rp.x, rp.y, rs.width, rs.height, 0) + val boundingBox = ic.getPartsBoundingBox() + val scale = math.min( + 8.0d / (boundingBox.width.toDouble + 1), + 8.0d / (boundingBox.height.toDouble + 1) + ) + RenderCircuit.renderCircuitOrtho(ic,scale, boundingBox.origin.vectorize) val name = ic.name diff --git a/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala index 26db20b3a..b2bd5bb28 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala @@ -5,67 +5,63 @@ */ package mrtjp.projectred.fabrication +import codechicken.lib.render.ColourMultiplier +import codechicken.lib.render.uv.{UVScale, UVTranslation} import codechicken.lib.vec._ +import mrtjp.core.color.Colors +import mrtjp.core.vec.{Point, Size, Vec2} +import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.ICComponentStore.{dynamicIdx, faceModels, finishRender, orthoPartT, prepairRender} import mrtjp.projectred.fabrication.gui.PrefboardRenderer +import net.minecraft.client.Minecraft import net.minecraft.client.renderer.texture.IIconRegister -import org.lwjgl.opengl.GL11._ object RenderCircuit { + val BASE_SCALE = 16 + def registerIcons(reg: IIconRegister) { ICComponentStore.registerIcons(reg) } def renderOrtho( - circuit: IntegratedCircuit, - x: Double, - y: Double, - xSize: Double, - ySize: Double, - frame: Float - ) { - val t = - ICComponentStore.orthoGridT(xSize, ySize) `with` new Translation(x, y, 0) - renderBoard(circuit, t, true) - renderCircuit(circuit, t, true, frame) - } - - def renderDynamic( - circuit: IntegratedCircuit, - t: Transformation, - frame: Float + circuit: IntegratedCircuit, + boardSize: Size, + gridScale: Double, + gridTranslation: Vec2 ) { - glDisable(GL_DEPTH_TEST) - renderBoard(circuit, t, true) - renderCircuit(circuit, t, true, frame) - glEnable(GL_DEPTH_TEST) + PrefboardRenderer.renderOrtho(boardSize, gridScale, gridTranslation) + renderCircuitOrtho(circuit, gridScale, gridTranslation) } - def renderBoard( - circuit: IntegratedCircuit, - t: Transformation, - ortho: Boolean - ) { - PrefboardRenderer.render(circuit, t, ortho) + def renderErrors(circuit: IntegratedCircuit, gridScale: Double, gridTranslation: Vec2): Unit = { + if(Minecraft.getMinecraft.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty) { + prepairRender() + PRResources.guiPrototyper.bind() + for ((Point(x, y), (_, c)) <- circuit.errors) { + val t = orthoPartT(Vec2(x, y) - gridTranslation, gridScale) + faceModels(dynamicIdx(0, true)).render( + t, + new UVScale(64) `with` new UVTranslation( + 330, + 37 + ) `with` new UVScale(1 / 512d), + ColourMultiplier.instance(Colors(c).rgba) + ) + } + finishRender() + } } - def renderCircuit( - circuit: IntegratedCircuit, - t: Transformation, - ortho: Boolean, - frame: Float - ) { + def renderCircuitOrtho(circuit: IntegratedCircuit, scale: Double, gridTranslation: Vec2): Unit = { + val t = ICComponentStore.orthoGridT(BASE_SCALE, BASE_SCALE) for (((x, y), part) <- circuit.parts) { val tlist = new TransformationList( - new Scale(1.0 / circuit.size.width, 1, 1.0 / circuit.size.height), - new Translation( - x * 1.0 / circuit.size.width, - 0, - y * 1.0 / circuit.size.height - ), + new Scale(scale, 1, scale), + new Translation((x - gridTranslation.dx) * scale, 0, (y - gridTranslation.dy) * scale), t ) - part.renderDynamic(tlist, ortho, frame) + part.renderDynamic(tlist, true, 1f) } } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala index 08feec109..e89ba097d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala @@ -68,7 +68,7 @@ trait NetWorldCircuit extends WorldCircuit { val part = getIC.getPart(x, y) partStream.writeByte(part.id) - partStream.writeByte(x).writeByte(y) + partStream.writeInt(x).writeInt(y) partStream } @@ -83,7 +83,7 @@ trait NetWorldCircuit extends WorldCircuit { try { var id = in.readUByte() while (id != 255) { - val (x, y) = (in.readUByte(), in.readUByte()) + val (x, y) = (in.readInt(), in.readInt()) var part = getIC.getPart(x, y) if (part == null || part.id != id) { log.error("client part stream couldnt find part " + Point(x, y)) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala index 3444f90bb..f538f99cd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala @@ -21,11 +21,11 @@ object CircuitPart { */ abstract class CircuitPart { var world: IntegratedCircuit = null - var loc: (Byte, Byte) = null + var loc: (Int, Int) = null def bind(ic: IntegratedCircuit, x: Int, y: Int) { world = ic - loc = (x.toByte, y.toByte) + loc = (x, y) } def unbind() { @@ -33,9 +33,9 @@ abstract class CircuitPart { loc = null } - def x = loc._1 & 0xff + def x = loc._1 - def y = loc._2 & 0xff + def y = loc._2 def id = getPartType.id diff --git a/src/main/scala/mrtjp/projectred/fabrication/components.scala b/src/main/scala/mrtjp/projectred/fabrication/components.scala index df82c1607..f89d7ac5f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/components.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/components.scala @@ -11,7 +11,7 @@ import codechicken.lib.render.uv.{IconTransformation, UVTransformation} import codechicken.lib.render.{CCModel, CCRenderState, ColourMultiplier, TextureUtils} import codechicken.lib.vec._ import mrtjp.core.color.Colors -import mrtjp.core.vec.Size +import mrtjp.core.vec.{Size, Vec2} import mrtjp.projectred.fabrication.circuitparts.ICGateRenderer import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.util.IIcon @@ -136,6 +136,14 @@ object ICComponentStore { 0 ) + def orthoPartT(position: Vec2, scale: Double): TransformationList = { + new TransformationList( + new Scale(RenderCircuit.BASE_SCALE * scale, 1, -RenderCircuit.BASE_SCALE * scale), + new Translation(position.dx * RenderCircuit.BASE_SCALE * scale, 0, -position.dy * RenderCircuit.BASE_SCALE * scale), + new Rotation(1.571, 1, 0, 0) + ) + } + def orthoPartT( x: Double, y: Double, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index c4c3a3b04..bd8d8cbb4 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -13,9 +13,9 @@ import mrtjp.core.gui._ import mrtjp.core.vec.{Point, Size, Vec2} import mrtjp.core.world.WorldLib import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.gui.nodes.{ICToolsetNode, InfoNode, NewICNode, OpPreviewNode, PrefboardNode} +import mrtjp.projectred.fabrication.gui.nodes._ import mrtjp.projectred.fabrication.operations.{CircuitOpDefs, OpGate} -import mrtjp.projectred.fabrication.{FabricationProxy, IntegratedCircuit, TileICWorkbench} +import mrtjp.projectred.fabrication.{FabricationProxy, TileICWorkbench} import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui import net.minecraft.entity.player.EntityPlayer @@ -27,7 +27,6 @@ import java.math.MathContext class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var pref: PrefboardNode = null - var pan: PanNode = null var toolSets = Seq[ICToolsetNode]() override def onAddedToParent_Impl() { @@ -36,19 +35,12 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { clip.size = Size(252, 197) addChild(clip) - pan = new PanNode - pan.size = Size(252, 197) - pan.clampSlack = 35 - pan.dragTestFunction = { () => Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) } - clip.addChild(pan) - val opPreview = new OpPreviewNode() - opPreview.position = Point(269, 30) + opPreview.position = Point(269, 18) addChild(opPreview) - pref = new PrefboardNode(tile.circuit, op => {opPreview.updatePreview(op)}) - pref.position = Point(pan.size / 2 - pref.size / 2) - pref.zPosition = -0.01 // Must be below pan/clip nodes + pref = new PrefboardNode(tile.circuit, tile.hasBP, op => {opPreview.updatePreview(op)}) + pref.zPosition = -0.01 // Must be below clip nodes pref.opPickDelegate = { op => if (op == null) { // Reset rotation and configuration of selected Gate @@ -63,7 +55,13 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { } toolSets.foreach(_.pickOp(op)) } - pan.addChild(pref) + clip.addChild(pref) + if(tile.circuit.parts.nonEmpty) { + pref.scaleGuiToCircuit() + } else { + pref.offset = Vec2(0, 0) + pref.scale = 1.0d + } val toolbar = new TNode {} @@ -132,6 +130,13 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolbar.position = Point(size.width / 2 - toolbar.calculateAccumulatedFrame.width / 2, 235) + val textbox = new SimpleTextboxNode() + textbox.position = Point(80, 4) + textbox.size = Size(150, 12) + textbox.text = tile.circuit.name + textbox.textChangedDelegate = { () => tile.sendICNameToServer(textbox.text) } + addChild(textbox) + val dminus = new MCButtonNode dminus.position = Point(269, 175) dminus.size = Size(10, 10) @@ -160,25 +165,16 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { splus.clickDelegate = { () => pref.incScale() } addChild(splus) - val reqNew = new MCButtonNode - reqNew.position = Point(272, 133) - reqNew.size = Size(44, 12) - reqNew.text = "redraw" - reqNew.clickDelegate = { () => - if (tile.hasBP) { - val nic = new NewICNode - nic.position = Point(size / 2) - Point(nic.size / 2) - nic.completionDelegate = { () => - val ic = new IntegratedCircuit - ic.name = nic.getName - ic.size = nic.selectedBoardSize * 16 - tile.sendNewICToServer(ic) - } - addChild(nic) - nic.pushZTo(5) + val resetView = new MCButtonNode + resetView.position = Point(265, 133) + resetView.size = Size(60, 12) + resetView.text = "Reset View" + resetView.clickDelegate = { () => + if (tile.hasBP && tile.circuit.parts.nonEmpty) { + pref.scaleGuiToCircuit() } } - addChild(reqNew) + addChild(resetView) val info = new InfoNode info.position = Point(241, 18) @@ -190,16 +186,16 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { import Keyboard._ if (!consumed) keycode match { case KEY_W => - pan.panChildren(Vec2(0, 10)) + pref.offset += Vec2(0, -2 / pref.scale) true case KEY_A => - pan.panChildren(Vec2(10, 0)) + pref.offset += Vec2(-2 / pref.scale, 0) true case KEY_S => - pan.panChildren(Vec2(0, -10)) - true + pref.offset += Vec2(0, 2 / pref.scale) + true case KEY_D => - pan.panChildren(Vec2(-10, 0)) + pref.offset += Vec2(2 / pref.scale, 0) true case _ => false @@ -252,4 +248,4 @@ object GuiICWorkbench extends TGuiBuilder { case _ => null } } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala index 4ae2ae04a..402cbb410 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala @@ -5,110 +5,44 @@ */ package mrtjp.projectred.fabrication.gui +import codechicken.lib.math.MathHelper +import codechicken.lib.render.CCRenderState import codechicken.lib.render.uv.UVScale -import codechicken.lib.render.{CCModel, CCRenderState} -import codechicken.lib.vec.{Scale, Transformation, TransformationList, Translation} +import codechicken.lib.vec.{Rotation, Scale, TransformationList, Translation} +import mrtjp.core.vec.{Size, Vec2} import mrtjp.projectred.fabrication.ICComponentStore.faceModels -import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.projectred.fabrication.RenderCircuit import net.minecraft.client.Minecraft import net.minecraft.util.ResourceLocation -import scala.collection.JavaConversions._ - object PrefboardRenderer { - private var boardModels = Map[(Int, Int), Seq[CCModel]]() - private var cornerModels = Map[(Int, Int), Seq[CCModel]]() - private var edgeModels = Map[(Int, Int), Seq[CCModel]]() - - private def createBoardModel(w: Int, h: Int): Seq[CCModel] = - faceModels.map(_.copy.apply(new UVScale(w, h))) - - private def createCornerModel(w: Int, h: Int): Seq[CCModel] = { - val corners = Seq((0, 0), (0, h - 1), (w - 1, h - 1), (w - 1, 0)).map { - pair => - new TransformationList( - new Scale(1.0 / w, 1, 1.0 / h), - new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) - ) - } - - faceModels.map { m => - var models = Seq[CCModel]() - for (t <- corners) - models :+= m.copy.apply(t) - CCModel.combine(models) - } - } - - private def createEdgeModel(w: Int, h: Int): Seq[CCModel] = { - val edges = - Seq((0, 0, 1, h), (0, 0, w, 1), (w - 1, 0, 1, h), (0, h - 1, w, 1)).map { - pair => - ( - new TransformationList( - new Scale(1.0 / w, 1, 1.0 / h), - new Scale(pair._3, 1, pair._4), - new Translation(pair._1 * 1.0 / w, 0, pair._2 * 1.0 / h) - ), - new UVScale(pair._3, pair._4) - ) - } - - faceModels.map { m => - var models = Seq[CCModel]() - for ((t, uvt) <- edges) - models :+= m.copy.apply(t).apply(uvt) - CCModel.combine(models) - } - } - - private def getBoardModel(w: Int, h: Int) = { - if (!boardModels.contains((w, h))) - boardModels += (w, h) -> createBoardModel(w, h) - boardModels((w, h)) - } - - private def getCornerModel(w: Int, h: Int) = { - if (!cornerModels.contains((w, h))) - cornerModels += (w, h) -> createCornerModel(w, h) - cornerModels((w, h)) - } - - private def getEdgeModel(w: Int, h: Int) = { - if (!edgeModels.contains((w, h))) - edgeModels += (w, h) -> createEdgeModel(w, h) - edgeModels((w, h)) - } - def render(circuit: IntegratedCircuit, t: Transformation, ortho: Boolean) { - val w = circuit.size.width - val h = circuit.size.height + def renderOrtho(size: Size, scale: Double, gridTranslation: Vec2) { + val offset = gridTranslation - Vec2(gridTranslation.dx.toInt, gridTranslation.dy.toInt) - def bind(s: String) { - val r = new ResourceLocation( - "projectred", - "textures/blocks/fabrication/" + s + ".png" - ) - Minecraft.getMinecraft.getTextureManager.bindTexture(r) - } + val uv = new UVScale(size.width / (RenderCircuit.BASE_SCALE * scale) + 2, size.height / (RenderCircuit.BASE_SCALE * scale) + 2) + val boardModel = faceModels.map(_.copy().apply(uv)) val state = CCRenderState.instance state.resetInstance() state.pullLightmapInstance() state.setDynamicInstance() - for ( - (tex, models) <- Seq( - ("prefboard", getBoardModel(w, h)), - ("prefboard_edge", getEdgeModel(w, h)), - ("prefboard_corner", getCornerModel(w, h)) - ) - ) { - bind(tex) - state.startDrawingInstance() - models(if (ortho) 1 else 0).render(t) - state.drawInstance() - } + val t = new TransformationList( + new Scale(size.width + 2 * RenderCircuit.BASE_SCALE * scale, 1, -(size.height + 2 * RenderCircuit.BASE_SCALE * scale)), + new Translation(-(offset.dx + 1) * RenderCircuit.BASE_SCALE * scale, 0, (offset.dy + 1) * RenderCircuit.BASE_SCALE * scale), + new Rotation(0.5 * MathHelper.pi, 1, 0, 0) + ) + + val r = new ResourceLocation( + "projectred", + "textures/blocks/fabrication/prefboard.png" + ) + Minecraft.getMinecraft.getTextureManager.bindTexture(r) + + state.startDrawingInstance() + boardModel(1).render(t) + state.drawInstance() } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala index a7b983fbb..9d595e208 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala @@ -21,7 +21,7 @@ class InfoNode extends TNode { override def drawBack_Impl(mouse: Point, rframe: Float) { PRResources.guiPrototyper.bind() - if (!getTile.hasBP || getTile.getIC.isEmpty) + if (!getTile.hasBP) Gui.func_146110_a( position.x, position.y, @@ -38,8 +38,6 @@ class InfoNode extends TNode { val text = if (!getTile.hasBP) "Lay down a blueprint on the workbench." - else if (getTile.getIC.isEmpty) - "Blueprint is empty. Redraw it." else "" if (text.nonEmpty && rayTest(mouse)) { translateToScreen() @@ -50,7 +48,3 @@ class InfoNode extends TNode { } } } - - - - diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala deleted file mode 100644 index a7fa212b4..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/NewICNode.scala +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui.nodes - -import codechicken.lib.gui.GuiDraw -import mrtjp.core.color.Colors -import mrtjp.core.gui.{GuiLib, MCButtonNode, SimpleTextboxNode, TNode} -import mrtjp.core.vec.{Point, Rect, Size} -import mrtjp.projectred.fabrication.gui.GuiICWorkbench -import org.lwjgl.input.Keyboard - -class NewICNode extends TNode { - val size = Size(100, 120) - - override def frame = Rect(position, size) - - var sizerRenderSize = Size(50, 50) - var sizerRenderOffset = Point(0, -16) - var sizerRenderGap = 2 - - var maxBoardSize = Size(4, 4) - var selectedBoardSize = Size(1, 1) - - var completionDelegate = { () => () } - - var outsideColour = Colors.LIGHT_GREY.argb - var insideColour = Colors.CYAN.rgb | 0x88000000 - var hoverColour = Colors.BLUE.argb - - def getName = { - val t = textbox.text - if (t.isEmpty) "untitled" else t - } - - private var textbox: SimpleTextboxNode = null - private var sizerMap: Map[(Int, Int), Rect] = null - - private def sizerPos = - position + Point(size / 2 - sizerRenderSize / 2) + sizerRenderOffset - - private def calcSizerRects = { - val p = sizerPos - val d = sizerRenderSize / maxBoardSize - - val rcol = GuiLib.createGrid( - p.x, - p.y, - maxBoardSize.width, - maxBoardSize.height, - d.width, - d.height - ) - val icol = - GuiLib.createGrid(0, 0, maxBoardSize.width, maxBoardSize.height, 1, 1) - val zcol = rcol.zip(icol) - - var rects = Map[(Int, Int), Rect]() - for (((px, py), (x, y)) <- zcol) { - val rect = - Rect(Point(px, py) + sizerRenderGap / 2, d - sizerRenderGap / 2) - rects += (x, y) -> rect - } - rects - } - - private def getMouseoverPos(mouse: Point) = - sizerMap.find(_._2 contains mouse) match { - case Some(((x, y), r)) => Point(x, y) - case None => null - } - - override def traceHit(absPoint: Point) = true - - override def onAddedToParent_Impl() { - sizerMap = calcSizerRects - - val close = new MCButtonNode - close.size = Size(8, 8) - close.position = Point(4, 4) - close.clickDelegate = { () => removeFromParent() } - addChild(close) - - val fin = new MCButtonNode - fin.size = Size(40, 15) - fin.position = Point( - size.width / 2 - fin.size.width / 2, - size.height - fin.size.height - 4 - ) - fin.clickDelegate = { () => - removeFromParent() - completionDelegate() - } - fin.text = "start" - addChild(fin) - - textbox = new SimpleTextboxNode - textbox.size = Size(80, 14) - textbox.position = Point(size / 2 - textbox.size / 2) + Point(0, 24) - textbox.phantom = "untitled" - addChild(textbox) - } - - override def frameUpdate_Impl(mouse: Point, rframe: Float) { - if (!parent.asInstanceOf[GuiICWorkbench].tile.hasBP) - removeFromParent() - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - GuiDraw.drawGradientRect( - 0, - 0, - parent.frame.width, - parent.frame.height, - -1072689136, - -804253680 - ) - GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) - - val mousePos = getMouseoverPos(mouse) - for (((x, y), rect) <- sizerMap) { - GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, outsideColour) - - if (x <= selectedBoardSize.width - 1 && y <= selectedBoardSize.height - 1) - GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, insideColour) - - if (mousePos != null && x == mousePos.x && y == mousePos.y) - GuiDraw.drawRect(rect.midX - 2, rect.midY - 2, 4, 4, hoverColour) - } - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - if (rayTest(mouse)) { - val mousePos = getMouseoverPos(mouse) - if (mousePos != null) { - translateToScreen() - val Point(mx, my) = parent.convertPointToScreen(mouse) - import scala.collection.JavaConversions._ - GuiDraw.drawMultilineTip( - mx + 12, - my - 12, - Seq((mousePos.x + 1) * 16 + " x " + (mousePos.y + 1) * 16) - ) - translateFromScreen() - } - } - } - - override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { - if (!consumed) { - val mousePos = getMouseoverPos(p) - if (mousePos != null) { - selectedBoardSize = Size(mousePos + 1) - return true - } - } - false - } - - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { - if (!consumed) keycode match { - case Keyboard.KEY_ESCAPE => - removeFromParent() - true - case Keyboard.KEY_RETURN => - removeFromParent() - completionDelegate() - true - case _ => false - } - else false - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index c63927ccf..f9d76a169 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -6,21 +6,16 @@ package mrtjp.projectred.fabrication.gui.nodes import codechicken.lib.gui.GuiDraw -import codechicken.lib.render.ColourMultiplier -import codechicken.lib.render.uv.{UVScale, UVTranslation} -import mrtjp.core.color.Colors import mrtjp.core.gui.{ClipNode, TNode} -import mrtjp.core.vec.{Point, Rect, Size} -import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.ICComponentStore._ +import mrtjp.core.vec.{Point, Rect, Vec2} import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition +import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, TransparentLatch} import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, DecRandomizer, Randomizer} import mrtjp.projectred.fabrication.circuitparts.primitives._ import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} -import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} -import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs, OpGate} +import mrtjp.projectred.fabrication.operations._ import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} import net.minecraft.util.EnumChatFormatting import org.lwjgl.input.{Keyboard, Mouse} @@ -28,16 +23,15 @@ import org.lwjgl.input.{Keyboard, Mouse} import scala.collection.JavaConversions._ import scala.collection.convert.WrapAsJava -class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitOp) => Unit) extends TNode { +class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUpdateDelegate: (CircuitOp) => Unit) extends TNode { var currentOp: CircuitOp = null /** 0 - off 1 - name only 2 - minor details 3 - all details */ var detailLevel = 1 var scale = 1.0 - var sizeMult = 8 - def size = circuit.size * sizeMult + var offset: Vec2 = Vec2(0, 0) def updatePreview(): Unit = { previewUpdateDelegate(currentOp) @@ -45,7 +39,7 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO override def frame = Rect( position, - Size((size.width * scale).toInt, (size.height * scale).toInt) + parent.frame.size ) var opPickDelegate = { _: CircuitOp => () } @@ -54,23 +48,29 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO private var rightMouseDown = false private var mouseStart = Point(0, 0) - private def isCircuitValid = circuit.nonEmpty - private def toGridPoint(p: Point) = { - val f = frame - val rpos = p - position + /** + * Converts coordinates in the gui to coordinates in the circuit (with rounding) + */ + private def toGridPoint(p: Vec2): Point = { + val circuitCoord = p / (RenderCircuit.BASE_SCALE * scale) + offset + Point( + math.floor(circuitCoord.dx).round.toInt, + math.floor(circuitCoord.dy).round.toInt + ) + } + + private def toGridPoint(p: Point): Point = { + val circuitCoord = p.vectorize / (RenderCircuit.BASE_SCALE * scale) + offset Point( - (rpos.x * circuit.size.width * 1.0 / f.width).toInt - .min(circuit.size.width - 1) - .max(0), - (rpos.y * circuit.size.height * 1.0 / f.height).toInt - .min(circuit.size.height - 1) - .max(0) + math.floor(circuitCoord.dx).round.toInt, + math.floor(circuitCoord.dy).round.toInt ) } + private def toCenteredGuiPoint(gridP: Point) = { - val dp = frame.size.vectorize / circuit.size.vectorize + val dp = frame.size.vectorize / 16 Point(gridP.vectorize * dp + dp / 2) } @@ -80,75 +80,42 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO } override def drawBack_Impl(mouse: Point, rframe: Float) { - if (isCircuitValid) { + if(hasBlueprint) { val f = frame RenderCircuit.renderOrtho( circuit, - f.x, - f.y, - size.width * scale, - size.height * scale, - rframe + parent.frame.size, + scale, + offset ) if (currentOp != null) { - if (frame.contains(mouse) && rayTest(mouse) && !leftMouseDown) { - currentOp.renderHover( - circuit, - toGridPoint(mouse), - f.x, - f.y, - size.width * scale, - size.height * scale - ) - } else if (leftMouseDown) + if (rayTest(mouse) && !leftMouseDown) { + // Render: Erase always, other stuff only if there are no already placed parts under the cursor + currentOp match { + case _: OpGate | _: OpWire | _: SimplePlacementOp => + if (circuit.getPart(toGridPoint(mouse.vectorize)) == null) + currentOp.renderHover(toGridPoint(mouse).vectorize, scale, offset) + case _: CircuitOpErase => + currentOp.renderHover(toGridPoint(mouse).vectorize, scale, offset) + } + } else if (leftMouseDown) { currentOp.renderDrag( - circuit, - mouseStart, - toGridPoint(mouse), - f.x, - f.y, - size.width * scale, - size.height * scale - ) - } - - if ( - mcInst.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty - ) { - prepairRender() - PRResources.guiPrototyper.bind() - for ((Point(x, y), (_, c)) <- circuit.errors) { - val t = orthoPartT( - f.x, - f.y, - size.width * scale, - size.height * scale, - circuit.size, - x, - y - ) - faceModels(dynamicIdx(0, true)).render( - t, - new UVScale(64) `with` new UVTranslation( - 330, - 37 - ) `with` new UVScale(1 / 512d), - ColourMultiplier.instance(Colors(c).rgba) + mouseStart.vectorize, + toGridPoint(mouse).vectorize, + CircuitOp.partsBetweenPoints(mouseStart.vectorize, toGridPoint(mouse).vectorize, circuit), + scale, + offset ) } - finishRender() } + RenderCircuit.renderErrors(circuit, scale, offset) } } override def drawFront_Impl(mouse: Point, rframe: Float) { - if ( - isCircuitValid && !leftMouseDown && frame.contains(mouse) && rayTest( - mouse - ) - ) { - val point = toGridPoint(mouse) + if(!leftMouseDown && rayTest(mouse)) { + val point = toGridPoint(mouse.vectorize) val part = circuit.getPart(point) if (part != null) { val data = part.getRolloverData(detailLevel) @@ -174,19 +141,33 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO } } + private var mousePosition = Point(0, 0) + override def mouseDragged_Impl(p: Point, button: Int, time: Long, consumed: Boolean): Boolean = { + if(!consumed && rayTest(p) && currentOp == null) { + if(time > 10) { + offset = offset - (p - mousePosition).vectorize / (RenderCircuit.BASE_SCALE * scale) + } + mousePosition = p + true + } else { + mousePosition = p + false + } + } + override def mouseClicked_Impl( p: Point, button: Int, consumed: Boolean ): Boolean = { - if (isCircuitValid && !consumed && rayTest(p)) button match { + if (!consumed && rayTest(p)) button match { case 0 => leftMouseDown = true - mouseStart = toGridPoint(p) + mouseStart = toGridPoint(p.vectorize) return true case 1 => rightMouseDown = true - val gridP = toGridPoint(p) + val gridP = toGridPoint(p.vectorize) circuit.getPart(gridP) match { case gp: IGuiCircuitPart => val currentlyOpen = children.collect { case cg: CircuitGui => cg } @@ -212,16 +193,20 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { if (leftMouseDown) { leftMouseDown = false - val mouseEnd = toGridPoint(p) - val opUsed = currentOp != null && circuit.sendOpUse(currentOp, mouseStart, mouseEnd) - if (!opUsed && mouseEnd == mouseStart) { + val mouseEnd = toGridPoint(p.vectorize) + val opUsed = currentOp != null && circuit.sendOpUse( + currentOp, + mouseStart, + mouseEnd + ) + if (!opUsed && mouseStart == mouseEnd) { val part = circuit.getPart(mouseEnd) if (part != null) part.onClicked() } } if (rightMouseDown) { rightMouseDown = false - val mouseEnd = toGridPoint(p) + val mouseEnd = toGridPoint(p.vectorize) if (mouseEnd == mouseStart) { val part = circuit.getPart(mouseEnd) if (part != null) part.onActivated() @@ -232,8 +217,8 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO override def mouseScrolled_Impl(p: Point, dir: Int, consumed: Boolean) = { if (!consumed && rayTest(p)) { - if (dir > 0) rescaleAt(p, math.min(scale + 0.1, 3.0)) - else if (dir < 0) rescaleAt(p, math.max(scale - 0.1, 0.5)) + if (dir > 0) rescaleAt(p, math.min(scale * 1.25, 3.0)) + else if (dir < 0) rescaleAt(p, math.max(scale * 0.8, 0.5)) true } else false } @@ -257,9 +242,6 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO case KEY_C if currentOp != null => doConfigure() true - case _ if keycode == mcInst.gameSettings.keyBindInventory.getKeyCode => - opPickDelegate(CircuitOpDefs.Erase.getOp) - true case _ => false } else false @@ -333,7 +315,7 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO val pos = parent.convertPointFromScreen(absPos) if (rayTest(pos)) { - val part = circuit.getPart(toGridPoint(pos)) + val part = circuit.getPart(toGridPoint(pos.vectorize)) opPickDelegate(if (part != null) part.getPickOp else null) updatePreview() } @@ -348,18 +330,32 @@ class PrefboardNode(circuit: IntegratedCircuit, previewUpdateDelegate: (CircuitO } def incScale() { - rescaleAt(frame.midPoint, math.min(scale + 0.2, 3.0)) + rescaleAt(parent.frame.midPoint, math.min(scale + 0.2, 3.0)) } def decScale() { - rescaleAt(frame.midPoint, math.max(scale - 0.2, 0.5)) + rescaleAt(parent.frame.midPoint, math.max(scale - 0.2, 0.5)) } - def rescaleAt(point: Point, newScale: Double) { - val p = parent.convertPointTo(point, this).vectorize - val newP = (p / scale) * newScale - val dp = newP - p + private def rescaleAt(point: Point, newScale: Double): Unit = { + val newP = (point.vectorize / scale) * newScale + val dp = (newP - point.vectorize) / (RenderCircuit.BASE_SCALE * scale) + offset = offset + dp scale = newScale - position -= Point(dp) + } + + /** + * Scales the prefboard to the circuit with some border + */ + def scaleGuiToCircuit() = { + val circuitBounds = circuit.getPartsBoundingBox() + val circuitBoundsWithPadding = circuitBounds.union(Rect(circuitBounds.origin.subtract(1, 1), circuitBounds.size.add(3))) + // Required scaling to fit whole circuit on the screen + val requiredScale = math.min( + (parent.frame.size.width / RenderCircuit.BASE_SCALE.toDouble) / circuitBoundsWithPadding.size.width, + (parent.frame.size.height / RenderCircuit.BASE_SCALE.toDouble) / circuitBoundsWithPadding.size.height + ) + offset = circuitBoundsWithPadding.origin.vectorize + scale = requiredScale } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index 5c000ddbc..235eefdf7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -8,8 +8,8 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.gui.GuiDraw import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.core.vec.{Point, Size, Vec2} +import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} trait CircuitOp { @@ -33,26 +33,24 @@ trait CircuitOp { @SideOnly(Side.CLIENT) def getOpName: String + /** + * Render the selected Operation, when on the mouse cursor + * @param position Position in Grid coordinates + * @param scale Prefboard scaling + */ @SideOnly(Side.CLIENT) - def renderHover( - circuit: IntegratedCircuit, - point: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) + def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit + /** + * Render the selected Operation when dragging + * @param start Start in Grid coordinates + * @param end End in Grid coordinates + * @param positionsWithParts Positions in Rect(start, end) with existing parts + * @param scale Prefboard scaling + * @param prefboardOffset Prefboard offset + */ @SideOnly(Side.CLIENT) - def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) + def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit /** * Render the part, that will be placed by this operation @@ -71,6 +69,27 @@ trait CircuitOp { object CircuitOp { def getOperation(id: Int) = CircuitOpDefs(id).getOp + /** + * Draw one Tile + * @param position In Grid Coordinates + */ + def renderHolo(position: Vec2, scale: Double, colour: Int): Unit = { + val start = position * RenderCircuit.BASE_SCALE * scale + val end = start + Vec2(RenderCircuit.BASE_SCALE * scale, RenderCircuit.BASE_SCALE * scale) + GuiDraw.drawRect(start.dx.toInt, start.dy.toInt, (end - start).dx.toInt, (end - start).dy.toInt, colour) + } + + /** + * Draw Multiple tiles in a rect excluding end + * @param start In Grid Coordinates + * @param end In Grid coordinates + */ + def renderHolo(start: Vec2, end: Vec2, scale: Double, colour: Int): Unit = { + val s = start * RenderCircuit.BASE_SCALE * scale + val e = end * RenderCircuit.BASE_SCALE * scale + GuiDraw.drawRect(s.dx.toInt, s.dy.toInt, (e - s).dx.toInt, (e - s).dy.toInt, colour) + } + def renderHolo( x: Double, y: Double, @@ -88,15 +107,15 @@ object CircuitOp { GuiDraw.drawRect(x1, y1, x2 - x1, y2 - y1, colour) } - def isOnBorder(cSize: Size, point: Point) = - point.x == 0 || point.y == 0 || point.x == cSize.width - 1 || point.y == cSize.height - 1 - - def isOnEdge(cSize: Size, point: Point) = - point == Point(0, 0) || point == Point( - 0, - cSize.height - 1 - ) || point == Point(cSize.width - 1, 0) || point == Point( - cSize.width - 1, - cSize.height - 1 - ) -} \ No newline at end of file + def partsBetweenPoints(start: Vec2, end: Vec2, circuit: IntegratedCircuit): Seq[Vec2] = { + var partPositions: Seq[Vec2] = Seq.empty + for(x <- math.min(start.dx.toInt, end.dx.toInt) to math.max(start.dx.toInt, end.dx.toInt)) { + for(y <- math.min(start.dy.toInt, end.dy.toInt) to math.max(start.dy.toInt, end.dy.toInt)) { + if(circuit.getPart(x, y) != null) { + partPositions = partPositions :+ Vec2(x, y) + } + } + } + partPositions + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala index 549beeb2d..6f10e8bef 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala @@ -9,7 +9,7 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.render.uv.{UVScale, UVTranslation} import codechicken.lib.vec.Translation import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.vec.Point +import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication.IntegratedCircuit @@ -28,13 +28,13 @@ class CircuitOpErase extends CircuitOp { end: Point, out: MCDataOutput ) { - out.writeByte(start.x).writeByte(start.y) - out.writeByte(end.x).writeByte(end.y) + out.writeInt(start.x).writeInt(start.y) + out.writeInt(end.x).writeInt(end.y) } override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { - val start = Point(in.readUByte(), in.readUByte()) - val end = Point(in.readUByte(), in.readUByte()) + val start = Point(in.readInt(), in.readInt()) + val end = Point(in.readInt(), in.readInt()) for (x <- math.min(start.x, end.x) to math.max(start.x, end.x)) for (y <- math.min(start.y, end.y) to math.max(start.y, end.y)) @@ -62,41 +62,21 @@ class CircuitOpErase extends CircuitOp { } @SideOnly(Side.CLIENT) - override def renderHover( - circuit: IntegratedCircuit, - point: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(point) != null) - CircuitOp.renderHolo(x, y, xSize, ySize, circuit.size, point, 0x33ff0000) + override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + CircuitOp.renderHolo(position - prefboardOffset, scale, 0x33ff0000) } @SideOnly(Side.CLIENT) - override def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - for (px <- math.min(start.x, end.x) to math.max(start.x, end.x)) - for (py <- math.min(start.y, end.y) to math.max(start.y, end.y)) { - val point = Point(px, py) - CircuitOp.renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - if (circuit.getPart(point) != null) 0x44ff0000 else 0x44ffffff - ) - } + override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + var (topLeft, bottomRight) = ( + Vec2(math.min(start.dx, end.dx), math.min(start.dy, end.dy)).subtract(prefboardOffset), + Vec2(math.max(start.dx, end.dx), math.max(start.dy, end.dy)).subtract(prefboardOffset) + ) + bottomRight = bottomRight.add(1, 1) + CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) + for(posWithPart <- positionsWithParts) { + CircuitOp.renderHolo(posWithPart - prefboardOffset, scale, 0x44ff0000) + } } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index 548ba7ccd..7b2f63e7a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -12,7 +12,7 @@ import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, GateICPart, ICGateDefinition, ICGateRenderer} -import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, isOnEdge, renderHolo} +import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo class OpGate(meta: Int) extends CircuitOp { @@ -55,54 +55,18 @@ class OpGate(meta: Int) extends CircuitOp { } @SideOnly(Side.CLIENT) - override def renderHover( - circuit: IntegratedCircuit, - point: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(point) != null) return - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) + override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + val t = orthoPartT(position.subtract(prefboardOffset), scale) doRender(t, rotation, configuration) - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - 0x33ffffff - ) + renderHolo(position.subtract(prefboardOffset), scale, 0x33ffffff) } @SideOnly(Side.CLIENT) - override def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(start) != null) return - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, start.x, start.y) + def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + // Gates can't be dragged, so only the first will be rendered + val t = orthoPartT(start - prefboardOffset, scale) doRender(t, rotation, configuration) - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - start, - 0x44ffffff - ) + renderHolo(start - prefboardOffset, scale, 0x44ffffff) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala index 3015ca9bd..83e3fc4c0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala @@ -6,13 +6,13 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.vec.{Rotation, Transformation, Translation} +import codechicken.lib.vec.{Transformation, Translation} import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.vec.Point +import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.ICComponentStore.{orthoGridT, orthoPartT} -import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, renderHolo} import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.circuitparts.CircuitPart +import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo abstract class SimplePlacementOp extends CircuitOp { @@ -50,55 +50,17 @@ abstract class SimplePlacementOp extends CircuitOp { } @SideOnly(Side.CLIENT) - override def renderHover( - circuit: IntegratedCircuit, - point: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(point) != null) return - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - if (!isOnBorder(circuit.size, point)) 0x33ffffff else 0x33ff0000 - ) - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) + override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + val t = orthoPartT(position - prefboardOffset, scale) doPartRender(t) - + renderHolo(position.subtract(prefboardOffset), scale, 0x33ff0000) } @SideOnly(Side.CLIENT) - override def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(end) != null) return - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - end, - if (!isOnBorder(circuit.size, end)) 0x44ffffff else 0x44ff0000 - ) - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, end.x, end.y) + override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + val t = orthoPartT(end - prefboardOffset, scale) doPartRender(t) + renderHolo(end - prefboardOffset, scale, 0x44ffffff) } def doPartRender(t: Transformation) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala index 17e1803fe..49cc67a21 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala @@ -9,12 +9,12 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.vec.{Transformation, Translation} import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.color.Colors -import mrtjp.core.vec.Point +import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ +import mrtjp.projectred.fabrication.circuitparts.wire._ import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs} -import mrtjp.projectred.fabrication.circuitparts.wire.{BundledCableICPart, InsulatedWireICPart, RenderICAlloyWire, RenderICBundledCable, RenderICInsulatedWire} -import mrtjp.projectred.fabrication.operations.CircuitOp.{isOnBorder, renderHolo} +import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo abstract class OpWire extends CircuitOp { @@ -31,90 +31,77 @@ abstract class OpWire extends CircuitOp { end: Point, out: MCDataOutput ) { - out.writeByte(start.x).writeByte(start.y) - out.writeByte(end.x).writeByte(end.y) + out.writeInt(start.x).writeInt(start.y) + out.writeInt(end.x).writeInt(end.y) } override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { - val start = Point(in.readUByte(), in.readUByte()) - val end = Point(in.readUByte(), in.readUByte()) - val end2 = start + Point((end - start).vectorize.axialProject) - - for (px <- math.min(start.x, end2.x) to math.max(start.x, end2.x)) - for (py <- math.min(start.y, end2.y) to math.max(start.y, end2.y)) - if (!isOnBorder(circuit.size, Point(px, py))) - if (circuit.getPart(px, py) == null) - circuit.setPart(px, py, createPart) + val start = Point(in.readInt(), in.readInt()) + val end = Point(in.readInt(), in.readInt()) + val corner = start + Point((end - start).vectorize.axialProject) + + for(x <- math.min(start.x, corner.x) to math.max(start.x, corner.x)) { + for(y <- math.min(start.y, corner.y) to math.max(start.y, corner.y)) { + if(circuit.getPart(x, y) == null) { + circuit.setPart(x, y, createPart) + } + } + } + for(x <- math.min(corner.x, end.x) to math.max(corner.x, end.x)) { + for(y <- math.min(corner.y, end.y) to math.max(corner.y, end.y)) { + if(circuit.getPart(x, y) == null) { + circuit.setPart(x, y, createPart) + } + } + } } def createPart: CircuitPart @SideOnly(Side.CLIENT) - override def renderHover( - circuit: IntegratedCircuit, - point: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(point) != null) return - - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - if (isOnBorder(circuit.size, point)) 0x33ff0000 else 0x33ffffff - ) - - val t = orthoPartT(x, y, xSize, ySize, circuit.size, point.x, point.y) + override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + val t = orthoPartT(position.subtract(prefboardOffset), scale) doRender(t, 0) + renderHolo(position.subtract(prefboardOffset), scale, 0x33ffffff) } @SideOnly(Side.CLIENT) - override def renderDrag( - circuit: IntegratedCircuit, - start: Point, - end: Point, - x: Double, - y: Double, - xSize: Double, - ySize: Double - ) { - if (circuit.getPart(start) != null) return - - val end2 = start + Point((end - start).vectorize.axialProject) - - for (px <- math.min(start.x, end2.x) to math.max(start.x, end2.x)) - for (py <- math.min(start.y, end2.y) to math.max(start.y, end2.y)) { - val point = Point(px, py) - renderHolo( - x, - y, - xSize, - ySize, - circuit.size, - point, - if (isOnBorder(circuit.size, point)) 0x44ff0000 else 0x44ffffff - ) - - if (circuit.getPart(px, py) == null) { - val t = orthoPartT(x, y, xSize, ySize, circuit.size, px, py) - var m = 0 - if (px > start.x) { m |= 8; if (px != end2.x) m |= 2 } - if (px < start.x) { m |= 2; if (px != end2.x) m |= 8 } - if (py > start.y) { m |= 1; if (py != end2.y) m |= 4 } - if (py < start.y) { m |= 4; if (py != end2.y) m |= 1 } - if (px == start.x && end2.x > start.x) m |= 2 - if (px == start.x && end2.x < start.x) m |= 8 - if (py == start.y && end2.y > start.y) m |= 4 - if (py == start.y && end2.y < start.y) m |= 1 - doRender(t, m) + override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + val corner = start + (end - start).axialProject + + for(x <- math.min(start.dx.toInt, corner.dx.toInt) to math.max(start.dx.toInt, corner.dx.toInt)) { + for(y <- math.min(start.dy.toInt, corner.dy.toInt) to math.max(start.dy.toInt, corner.dy.toInt)) { + if(!positionsWithParts.contains(Point(x, y))) { + val t = orthoPartT(Vec2(x, y) - prefboardOffset, scale) + doRender(t, 0) + } + renderHolo(Vec2(x, y) - prefboardOffset, corner.subtract(prefboardOffset), scale, 0x44ffffff) + } + } + for(x <- math.min(corner.dx.toInt, end.dx.toInt) to math.max(corner.dx.toInt, end.dx.toInt)) { + for(y <- math.min(corner.dy.toInt, end.dy.toInt) to math.max(corner.dy.toInt, end.dy.toInt)) { + if(!positionsWithParts.contains(Point(x, y))) { + val t = orthoPartT(Vec2(x, y) - prefboardOffset, scale) + doRender(t, 0) } + renderHolo(Vec2(x, y) - prefboardOffset, corner.subtract(prefboardOffset), scale, 0x44ffffff) } + } + + // TODO Connections +// if (circuit.getPart(px, py) == null) { +// val t = orthoPartT(x, y, xSize, ySize, circuit.size, px, py) +// var m = 0 +// if (px > start.x) { m |= 8; if (px != end2.x) m |= 2 } +// if (px < start.x) { m |= 2; if (px != end2.x) m |= 8 } +// if (py > start.y) { m |= 1; if (py != end2.y) m |= 4 } +// if (py < start.y) { m |= 4; if (py != end2.y) m |= 1 } +// if (px == start.x && end2.x > start.x) m |= 2 +// if (px == start.x && end2.x < start.x) m |= 8 +// if (py == start.y && end2.y > start.y) m |= 4 +// if (py == start.y && end2.y < start.y) m |= 1 +// doRender(t, m) +// } } @SideOnly(Side.CLIENT) From 4336911754c587576b148795d3e0fd7e9f6511f7 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:23:48 +0200 Subject: [PATCH 08/21] Remove configuration GUIs --- .../circuitparts/ArrayGateICPart.scala | 8 +- .../circuitparts/ComboICGatePart.scala | 7 +- .../fabrication/circuitparts/GateICPart.scala | 6 +- .../circuitparts/ICGateLogic.scala | 4 - .../circuitparts/SequentialGateICPart.scala | 18 +++- .../circuitparts/io/IOGateICPart.scala | 30 ++++-- .../circuitparts/io/SimpleIO.scala | 5 - .../circuitparts/io/TFreqIOICGateLogic.scala | 7 -- .../circuitparts/misc/Counter.scala | 5 - .../circuitparts/timing/Sequencer.scala | 5 - .../circuitparts/timing/Timer.scala | 5 - .../fabrication/gui/GuiICWorkbench.scala | 51 ++++++--- .../fabrication/gui/ICCounterGateGui.scala | 101 ------------------ .../fabrication/gui/ICGateGui.scala | 32 ------ .../fabrication/gui/ICIOFreqGateGui.scala | 77 ------------- .../fabrication/gui/ICIOGateGui.scala | 43 -------- .../fabrication/gui/ICTimerGateGui.scala | 79 -------------- .../projectred/fabrication/gui/TGateGui.scala | 35 ------ .../gui/nodes/ConfigurationNode.scala | 33 ++++++ .../fabrication/gui/nodes/PrefboardNode.scala | 23 ++-- .../gui/nodes/configuration/ColorPicker.scala | 37 +++++++ .../configuration/ConfigurationAnalogIO.scala | 36 +++++++ .../ConfigurationBundledIO.scala | 19 ++++ .../configuration/ConfigurationCounter.scala | 71 ++++++++++++ .../configuration/ConfigurationRotation.scala | 20 ++++ .../ConfigurationRotationConfig.scala | 20 ++++ .../configuration/ConfigurationSimpleIO.scala | 60 +++++++++++ .../configuration/ConfigurationTimer.scala | 42 ++++++++ 28 files changed, 433 insertions(+), 446 deletions(-) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala index 837aa8430..919b0321b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala @@ -5,11 +5,15 @@ */ package mrtjp.projectred.fabrication.circuitparts +import mrtjp.projectred.fabrication.gui.nodes.configuration.ConfigurationRotation +import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} + class ArrayGateICPart extends RedstoneGateICPart with TComplexGateICPart - with TArrayGateICPart { + with TArrayGateICPart + with TConfigurable { private var logic: ArrayGateICLogic = null override def getLogic[T] = logic.asInstanceOf[T] @@ -19,4 +23,6 @@ class ArrayGateICPart } override def getPartType = CircuitPartDefs.ArrayGate + + override def createConfigurationNode: ConfigurationNode = new ConfigurationRotation(this) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala index 0f050dc62..31ade76f4 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala @@ -5,10 +5,15 @@ */ package mrtjp.projectred.fabrication.circuitparts -class ComboICGatePart extends RedstoneGateICPart { +import mrtjp.projectred.fabrication.gui.nodes.configuration.ConfigurationRotationConfig +import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} + +class ComboICGatePart extends RedstoneGateICPart with TConfigurable { override def getLogic[T] = ComboICGateLogic.instances(subID).asInstanceOf[T] def getLogicCombo = getLogic[ComboICGateLogic] override def getPartType = CircuitPartDefs.SimpleGate + + override def createConfigurationNode: ConfigurationNode = new ConfigurationRotationConfig(this) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala index 946be37ea..18e97f08f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala @@ -8,7 +8,6 @@ package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.fabrication.gui.IGuiCircuitPart import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound @@ -16,7 +15,7 @@ abstract class GateICPart extends CircuitPart with TConnectableICPart with TICOrient - with IGuiCircuitPart { + with TClientNetCircuitPart { private var gateSubID: Byte = 0 private var gateShape: Byte = 0 @@ -202,9 +201,6 @@ abstract class GateICPart super.getRolloverData(detailLevel) ++ s.result().map(GRAY + _) } - @SideOnly(Side.CLIENT) - override def createGui = getLogicPrimitive.createGui(this) - @SideOnly(Side.CLIENT) override def onClicked() { sendClientPacket(_.writeByte(2)) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala index f918dfe39..1e89aba74 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateLogic.scala @@ -6,7 +6,6 @@ package mrtjp.projectred.fabrication.circuitparts import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICGateGui} abstract class ICGateLogic[T <: GateICPart] { def canConnectTo(gate: T, part: CircuitPart, r: Int): Boolean @@ -25,7 +24,4 @@ abstract class ICGateLogic[T <: GateICPart] { @SideOnly(Side.CLIENT) def getRolloverData(gate: T, detailLevel: Int): Seq[String] = Seq.empty - - @SideOnly(Side.CLIENT) - def createGui(gate: T): CircuitGui = new ICGateGui(gate) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala index a2c19387e..853011252 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala @@ -7,11 +7,14 @@ package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.MCDataInput import mrtjp.projectred.ProjectRedCore.log -import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic +import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, ToggleLatch} +import mrtjp.projectred.fabrication.circuitparts.misc.{ICounterGuiLogic, Synchronizer} import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic +import mrtjp.projectred.fabrication.gui.nodes.configuration.{ConfigurationCounter, ConfigurationRotation, ConfigurationRotationConfig, ConfigurationTimer} +import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} -class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart { +class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart with TConfigurable { var logic: SequentialICGateLogic = null override def assertLogic() { @@ -26,7 +29,7 @@ class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart { case 3 => getLogicPrimitive match { case t: ITimerGuiLogic => - t.setTimerMax(this, t.getTimerMax + in.readShort()) + t.setTimerMax(this, in.readShort()) case _ => log.error( "Server IC stream received client packet for incorrect gate type" @@ -52,4 +55,13 @@ class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart { } case _ => super.readClientPacket(in, key) } + + override def createConfigurationNode: ConfigurationNode = { + getLogicPrimitive match { + case _: ICounterGuiLogic => new ConfigurationCounter(this) + case _: ITimerGuiLogic => new ConfigurationTimer(this) + case _ => + new ConfigurationRotationConfig(this) + } + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala index 44d5677b0..883fd1535 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala @@ -7,11 +7,14 @@ package mrtjp.projectred.fabrication.circuitparts.io import codechicken.lib.data.MCDataInput import mrtjp.projectred.fabrication.circuitparts.{CircuitPartDefs, RedstoneGateICPart, TComplexGateICPart} +import mrtjp.projectred.fabrication.gui.nodes.configuration.{ConfigurationAnalogIO, ConfigurationBundledIO, ConfigurationSimpleIO} +import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} class IOGateICPart extends RedstoneGateICPart with TIOCircuitPart - with TComplexGateICPart { + with TComplexGateICPart + with TConfigurable { private var logic: IOICGateLogic = null override def getLogic[T] = logic.asInstanceOf[T] @@ -25,17 +28,19 @@ class IOGateICPart override def readClientPacket(in: MCDataInput, key: Int) = key match { case 5 => getLogicIO match { - case f: TFreqIOICGateLogic => f.freqUp() - case _ => - } - case 6 => - getLogicIO match { - case f: TFreqIOICGateLogic => f.freqDown() + case f: TFreqIOICGateLogic => + f.freq = in.readByte() + f.sendFreqUpdate() + f.gate.onChange() case _ => } case _ => super.readClientPacket(in, key) } + def sendFrequency(color: Int): Unit = { + sendClientPacket(_.writeByte(5).writeByte(color)) + } + override def getPartType = CircuitPartDefs.IOGate override def onExtInputChanged(r: Int) { @@ -66,4 +71,15 @@ class IOGateICPart if (oldOutput != newOutput) world.onOutputChanged(1 << rotation) } } + + override def createConfigurationNode: ConfigurationNode = { + getLogicIO match { + case _: BundledIOICGateLogic => + new ConfigurationBundledIO(this) + case _: SimpleIOICGateLogic => + new ConfigurationSimpleIO(this) + case _: AnalogIOICGateLogic => + new ConfigurationAnalogIO(this) + } + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala index 34e5d9b13..bf6496076 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala @@ -5,9 +5,7 @@ */ package mrtjp.projectred.fabrication.circuitparts.io -import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore.signalColour -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICIOGateGui} class SimpleIOICGateLogic(gate: IOGateICPart) @@ -32,9 +30,6 @@ class SimpleIOICGateLogic(gate: IOGateICPart) if ((gate.world.iostate(gate.rotation) & 0x8000) != 0) 1 else 0x8000 ) } - - @SideOnly(Side.CLIENT) - override def createGui(gate: IOGateICPart): CircuitGui = new ICIOGateGui(gate) } class RenderSimpleIO extends RenderIO { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala index 3fa8b721a..488d91bcd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala @@ -6,8 +6,6 @@ package mrtjp.projectred.fabrication.circuitparts.io import codechicken.lib.data.{MCDataInput, MCDataOutput} -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICIOFreqGateGui} import net.minecraft.nbt.NBTTagCompound trait TFreqIOICGateLogic extends IOICGateLogic { @@ -74,9 +72,4 @@ trait TFreqIOICGateLogic extends IOICGateLogic { 0) << freq gate.world.setOutput(gate.rotation, s) } - - @SideOnly(Side.CLIENT) - override def createGui(gate: IOGateICPart): CircuitGui = new ICIOFreqGateGui( - gate - ) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala index 70439d053..b6b6db8e0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala @@ -11,7 +11,6 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.TFaceOrient.flipMaskZ import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICCounterGateGui} import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} import net.minecraft.nbt.NBTTagCompound @@ -155,10 +154,6 @@ class Counter(gate: SequentialGateICPart) if (newOutput != oldOutput) gate.onOutputChange(5) } - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICCounterGateGui(gate) - @SideOnly(Side.CLIENT) override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { val data = Seq.newBuilder[String] diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala index fd28ebe02..c8cf34f90 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala @@ -11,7 +11,6 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.Configurator import mrtjp.projectred.core.TFaceOrient.flipMaskZ import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICTimerGateGui} import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} import net.minecraft.nbt.NBTTagCompound @@ -84,10 +83,6 @@ class Sequencer(gate: SequentialGateICPart) true } - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICTimerGateGui(gate) - @SideOnly(Side.CLIENT) override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { val data = Seq.newBuilder[String] diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala index 4e8673444..93ebb5039 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala @@ -12,7 +12,6 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.Configurator import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.gui.{CircuitGui, ICTimerGateGui} import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} import net.minecraft.nbt.NBTTagCompound @@ -161,10 +160,6 @@ trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { def interpPointer(f: Float) = if (pointer_start < 0) 0f else (pointerValue + f) / pointer_max - @SideOnly(Side.CLIENT) - override def createGui(gate: SequentialGateICPart): CircuitGui = - new ICTimerGateGui(gate) - @SideOnly(Side.CLIENT) override def getRolloverData(gate: SequentialGateICPart, detailLevel: Int) = { val data = Seq.newBuilder[String] diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index bd8d8cbb4..1247880aa 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -28,6 +28,7 @@ import java.math.MathContext class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var pref: PrefboardNode = null var toolSets = Seq[ICToolsetNode]() + var configurationNode: TNode = null override def onAddedToParent_Impl() { val clip = new ClipNode @@ -39,7 +40,20 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { opPreview.position = Point(269, 18) addChild(opPreview) - pref = new PrefboardNode(tile.circuit, tile.hasBP, op => {opPreview.updatePreview(op)}) + pref = new PrefboardNode( + tile.circuit, tile.hasBP, + op => {opPreview.updatePreview(op)}, + node => { + if(configurationNode != null) { + configurationNode.removeFromParent() + configurationNode = null + } + configurationNode = node + if(configurationNode != null) { + configurationNode.position = Point(260, 17) + addChild(configurationNode) + } + }) pref.zPosition = -0.01 // Must be below clip nodes pref.opPickDelegate = { op => if (op == null) { @@ -80,6 +94,10 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolset.opSelectDelegate = { op => pref.currentOp = op pref.updatePreview() + if(configurationNode != null) { + configurationNode.removeFromParent() + configurationNode = null + } } toolbar.addChild(toolset) toolSets :+= toolset @@ -130,43 +148,43 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolbar.position = Point(size.width / 2 - toolbar.calculateAccumulatedFrame.width / 2, 235) - val textbox = new SimpleTextboxNode() - textbox.position = Point(80, 4) - textbox.size = Size(150, 12) - textbox.text = tile.circuit.name - textbox.textChangedDelegate = { () => tile.sendICNameToServer(textbox.text) } - addChild(textbox) + val textboxICName = new SimpleTextboxNode() + textboxICName.position = Point(80, 4) + textboxICName.size = Size(115, 11) + textboxICName.text = tile.circuit.name + textboxICName.textChangedDelegate = { () => tile.sendICNameToServer(textboxICName.text) } + addChild(textboxICName) val dminus = new MCButtonNode - dminus.position = Point(269, 175) + dminus.position = Point(269, 200) dminus.size = Size(10, 10) dminus.text = "-" dminus.clickDelegate = { () => pref.decDetail() } addChild(dminus) val dplus = new MCButtonNode - dplus.position = Point(309, 175) + dplus.position = Point(309, 200) dplus.size = Size(10, 10) dplus.text = "+" dplus.clickDelegate = { () => pref.incDetail() } addChild(dplus) val sminus = new MCButtonNode - sminus.position = Point(269, 207) + sminus.position = Point(268, 4) sminus.size = Size(10, 10) sminus.text = "-" sminus.clickDelegate = { () => pref.decScale() } addChild(sminus) val splus = new MCButtonNode - splus.position = Point(309, 207) + splus.position = Point(308, 4) splus.size = Size(10, 10) splus.text = "+" splus.clickDelegate = { () => pref.incScale() } addChild(splus) val resetView = new MCButtonNode - resetView.position = Point(265, 133) + resetView.position = Point(200, 3) resetView.size = Size(60, 12) resetView.text = "Reset View" resetView.clickDelegate = { () => @@ -209,22 +227,21 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { GuiDraw.drawString("IC Workbench", 8, 6, Colors.GREY.argb, false) - GuiDraw.drawStringC("detail", 273, 162, 42, 14, Colors.GREY.argb, false) + GuiDraw.drawStringC("detail", 273, 190, 42, 14, Colors.GREY.argb, false) GuiDraw.drawStringC( pref.detailLevel + "", 279, - 175, + 200, 30, 10, Colors.GREY.argb, false ) - GuiDraw.drawStringC("scale", 273, 193, 42, 14, Colors.GREY.argb, false) GuiDraw.drawStringC( BigDecimal(pref.scale, new MathContext(2)) + "", - 279, - 207, + 278, + 4, 30, 10, Colors.GREY.argb, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala deleted file mode 100644 index 946248f3f..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/ICCounterGateGui.scala +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.gui.GuiDraw -import mrtjp.core.color.Colors -import mrtjp.core.gui.MCButtonNode -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.SequentialGateICPart -import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic - -class ICCounterGateGui(override val gate: SequentialGateICPart) - extends CircuitGui(gate) - with TGateGui { - var valID = 0 - - { - size = Size(160, 94) - - val ax = 54 - val aw = 50 - val ah = 15 - - val rotate = new MCButtonNode - rotate.position = Point(ax, 5) - rotate.size = Size(aw, ah) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(ax + aw + 1, 5) - conf.size = Size(aw, ah) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - val sw = new MCButtonNode - sw.position = Point(54, 28) - sw.size = Size(20, 12) - sw.text = "var" - sw.clickDelegate = { () => valID = (valID + 1) % 3 } - addChild(sw) - - def createButton(x: Int, y: Int, w: Int, h: Int, delta: Int) { - val b = new MCButtonNode - b.position = Point(x, y) - b.size = Size(w, h) - b.text = (if (delta < 0) "" else "+") + delta - b.clickDelegate = { () => - gate.sendClientPacket(_.writeByte(4).writeByte(valID).writeShort(delta)) - } - addChild(b) - } - - val bw = 32 - val bh = 12 - val r1x = 69 - val r2x = r1x + 35 - val by = 48 - val bdy = 14 - - createButton(r1x, by + (0 * bdy), bw, bh, -1) - createButton(r1x, by + (1 * bdy), bw, bh, -5) - createButton(r1x, by + (2 * bdy), bw, bh, -10) - - createButton(r2x, by + (0 * bdy), bw, bh, 1) - createButton(r2x, by + (1 * bdy), bw, bh, 5) - createButton(r2x, by + (2 * bdy), bw, bh, 10) - } - - def getLogic = gate.getLogic[ICounterGuiLogic] - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - val s = "State: " + getLogic.getCounterValue - GuiDraw.drawStringC( - s, - position.x + 102, - position.y + 24, - Colors.GREY.argb, - false - ) - - val m = valID match { - case 0 => "Max: " + getLogic.getCounterMax - case 1 => "Incr: " + getLogic.getCounterIncr - case 2 => "Decr: " + getLogic.getCounterDecr - } - GuiDraw.drawStringC( - m, - position.x + 102, - position.y + 36, - Colors.GREY.argb, - false - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala deleted file mode 100644 index 5f1be4d53..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/ICGateGui.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import mrtjp.core.gui.MCButtonNode -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.GateICPart - -class ICGateGui(override val gate: GateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(120, 55) - - val rotate = new MCButtonNode - rotate.position = Point(58, 12) - rotate.size = Size(50, 15) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(58, 28) - conf.size = Size(50, 15) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala deleted file mode 100644 index b4636afdf..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOFreqGateGui.scala +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.gui.GuiDraw -import mrtjp.core.color.Colors -import mrtjp.core.gui.MCButtonNode -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.io.{IOGateICPart, TFreqIOICGateLogic} - - -class ICIOFreqGateGui(override val gate: IOGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(138, 55) - - val conf = new MCButtonNode - conf.position = Point(52, 7) - conf.size = Size(46, 15) - conf.text = "io mode" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - val minus = new MCButtonNode - minus.position = Point(52, 33) - minus.size = Size(14, 14) - minus.text = "-" - minus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(6)) } - addChild(minus) - - val plus = new MCButtonNode - plus.position = Point(117, 33) - plus.size = Size(14, 14) - plus.text = "+" - plus.clickDelegate = { () => gate.sendClientPacket(_.writeByte(5)) } - addChild(plus) - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - GuiDraw.drawStringC( - gate.shape match { - case 0 => "input" - case 1 => "output" - case 2 => "inout" - }, - position.x + 117, - position.y + 11, - Colors.GREY.argb, - false - ) - - GuiDraw.drawStringC( - "freq", - position.x + 66, - position.y + 22, - 50, - 14, - Colors.GREY.argb, - false - ) - GuiDraw.drawStringC( - gate.getLogic[TFreqIOICGateLogic].getFreqName, - position.x + 66, - position.y + 33, - 50, - 14, - Colors.GREY.argb, - false - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala deleted file mode 100644 index adcd3aa2d..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/ICIOGateGui.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.gui.GuiDraw -import mrtjp.core.color.Colors -import mrtjp.core.gui.MCButtonNode -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart - -class ICIOGateGui(override val gate: IOGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(124, 55) - - val conf = new MCButtonNode - conf.position = Point(62, 33) - conf.size = Size(46, 15) - conf.text = "io mode" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - GuiDraw.drawStringC( - gate.shape match { - case 0 => "input" - case 1 => "output" - case 2 => "inout" - }, - position.x + 85, - position.y + 16, - Colors.GREY.argb, - false - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala deleted file mode 100644 index ad0305ab7..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/ICTimerGateGui.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.gui.GuiDraw -import mrtjp.core.color.Colors -import mrtjp.core.gui.MCButtonNode -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.SequentialGateICPart -import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic - -class ICTimerGateGui(override val gate: SequentialGateICPart) - extends CircuitGui(gate) - with TGateGui { - { - size = Size(160, 80) - - val ax = 54 - val aw = 50 - val ah = 15 - - val rotate = new MCButtonNode - rotate.position = Point(ax, 5) - rotate.size = Size(aw, ah) - rotate.text = "rotate" - rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } - addChild(rotate) - - val conf = new MCButtonNode - conf.position = Point(ax + aw + 1, 5) - conf.size = Size(aw, ah) - conf.text = "configure" - conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } - addChild(conf) - - def createButton(x: Int, y: Int, w: Int, h: Int, text: String, delta: Int) { - val b = new MCButtonNode - b.position = Point(x, y) - b.size = Size(w, h) - b.text = text - b.clickDelegate = { () => - gate.sendClientPacket(_.writeByte(3).writeShort(delta)) - } - addChild(b) - } - - val bw = 32 - val bh = 12 - val r1x = 69 - val r2x = r1x + 35 - val by = 34 - val bdy = 14 - - createButton(r1x, by + (0 * bdy), bw, bh, "-50ms", -1) - createButton(r1x, by + (1 * bdy), bw, bh, "-1s", -20) - createButton(r1x, by + (2 * bdy), bw, bh, "-10s", -200) - - createButton(r2x, by + (0 * bdy), bw, bh, "+50ms", 1) - createButton(r2x, by + (1 * bdy), bw, bh, "+1s", 20) - createButton(r2x, by + (2 * bdy), bw, bh, "+10s", 200) - } - - def getLogic = gate.getLogic[ITimerGuiLogic] - - override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - val s = "Interval: " + "%.2f".format(getLogic.getTimerMax * 0.05) + "s" - GuiDraw.drawStringC( - s, - position.x + 102, - position.y + 24, - Colors.GREY.argb, - false - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala deleted file mode 100644 index e9ba2ed28..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/TGateGui.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.vec.Translation -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.ICComponentStore -import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer} - -trait TGateGui extends CircuitGui { - var gateRenderSize = Size(40, 40) - var gateRenderX = 10 - - def gate: GateICPart - - abstract override def drawBack_Impl(mouse: Point, rframe: Float) { - super.drawBack_Impl(mouse, rframe) - - ICGateRenderer.renderDynamic( - gate, - ICComponentStore - .orthoGridT(gateRenderSize.width, gateRenderSize.height) `with` - new Translation( - position.x + gateRenderX, - position.y + (size / 2 - gateRenderSize / 2).height, - 0 - ), - true, - rframe - ) - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala new file mode 100644 index 000000000..8830a846a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.vec.Translation +import mrtjp.core.gui.TNode +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.ICComponentStore +import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, TClientNetCircuitPart} + +trait TConfigurable extends TClientNetCircuitPart { + def createConfigurationNode: ConfigurationNode +} + +abstract class ConfigurationNode(gate: GateICPart) extends TNode { + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + val pos = position.add(8, 0) + ICGateRenderer.renderDynamic( + gate, + ICComponentStore.orthoGridT(50, 50) `with` + new Translation( + pos.x, + pos.y, + 0 + ), + true, + rframe + ) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index f9d76a169..efa06bc3b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -23,7 +23,7 @@ import org.lwjgl.input.{Keyboard, Mouse} import scala.collection.JavaConversions._ import scala.collection.convert.WrapAsJava -class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUpdateDelegate: (CircuitOp) => Unit) extends TNode { +class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUpdateDelegate: CircuitOp => Unit, setConfigNode: TNode => Unit) extends TNode { var currentOp: CircuitOp = null /** 0 - off 1 - name only 2 - minor details 3 - all details @@ -143,8 +143,8 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp private var mousePosition = Point(0, 0) override def mouseDragged_Impl(p: Point, button: Int, time: Long, consumed: Boolean): Boolean = { - if(!consumed && rayTest(p) && currentOp == null) { - if(time > 10) { + if(!consumed && rayTest(p) && button == 0 && currentOp == null) { + if(time > 20) { offset = offset - (p - mousePosition).vectorize / (RenderCircuit.BASE_SCALE * scale) } mousePosition = p @@ -169,16 +169,8 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp rightMouseDown = true val gridP = toGridPoint(p.vectorize) circuit.getPart(gridP) match { - case gp: IGuiCircuitPart => - val currentlyOpen = children.collect { case cg: CircuitGui => cg } - if (!currentlyOpen.exists(_.part == gp)) { - val gui = gp.createGui - gui.position = - convertPointFrom(Point(4, 4) * (currentlyOpen.size + 1), parent) - gui.linePointerCalc = () => toCenteredGuiPoint(gridP) - addChild(gui) - gui.pushZTo(currentlyOpen.size * 0.1) - } + case gp: TConfigurable => + setConfigNode(gp.createConfigurationNode) case _ => } return true @@ -316,7 +308,10 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp val pos = parent.convertPointFromScreen(absPos) if (rayTest(pos)) { val part = circuit.getPart(toGridPoint(pos.vectorize)) - opPickDelegate(if (part != null) part.getPickOp else null) + opPickDelegate(if (part != null) { + setConfigNode(null) + part.getPickOp + } else null) updatePreview() } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala new file mode 100644 index 000000000..0ad864e01 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.TNode +import mrtjp.core.vec.{Point, Rect, Size} + +class ColorPicker(onPickColor: Int => Unit) extends TNode { + + var size = Size.zeroSize + + override def frame = Rect(position, size) + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + val edge = size.width / 4 + + for(i <- 0 to 15) { + GuiDraw.drawRect(position.x + (i % 4) * edge, position.y + (i / 4) * edge, edge, edge, Colors(i).argb) + } + } + + override def mouseClicked_Impl(p: Point, button: Int, consumed: Boolean): Boolean = { + if(!consumed && rayTest(p)) { + val relPos = p.subtract(position) + val index = (relPos.y / (size.height / 4)) * 4 + relPos.x / (size.width / 4) + onPickColor(index) + true + } + else + false + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala new file mode 100644 index 000000000..bb3223a69 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.SimpleTextboxNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.io.{AnalogIOICGateLogic, IOGateICPart} + +import scala.util.Try + +class ConfigurationAnalogIO(gate: IOGateICPart) extends ConfigurationSimpleIO(gate) { + private val logic = gate.getLogicPrimitive.asInstanceOf[AnalogIOICGateLogic] + + val freq = new SimpleTextboxNode + freq.position = Point(20, 110) + freq.size = Size(30, 12) + freq.text = "0x%x".format(logic.freq) + freq.textChangedDelegate = { () => { + val num = Try(Integer.parseInt(freq.text.substring(2), 16)) + gate.sendFrequency(num.getOrElse(0)) + } + } + addChild(freq) + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + super.drawBack_Impl(mouse, rframe) + + val pos_text = position.add(5, 100) + GuiDraw.drawString("Frequency:", pos_text.x, pos_text.y, Colors.GREY.argb, false) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala new file mode 100644 index 000000000..4b63d3ff9 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart + +class ConfigurationBundledIO(gate: IOGateICPart) extends ConfigurationSimpleIO(gate){ + val colorPicker = new ColorPicker( + onPickColor = color => { + gate.sendFrequency(color) + }) + colorPicker.position = Point(5, 100) + colorPicker.size = Size(60, 60) + addChild(colorPicker) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala new file mode 100644 index 000000000..caa6a00f8 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.SimpleTextboxNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.SequentialGateICPart +import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic + +import scala.util.Try + +class ConfigurationCounter(gate: SequentialGateICPart) extends ConfigurationRotationConfig(gate) { + private val counterLogic = gate.getLogicPrimitive.asInstanceOf[ICounterGuiLogic] + + val max = new SimpleTextboxNode() + max.position = Point(30, 118) + max.size = Size(30, 12) + max.text = counterLogic.getCounterMax.toString + max.allowedcharacters = "0123456789" + max.textChangedDelegate = { () => { + val num = Try(max.text.toInt) + gate.sendClientPacket(_.writeByte(4).writeByte(0).writeShort(num.getOrElse(1))) + } } + addChild(max) + + val inc = new SimpleTextboxNode() + inc.position = Point(30, 138) + inc.size = Size(30, 12) + inc.text = counterLogic.getCounterIncr.toString + inc.allowedcharacters = "0123456789" + inc.textChangedDelegate = { () => { + val num = Try(inc.text.toInt) + gate.sendClientPacket(_.writeByte(4).writeByte(1).writeShort(num.getOrElse(1))) + } } + addChild(inc) + + val dec = new SimpleTextboxNode() + dec.position = Point(30, 158) + dec.size = Size(30, 12) + dec.text = counterLogic.getCounterDecr.toString + dec.allowedcharacters = "0123456789" + dec.textChangedDelegate = { () => { + val num = Try(dec.text.toInt) + gate.sendClientPacket(_.writeByte(4).writeByte(2).writeShort(num.getOrElse(1))) + } } + addChild(dec) + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + super.drawBack_Impl(mouse, rframe) + + val pos_state = position.add(5, 102) + GuiDraw.drawString( + "State: " + counterLogic.getCounterValue.toString, + pos_state.x, pos_state.y, Colors.GREY.argb, false + ) + + val pos_max = position.add(5, 120) + GuiDraw.drawString("Max", pos_max.x, pos_max.y, Colors.GREY.argb, false) + + val pos_inc = position.add(5, 140) + GuiDraw.drawString("Inc", pos_inc.x, pos_inc.y, Colors.GREY.argb, false) + + val pos_dec = position.add(5, 160) + GuiDraw.drawString("Dec", pos_dec.x, pos_dec.y, Colors.GREY.argb, false) + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala new file mode 100644 index 000000000..3d5ee33b3 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.GateICPart +import mrtjp.projectred.fabrication.gui.nodes.ConfigurationNode + +class ConfigurationRotation(gate: GateICPart) extends ConfigurationNode(gate) { + val rotate = new MCButtonNode + rotate.position = Point(8, 60) + rotate.size = Size(50, 15) + rotate.text = "rotate" + rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } + addChild(rotate) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala new file mode 100644 index 000000000..6146d7892 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import mrtjp.core.gui.MCButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.GateICPart + +class ConfigurationRotationConfig(gate: GateICPart) extends ConfigurationRotation(gate) { + + val conf = new MCButtonNode + conf.position = Point(8, 80) + conf.size = Size(50, 15) + conf.text = "configure" + conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(conf) +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala new file mode 100644 index 000000000..ca2576a5a --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import codechicken.lib.vec.{Rotation, Scale, TransformationList, Translation} +import mrtjp.core.gui.IconButtonNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart +import mrtjp.projectred.fabrication.{ArrowModel, ICComponentStore} + +class ConfigurationSimpleIO(gate: IOGateICPart) extends ConfigurationRotation(gate) { + + val arrowModel = new ArrowModel + + val in = new IconButtonNode { + override def drawButton(mouseover: Boolean): Unit = { + renderIcon(0, position) + } + } + + in.position = Point(5, 80) + in.size = Size(20, 15) + in.clickDelegate = { + () => gate.sendClientPacket(_.writeByte(1)) + } + addChild(in) + + val out = new IconButtonNode { + override def drawButton(mouseover: Boolean): Unit = + renderIcon(1, position) + } + out.position = Point(25, 80) + out.size = Size(20, 15) + out.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(out) + + val inout = new IconButtonNode { + override def drawButton(mouseover: Boolean): Unit = + renderIcon(2, position) + } + inout.position = Point(45, 80) + inout.size = Size(20, 15) + inout.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + addChild(inout) + + private def renderIcon(icon: Int, position: Point): Unit = { + val t = new TransformationList( + new Scale(40, 1, -40), + new Rotation(0.5 * math.Pi, 1, 0, 0), + new Translation(position.x - 9, position.y - 12, 0) + ) + arrowModel.arrowDirection = icon + ICComponentStore.prepairRender() + arrowModel.renderModel(t, 0, true) + ICComponentStore.finishRender() + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala new file mode 100644 index 000000000..51cf0c35d --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes.configuration + +import codechicken.lib.gui.GuiDraw +import codechicken.lib.vec.Translation +import mrtjp.core.color.Colors +import mrtjp.core.gui.SimpleTextboxNode +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.ICComponentStore +import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic +import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart} + +import scala.util.Try + +class ConfigurationTimer(gate: SequentialGateICPart) extends ConfigurationRotation(gate) { + private val timerLogic = gate.getLogicPrimitive.asInstanceOf[ITimerGuiLogic] + + val text = new SimpleTextboxNode + text.position = Point(20, 95) + text.size = Size(30, 10) + text.allowedcharacters = "0123456789.," + text.text = "%.2f".format(timerLogic.getTimerMax * 0.05) + text.textChangedDelegate = () => { + val time = Try(text.text.replaceAll(",", ".").toDouble) + gate.sendClientPacket(_.writeByte(3).writeShort((time.getOrElse(1d) * 20).toInt)) + } + addChild(text) + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + super.drawBack_Impl(mouse, rframe) + + val pos_state = position.add(13, 82) + GuiDraw.drawString( + "Interval:", + pos_state.x, pos_state.y, Colors.GREY.argb, false + ) + } +} From 602c3d4c96b8c80ab9a0bf4710e43045a4382d71 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 7 Jun 2025 23:18:11 +0200 Subject: [PATCH 09/21] spotless --- .../fabrication/FMPCircuitGate.scala | 14 +- .../projectred/fabrication/ICPrinter.scala | 22 ++- .../projectred/fabrication/ICWorkbench.scala | 7 +- .../fabrication/IntegratedCircuit.scala | 28 ++-- .../mrtjp/projectred/fabrication/Items.scala | 8 +- .../fabrication/RenderCircuit.scala | 39 +++-- .../projectred/fabrication/WorldCircuit.scala | 2 - .../circuitparts/ArrayGateICLogic.scala | 12 +- .../ArrayGateICLogicCrossing.scala | 2 +- .../circuitparts/ArrayGateICPart.scala | 6 +- .../circuitparts/CircuitPart.scala | 7 +- .../circuitparts/CircuitPartDefs.scala | 1 - .../circuitparts/ComboICGateLogic.scala | 9 +- .../circuitparts/ComboICGatePart.scala | 3 +- .../fabrication/circuitparts/GateICPart.scala | 12 +- .../circuitparts/ICGateDefinition.scala | 1 - .../circuitparts/ICGateRenderer.scala | 68 ++++++-- .../circuitparts/IWireICPart.scala | 58 +++---- .../circuitparts/RedstoneGateICPart.scala | 10 +- .../circuitparts/RedstoneICGateLogic.scala | 1 - .../circuitparts/SequentialGateICPart.scala | 20 ++- .../circuitparts/SequentialICGateLogic.scala | 15 +- .../circuitparts/TArrayGateICPart.scala | 6 +- .../circuitparts/TComplexGateICPart.scala | 6 +- .../circuitparts/TComplexICGateLogic.scala | 2 +- .../circuitparts/TExtraStateLogic.scala | 2 +- .../circuitparts/TICBundledAcquisitions.scala | 7 - .../circuitparts/TPropagatingICPart.scala | 12 +- .../circuitparts/TSimpleRSICGateLogic.scala | 1 - .../circuitparts/cells/BufferCell.scala | 8 +- .../circuitparts/cells/InvertCell.scala | 8 +- .../circuitparts/cells/NullCell.scala | 15 +- .../circuitparts/io/AnalogIO.scala | 5 +- .../circuitparts/io/BundledIO.scala | 3 +- .../circuitparts/io/IOGateICPart.scala | 14 +- .../circuitparts/io/IOICGateLogic.scala | 16 +- .../circuitparts/io/SimpleIO.scala | 3 +- .../circuitparts/io/TFreqIOICGateLogic.scala | 8 +- .../circuitparts/io/TIOCircuitPart.scala | 2 +- .../circuitparts/latches/SRLatch.scala | 58 +++---- .../circuitparts/latches/ToggleLatch.scala | 17 +- .../latches/TransparentLatch.scala | 7 +- .../circuitparts/misc/Counter.scala | 18 ++- .../circuitparts/misc/DecRandomizer.scala | 15 +- .../circuitparts/misc/Randomizer.scala | 7 +- .../circuitparts/misc/Synchronizer.scala | 17 +- .../circuitparts/primitives/AND.scala | 7 +- .../circuitparts/primitives/Buffer.scala | 7 +- .../circuitparts/primitives/Multiplexer.scala | 7 +- .../circuitparts/primitives/NAND.scala | 6 +- .../circuitparts/primitives/NOR.scala | 7 +- .../circuitparts/primitives/NOT.scala | 7 +- .../circuitparts/primitives/OR.scala | 7 +- .../circuitparts/primitives/XNOR.scala | 7 +- .../circuitparts/primitives/XOR.scala | 7 +- .../circuitparts/timing/Pulse.scala | 5 +- .../circuitparts/timing/Repeater.scala | 7 +- .../circuitparts/timing/Sequencer.scala | 17 +- .../circuitparts/timing/StateCell.scala | 18 ++- .../circuitparts/timing/Timer.scala | 37 +++-- .../circuitparts/wire/AlloyWire.scala | 3 +- .../circuitparts/wire/BundledCable.scala | 29 ++-- .../circuitparts/wire/Button.scala | 9 +- .../circuitparts/wire/InsulatedWire.scala | 11 +- .../fabrication/circuitparts/wire/Lever.scala | 12 +- .../circuitparts/wire/RedstoneTorch.scala | 9 +- .../circuitparts/wire/Redwire.scala | 27 ++-- .../fabrication/circuitparts/wire/Wire.scala | 10 +- .../projectred/fabrication/components.scala | 25 ++- .../fabrication/gui/CircuitGui.scala | 9 +- .../fabrication/gui/GuiICWorkbench.scala | 34 ++-- .../fabrication/gui/PrefboardRenderer.scala | 21 ++- .../gui/nodes/ConfigurationNode.scala | 6 +- .../fabrication/gui/nodes/ICToolsetNode.scala | 3 +- .../fabrication/gui/nodes/InfoNode.scala | 1 - .../fabrication/gui/nodes/OpPreviewNode.scala | 1 - .../fabrication/gui/nodes/PrefboardNode.scala | 87 ++++++---- .../gui/nodes/configuration/ColorPicker.scala | 24 ++- .../configuration/ConfigurationAnalogIO.scala | 25 ++- .../ConfigurationBundledIO.scala | 10 +- .../configuration/ConfigurationCounter.scala | 47 ++++-- .../ConfigurationRotationConfig.scala | 3 +- .../configuration/ConfigurationSimpleIO.scala | 7 +- .../configuration/ConfigurationTimer.scala | 17 +- .../fabrication/operations/CircuitOp.scala | 150 +++++++++++------- .../operations/CircuitOpDefs.scala | 4 - .../operations/CircuitOpErase.scala | 22 ++- .../fabrication/operations/ICPartOps.scala | 11 +- .../fabrication/operations/OpGate.scala | 35 +++- .../operations/SimplePlacementOp.scala | 35 ++-- .../fabrication/operations/WireOps.scala | 73 +++++++-- .../fabrication/wirepropagation.scala | 4 - 92 files changed, 989 insertions(+), 523 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala b/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala index d5bdb0c7c..feff24b18 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/FMPCircuitGate.scala @@ -10,8 +10,17 @@ import codechicken.lib.gui.GuiDraw import codechicken.lib.render.{CCRenderState, TextureUtils} import codechicken.lib.vec._ import mrtjp.core.math.MathLib -import mrtjp.projectred.fabrication.ItemICBlueprint.{getConnModes, getICName, hasICInside} -import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart.{Analog, Bundled, NoConn, Simple} +import mrtjp.projectred.fabrication.ItemICBlueprint.{ + getConnModes, + getICName, + hasICInside +} +import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart.{ + Analog, + Bundled, + NoConn, + Simple +} import mrtjp.projectred.integration import mrtjp.projectred.integration._ import mrtjp.projectred.transmission.BundledCommons._ @@ -20,7 +29,6 @@ import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import org.lwjgl.opengl.GL11 - class CircuitGatePart extends RedstoneGatePart with TBundledGatePart diff --git a/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala b/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala index 2291c23b1..8ea0128f0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ICPrinter.scala @@ -8,7 +8,11 @@ package mrtjp.projectred.fabrication import java.util.{ArrayList => JAList, List => JList} import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.gui.GuiDraw -import codechicken.lib.render.uv.{IconTransformation, MultiIconTransformation, UVTransformation} +import codechicken.lib.render.uv.{ + IconTransformation, + MultiIconTransformation, + UVTransformation +} import codechicken.lib.render.{CCModel, CCRenderState, TextureUtils} import codechicken.lib.vec._ import cpw.mods.fml.relauncher.{Side, SideOnly} @@ -23,7 +27,14 @@ import mrtjp.projectred.ProjectRedCore.log import mrtjp.projectred.core.PartDefs import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.circuitparts.GateICPart -import mrtjp.projectred.fabrication.circuitparts.wire.{AlloyWireICPart, BundledCableICPart, ButtonICPart, InsulatedWireICPart, LeverICPart, TorchICPart} +import mrtjp.projectred.fabrication.circuitparts.wire.{ + AlloyWireICPart, + BundledCableICPart, + ButtonICPart, + InsulatedWireICPart, + LeverICPart, + TorchICPart +} import mrtjp.projectred.integration.ComponentStore import mrtjp.projectred.transmission.WireDef import net.minecraft.client.renderer.RenderBlocks @@ -33,7 +44,12 @@ import net.minecraft.client.resources.I18n import net.minecraft.entity.player.EntityPlayer import net.minecraft.init.{Blocks, Items} import net.minecraft.item.ItemStack -import net.minecraft.item.crafting.{CraftingManager, IRecipe, ShapedRecipes, ShapelessRecipes} +import net.minecraft.item.crafting.{ + CraftingManager, + IRecipe, + ShapedRecipes, + ShapelessRecipes +} import net.minecraft.nbt.NBTTagCompound import net.minecraft.tileentity.TileEntity import net.minecraft.util.{IIcon, ResourceLocation} diff --git a/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala index 877e9a1ca..a17888f46 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/ICWorkbench.scala @@ -9,7 +9,12 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.packet.PacketCustom import codechicken.lib.render.uv.MultiIconTransformation import codechicken.lib.vec.{Rotation, Vector3} -import mrtjp.core.block.{InstancedBlock, InstancedBlockTile, TInstancedBlockRender, TTileOrient} +import mrtjp.core.block.{ + InstancedBlock, + InstancedBlockTile, + TInstancedBlockRender, + TTileOrient +} import mrtjp.core.gui.NodeContainer import mrtjp.core.render.TCubeMapRender import mrtjp.core.world.WorldLib diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index e98d7f5f5..fac9a0cb3 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -9,7 +9,11 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import mrtjp.core.vec.{Point, Rect, Size} import mrtjp.projectred.ProjectRedCore.log import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TClientNetCircuitPart, TErrorCircuitPart} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + TClientNetCircuitPart, + TErrorCircuitPart +} import mrtjp.projectred.fabrication.operations.CircuitOp import net.minecraft.nbt.{NBTTagCompound, NBTTagList} @@ -26,8 +30,8 @@ class IntegratedCircuit { private var scheduledTicks = MMap[(Int, Int), Long]() /** Mapped inputs and outputs of this IC. Outputs go to the world, inputs come - * in from the world. OOOO OOOO OOOO OOOO IIII IIII IIII IIII - */ + * in from the world. OOOO OOOO OOOO OOOO IIII IIII IIII IIII + */ val iostate = Array(0, 0, 0, 0) var outputChangedDelegate = { () => () } @@ -163,9 +167,9 @@ class IntegratedCircuit { } def sendClientPacket( - part: TClientNetCircuitPart, - writer: MCDataOutput => Unit - ) { + part: TClientNetCircuitPart, + writer: MCDataOutput => Unit + ) { val s = network.getICStreamOf(4).writeInt(part.x).writeInt(part.y) writer(s) } @@ -219,9 +223,15 @@ class IntegratedCircuit { def getPartsBoundingBox(): Rect = { val keys = parts.keys - val ((x2, y2), (x1, y1)) = if(keys.nonEmpty) { - (keys.reduce((p1, p2) => (math.max(p1._1, p2._1), math.max(p1._2, p2._2))), - keys.reduce((p1, p2) => (math.min(p1._1, p2._1), math.min(p1._2, p2._2)))) + val ((x2, y2), (x1, y1)) = if (keys.nonEmpty) { + ( + keys.reduce((p1, p2) => + (math.max(p1._1, p2._1), math.max(p1._2, p2._2)) + ), + keys.reduce((p1, p2) => + (math.min(p1._1, p2._1), math.min(p1._2, p2._2)) + ) + ) } else { ((1, 1), (0, 0)) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/Items.scala b/src/main/scala/mrtjp/projectred/fabrication/Items.scala index c94b31fa9..1b9e58e3a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/Items.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/Items.scala @@ -24,12 +24,14 @@ import net.minecraft.util.EnumChatFormatting._ import net.minecraft.util.{EnumChatFormatting, IIcon} import net.minecraft.world.World import net.minecraftforge.client.IItemRenderer -import net.minecraftforge.client.IItemRenderer.{ItemRenderType, ItemRendererHelper} +import net.minecraftforge.client.IItemRenderer.{ + ItemRenderType, + ItemRendererHelper +} import org.lwjgl.opengl.GL11._ import java.util.{List => JList} - class ItemICBlueprint extends ItemMap // extend ItemMap so minecraft will handle the FP render for us { @@ -237,7 +239,7 @@ object ItemRenderICBlueprint extends IItemRenderer { 8.0d / (boundingBox.width.toDouble + 1), 8.0d / (boundingBox.height.toDouble + 1) ) - RenderCircuit.renderCircuitOrtho(ic,scale, boundingBox.origin.vectorize) + RenderCircuit.renderCircuitOrtho(ic, scale, boundingBox.origin.vectorize) val name = ic.name diff --git a/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala index b2bd5bb28..d30d7a40c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/RenderCircuit.scala @@ -11,12 +11,17 @@ import codechicken.lib.vec._ import mrtjp.core.color.Colors import mrtjp.core.vec.{Point, Size, Vec2} import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.ICComponentStore.{dynamicIdx, faceModels, finishRender, orthoPartT, prepairRender} +import mrtjp.projectred.fabrication.ICComponentStore.{ + dynamicIdx, + faceModels, + finishRender, + orthoPartT, + prepairRender +} import mrtjp.projectred.fabrication.gui.PrefboardRenderer import net.minecraft.client.Minecraft import net.minecraft.client.renderer.texture.IIconRegister - object RenderCircuit { val BASE_SCALE = 16 @@ -25,17 +30,23 @@ object RenderCircuit { } def renderOrtho( - circuit: IntegratedCircuit, - boardSize: Size, - gridScale: Double, - gridTranslation: Vec2 + circuit: IntegratedCircuit, + boardSize: Size, + gridScale: Double, + gridTranslation: Vec2 ) { PrefboardRenderer.renderOrtho(boardSize, gridScale, gridTranslation) renderCircuitOrtho(circuit, gridScale, gridTranslation) } - def renderErrors(circuit: IntegratedCircuit, gridScale: Double, gridTranslation: Vec2): Unit = { - if(Minecraft.getMinecraft.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty) { + def renderErrors( + circuit: IntegratedCircuit, + gridScale: Double, + gridTranslation: Vec2 + ): Unit = { + if ( + Minecraft.getMinecraft.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty + ) { prepairRender() PRResources.guiPrototyper.bind() for ((Point(x, y), (_, c)) <- circuit.errors) { @@ -53,12 +64,20 @@ object RenderCircuit { } } - def renderCircuitOrtho(circuit: IntegratedCircuit, scale: Double, gridTranslation: Vec2): Unit = { + def renderCircuitOrtho( + circuit: IntegratedCircuit, + scale: Double, + gridTranslation: Vec2 + ): Unit = { val t = ICComponentStore.orthoGridT(BASE_SCALE, BASE_SCALE) for (((x, y), part) <- circuit.parts) { val tlist = new TransformationList( new Scale(scale, 1, scale), - new Translation((x - gridTranslation.dx) * scale, 0, (y - gridTranslation.dy) * scale), + new Translation( + (x - gridTranslation.dx) * scale, + 0, + (y - gridTranslation.dy) * scale + ), t ) part.renderDynamic(tlist, true, 1f) diff --git a/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala index e89ba097d..5ea78fe9a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/WorldCircuit.scala @@ -30,7 +30,6 @@ trait WorldCircuit { def markSave() } - object DummyMCIO extends MCDataOutput { override def writeVarInt(i: Int) = this override def writeCoord(x: Int, y: Int, z: Int) = this @@ -126,4 +125,3 @@ trait NetWorldCircuit extends WorldCircuit { } } } - diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala index fe7a0a966..33a334ad3 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogic.scala @@ -5,14 +5,18 @@ */ package mrtjp.projectred.fabrication.circuitparts -import mrtjp.projectred.fabrication.circuitparts.cells.{BufferCell, InvertCell, NullCell} +import mrtjp.projectred.fabrication.circuitparts.cells.{ + BufferCell, + InvertCell, + NullCell +} object ArrayGateICLogic { import ICGateDefinition._ def create(gate: ArrayGateICPart, subID: Int) = subID match { - case NullCell.ordinal => new NullCell(gate) + case NullCell.ordinal => new NullCell(gate) case InvertCell.ordinal => new InvertCell(gate) case BufferCell.ordinal => new BufferCell(gate) case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) @@ -20,6 +24,6 @@ object ArrayGateICLogic { } abstract class ArrayGateICLogic(val gate: ArrayGateICPart) - extends RedstoneICGateLogic[ArrayGateICPart] + extends RedstoneICGateLogic[ArrayGateICPart] with TArrayICGateLogic[ArrayGateICPart] - with TComplexICGateLogic[ArrayGateICPart] \ No newline at end of file + with TComplexICGateLogic[ArrayGateICPart] diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala index 5bc085a64..7bc7e0cb0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICLogicCrossing.scala @@ -10,7 +10,7 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import net.minecraft.nbt.NBTTagCompound abstract class ArrayGateICLogicCrossing(gate: ArrayGateICPart) - extends ArrayGateICLogic(gate) { + extends ArrayGateICLogic(gate) { var signal1: Byte = 0 var signal2: Byte = 0 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala index 919b0321b..b9dae7491 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ArrayGateICPart.scala @@ -8,9 +8,8 @@ package mrtjp.projectred.fabrication.circuitparts import mrtjp.projectred.fabrication.gui.nodes.configuration.ConfigurationRotation import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} - class ArrayGateICPart - extends RedstoneGateICPart + extends RedstoneGateICPart with TComplexGateICPart with TArrayGateICPart with TConfigurable { @@ -24,5 +23,6 @@ class ArrayGateICPart override def getPartType = CircuitPartDefs.ArrayGate - override def createConfigurationNode: ConfigurationNode = new ConfigurationRotation(this) + override def createConfigurationNode: ConfigurationNode = + new ConfigurationRotation(this) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala index f538f99cd..e9db03410 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala @@ -16,9 +16,8 @@ object CircuitPart { def createPart(id: Int) = CircuitPartDefs(id).createPart } -/** - * Base Class for all Gates, that are displayed in the IC Workbench - */ +/** Base Class for all Gates, that are displayed in the IC Workbench + */ abstract class CircuitPart { var world: IntegratedCircuit = null var loc: (Int, Int) = null @@ -97,4 +96,4 @@ abstract class CircuitPart { @SideOnly(Side.CLIENT) def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) {} -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala index dc507671d..13214f0b5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPartDefs.scala @@ -9,7 +9,6 @@ import mrtjp.core.util.Enum import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart import mrtjp.projectred.fabrication.circuitparts.wire._ - object CircuitPartDefs extends Enum { type EnumVal = CircuitPartDef diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala index e6c61472c..45d2d6143 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGateLogic.scala @@ -6,12 +6,15 @@ package mrtjp.projectred.fabrication.circuitparts import mrtjp.projectred.fabrication.circuitparts.latches.TransparentLatch -import mrtjp.projectred.fabrication.circuitparts.misc.{DecRandomizer, Randomizer} +import mrtjp.projectred.fabrication.circuitparts.misc.{ + DecRandomizer, + Randomizer +} import mrtjp.projectred.fabrication.circuitparts.primitives._ import mrtjp.projectred.fabrication.circuitparts.timing.Repeater abstract class ComboICGateLogic - extends RedstoneICGateLogic[ComboICGatePart] + extends RedstoneICGateLogic[ComboICGatePart] with TSimpleRSICGateLogic[ComboICGatePart] { override def cycleShape(gate: ComboICGatePart) = { val oldShape = gate.shape @@ -60,4 +63,4 @@ object ComboICGateLogic { instances(ICGateDefinition.TransparentLatch.ordinal) = TransparentLatch instances(ICGateDefinition.DecRandomizer.ordinal) = DecRandomizer } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala index 31ade76f4..f554a2fbb 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ComboICGatePart.scala @@ -15,5 +15,6 @@ class ComboICGatePart extends RedstoneGateICPart with TConfigurable { override def getPartType = CircuitPartDefs.SimpleGate - override def createConfigurationNode: ConfigurationNode = new ConfigurationRotationConfig(this) + override def createConfigurationNode: ConfigurationNode = + new ConfigurationRotationConfig(this) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala index 18e97f08f..179c410c5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala @@ -12,7 +12,7 @@ import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound abstract class GateICPart - extends CircuitPart + extends CircuitPart with TConnectableICPart with TICOrient with TClientNetCircuitPart { @@ -115,11 +115,11 @@ abstract class GateICPart def processScheduledDigital() { while (schedDigital && iter < 3) // recursion control - { - schedDigital = false - iter += 1 - scheduledTick() - } + { + schedDigital = false + iter += 1 + scheduledTick() + } } def onChange() { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala index 00f3ac112..5bb7d4769 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala @@ -8,7 +8,6 @@ package mrtjp.projectred.fabrication.circuitparts import mrtjp.core.util.Enum import mrtjp.projectred.integration.GateDefinition.GateDef - object ICGateDefinition extends Enum { type EnumVal = ICGateDef diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala index 7c0829dfd..08a06adee 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateRenderer.scala @@ -7,16 +7,51 @@ package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.vec.Transformation import mrtjp.projectred.fabrication.ICComponentModel -import mrtjp.projectred.fabrication.ICComponentStore.{finishRender, prepairRender} -import mrtjp.projectred.fabrication.circuitparts.cells.{RenderBufferCell, RenderInvertCell, RenderNullCell} -import mrtjp.projectred.fabrication.circuitparts.io.{RenderAnalogIO, RenderBundledIO, RenderSimpleIO} -import mrtjp.projectred.fabrication.circuitparts.latches.{RenderSRLatch, RenderToggleLatch, RenderTransparentLatch} -import mrtjp.projectred.fabrication.circuitparts.misc.{RenderCounter, RenderDecRandomizer, RenderRandomizer, RenderSynchronizer} -import mrtjp.projectred.fabrication.circuitparts.primitives.{RenderAND, RenderBuffer, RenderMultiplexer, RenderNAND, RenderNOR, RenderNOT, RenderOR, RenderXNOR, RenderXOR} -import mrtjp.projectred.fabrication.circuitparts.timing.{RenderPulse, RenderRepeater, RenderSequencer, RenderStateCell, RenderTimer} +import mrtjp.projectred.fabrication.ICComponentStore.{ + finishRender, + prepairRender +} +import mrtjp.projectred.fabrication.circuitparts.cells.{ + RenderBufferCell, + RenderInvertCell, + RenderNullCell +} +import mrtjp.projectred.fabrication.circuitparts.io.{ + RenderAnalogIO, + RenderBundledIO, + RenderSimpleIO +} +import mrtjp.projectred.fabrication.circuitparts.latches.{ + RenderSRLatch, + RenderToggleLatch, + RenderTransparentLatch +} +import mrtjp.projectred.fabrication.circuitparts.misc.{ + RenderCounter, + RenderDecRandomizer, + RenderRandomizer, + RenderSynchronizer +} +import mrtjp.projectred.fabrication.circuitparts.primitives.{ + RenderAND, + RenderBuffer, + RenderMultiplexer, + RenderNAND, + RenderNOR, + RenderNOT, + RenderOR, + RenderXNOR, + RenderXOR +} +import mrtjp.projectred.fabrication.circuitparts.timing.{ + RenderPulse, + RenderRepeater, + RenderSequencer, + RenderStateCell, + RenderTimer +} import net.minecraft.client.renderer.texture.IIconRegister - object ICGateRenderer { var renderers = buildRenders() @@ -53,17 +88,21 @@ object ICGateRenderer { def registerIcons(reg: IIconRegister) {} def renderDynamic( - gate: GateICPart, - t: Transformation, - ortho: Boolean, - frame: Float - ) { + gate: GateICPart, + t: Transformation, + ortho: Boolean, + frame: Float + ) { val r = renderers(gate.subID).asInstanceOf[ICGateRenderer[GateICPart]] r.prepareDynamic(gate, frame) r.renderDynamic(gate.rotationT `with` t, ortho) } - def renderWithConfiguration(configuration: Int, t: Transformation, id: Int): Unit = { + def renderWithConfiguration( + configuration: Int, + t: Transformation, + id: Int + ): Unit = { val r = renderers(id) r.prepareStatic(configuration) r.renderDynamic(t, true) @@ -76,7 +115,6 @@ object ICGateRenderer { } } - abstract class ICGateRenderer[T <: GateICPart] { var reflect = false diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala index b483f0852..7f5442fbb 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/IWireICPart.scala @@ -10,57 +10,57 @@ import mrtjp.projectred.fabrication.IntegratedCircuit object IWireICPart { /** Standard operation procedure, no special propogation rules. The propogator - * signal may not have increased. - */ + * signal may not have increased. + */ final val RISING = 0 /** Used when the propogator signal dropped (to 0). Propagation should - * continue until a rising or constant change is encountered at which point a - * RISING should be propogated back to this wire. - */ + * continue until a rising or constant change is encountered at which point a + * RISING should be propogated back to this wire. + */ final val DROPPING = 1 /** Used when a wire's connection state has changed. Even if the signal - * remains the same, new connections still need to be recalculated - */ + * remains the same, new connections still need to be recalculated + */ final val FORCE = 2 /** Used when the propogator did not change signal, but a new connection may - * have been established and signal needs recalculating - */ + * have been established and signal needs recalculating + */ final val FORCED = 3 } trait IWireICPart { /** Recalculates the signal of this wire and calls the appropriate propogation - * methods in WirePropagator. DO NOT CALL THIS YOURSELF. Use - * WirePropagator.propagateTo - * - * @param prev - * The part which called this propogation (should be connected) may be - * null. - * @param mode - * One of RISING, DROPPING, FORCE and FORCED specified above - */ + * methods in WirePropagator. DO NOT CALL THIS YOURSELF. Use + * WirePropagator.propagateTo + * + * @param prev + * The part which called this propogation (should be connected) may be + * null. + * @param mode + * One of RISING, DROPPING, FORCE and FORCED specified above + */ def updateAndPropagate(prev: CircuitPart, mode: Int) /** Called at the end of a propogation run for partChanged events. Marks the - * end of a state change for this part. - */ + * end of a state change for this part. + */ def onSignalUpdate() /** @param r - * The rotation of this part to test for wire connection. - * @return - * true if the specified side of this block is connected to, for example, a - * 'wire' where signal should decrease by one. - */ + * The rotation of this part to test for wire connection. + * @return + * true if the specified side of this block is connected to, for example, a + * 'wire' where signal should decrease by one. + */ def diminishOnSide(r: Int): Boolean /** The world in which this part resides - * - * @return - */ + * + * @return + */ def world: IntegratedCircuit -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala index 8e65d8748..a38b603ad 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneGateICPart.scala @@ -10,13 +10,13 @@ import mrtjp.projectred.fabrication.circuitparts.wire.IICRedwireEmitter import net.minecraft.nbt.NBTTagCompound abstract class RedstoneGateICPart - extends GateICPart + extends GateICPart with TICRSAcquisitions with TPoweredCircuitPart { /** Mapped inputs and outputs of the gate. OOOO IIII High nybble is output. - * Low nybble is input - */ + * Low nybble is input + */ private var gateState: Byte = 0 def state = gateState & 0xff @@ -78,8 +78,8 @@ abstract class RedstoneGateICPart def getRedstoneInput(r: Int) = calcSignal(toAbsolute(r)) override def resolveSignal(part: Any, r: Int) = part match { - case re: IICRedwireEmitter => re.getRedwireSignal(r) + case re: IICRedwireEmitter => re.getRedwireSignal(r) case ip: TPoweredCircuitPart => ip.rsOutputLevel(r) - case _ => 0 + case _ => 0 } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala index 35cbce2a2..9dc5b93d8 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/RedstoneICGateLogic.scala @@ -7,7 +7,6 @@ package mrtjp.projectred.fabrication.circuitparts import mrtjp.projectred.fabrication.circuitparts.wire.IICRedwireEmitter - abstract class RedstoneICGateLogic[T <: RedstoneGateICPart] extends ICGateLogic[T] { override def canConnectTo(gate: T, part: CircuitPart, r: Int) = part match { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala index 853011252..0d6611fef 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialGateICPart.scala @@ -8,13 +8,23 @@ package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.MCDataInput import mrtjp.projectred.ProjectRedCore.log import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, ToggleLatch} -import mrtjp.projectred.fabrication.circuitparts.misc.{ICounterGuiLogic, Synchronizer} +import mrtjp.projectred.fabrication.circuitparts.misc.{ + ICounterGuiLogic, + Synchronizer +} import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic -import mrtjp.projectred.fabrication.gui.nodes.configuration.{ConfigurationCounter, ConfigurationRotation, ConfigurationRotationConfig, ConfigurationTimer} +import mrtjp.projectred.fabrication.gui.nodes.configuration.{ + ConfigurationCounter, + ConfigurationRotation, + ConfigurationRotationConfig, + ConfigurationTimer +} import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} - -class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart with TConfigurable { +class SequentialGateICPart + extends RedstoneGateICPart + with TComplexGateICPart + with TConfigurable { var logic: SequentialICGateLogic = null override def assertLogic() { @@ -59,7 +69,7 @@ class SequentialGateICPart extends RedstoneGateICPart with TComplexGateICPart wi override def createConfigurationNode: ConfigurationNode = { getLogicPrimitive match { case _: ICounterGuiLogic => new ConfigurationCounter(this) - case _: ITimerGuiLogic => new ConfigurationTimer(this) + case _: ITimerGuiLogic => new ConfigurationTimer(this) case _ => new ConfigurationRotationConfig(this) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala index d82a4496c..656fffacb 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/SequentialICGateLogic.scala @@ -9,20 +9,19 @@ import mrtjp.projectred.fabrication.circuitparts.latches._ import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, Synchronizer} import mrtjp.projectred.fabrication.circuitparts.timing._ - abstract class SequentialICGateLogic(val gate: SequentialGateICPart) - extends RedstoneICGateLogic[SequentialGateICPart] + extends RedstoneICGateLogic[SequentialGateICPart] with TComplexICGateLogic[SequentialGateICPart] object SequentialICGateLogic { def create(gate: SequentialGateICPart, subID: Int) = subID match { - case ICGateDefinition.SRLatch.ordinal => new SRLatch(gate) - case ICGateDefinition.ToggleLatch.ordinal => new ToggleLatch(gate) - case ICGateDefinition.Timer.ordinal => new Timer(gate) - case ICGateDefinition.Sequencer.ordinal => new Sequencer(gate) - case ICGateDefinition.Counter.ordinal => new Counter(gate) - case ICGateDefinition.StateCell.ordinal => new StateCell(gate) + case ICGateDefinition.SRLatch.ordinal => new SRLatch(gate) + case ICGateDefinition.ToggleLatch.ordinal => new ToggleLatch(gate) + case ICGateDefinition.Timer.ordinal => new Timer(gate) + case ICGateDefinition.Sequencer.ordinal => new Sequencer(gate) + case ICGateDefinition.Counter.ordinal => new Counter(gate) + case ICGateDefinition.StateCell.ordinal => new StateCell(gate) case ICGateDefinition.Synchronizer.ordinal => new Synchronizer(gate) case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala index fa8ad7a91..5665e0b62 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TArrayGateICPart.scala @@ -11,7 +11,7 @@ import mrtjp.projectred.fabrication.circuitparts.wire.IRedwireICPart import mrtjp.projectred.transmission.IWirePart trait TArrayGateICPart - extends RedstoneGateICPart + extends RedstoneGateICPart with IRedwireICPart with TRSPropagatingICPart { def getLogicArray = getLogic[TArrayICGateLogic[TArrayGateICPart]] @@ -48,8 +48,8 @@ trait TArrayGateICPart val there = Point(part.x, part.y) there - here match { case Point(0, -1) => 1 << 0 - case Point(1, 0) => 1 << 1 - case Point(0, 1) => 1 << 2 + case Point(1, 0) => 1 << 1 + case Point(0, 1) => 1 << 2 case Point(-1, 0) => 1 << 3 case _ => throw new RuntimeException( diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala index 17197cf74..003f3c957 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexGateICPart.scala @@ -42,7 +42,11 @@ trait TComplexGateICPart extends GateICPart { case _ => super.read(packet, key) } - abstract override def preparePlacement(rotation: Int, configuration: Int, meta: Int) { + abstract override def preparePlacement( + rotation: Int, + configuration: Int, + meta: Int + ) { super.preparePlacement(rotation, configuration, meta) assertLogic() } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala index 1d2ee7030..852a19403 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TComplexICGateLogic.scala @@ -18,6 +18,6 @@ trait TComplexICGateLogic[T <: TComplexGateICPart] extends ICGateLogic[T] { def writeDesc(packet: MCDataOutput) {} /** Allocated keys > 10 - */ + */ def read(packet: MCDataInput, key: Int) {} } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala index 0b7288373..ca2853843 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TExtraStateLogic.scala @@ -41,7 +41,7 @@ trait TExtraStateLogic extends SequentialICGateLogic { abstract override def read(packet: MCDataInput, key: Int) = key match { case 11 => lState2 = packet.readByte() - case _ => super.read(packet, key) + case _ => super.read(packet, key) } def sendState2Update() { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala index 9f5658084..9e0669cf5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TICBundledAcquisitions.scala @@ -5,16 +5,9 @@ */ package mrtjp.projectred.fabrication.circuitparts - trait TICBundledAcquisitions extends TICAcquisitions { def calcArray(r: Int): Array[Byte] = resolveArray(getStraight(r), rotFromStraight(r)) def resolveArray(part: Any, r: Int): Array[Byte] } - - - - - - diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala index caff02c03..4a64936fd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TPropagatingICPart.scala @@ -10,7 +10,7 @@ import IWireICPart.FORCED import mrtjp.projectred.fabrication.ICPropagator trait TPropagatingICPart - extends CircuitPart + extends CircuitPart with TConnectableICPart with IWireICPart { var propagationMask = 0xf @@ -28,11 +28,11 @@ trait TPropagatingICPart def propagateOther(mode: Int) {} def propagateExternal( - to: CircuitPart, - at: Point, - from: CircuitPart, - mode: Int - ) { + to: CircuitPart, + at: Point, + from: CircuitPart, + mode: Int + ) { if (to != null) { if (to == from) return if (propagateTo(to, mode)) return diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala index 90254792d..f62acd62f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/TSimpleRSICGateLogic.scala @@ -7,7 +7,6 @@ package mrtjp.projectred.fabrication.circuitparts import cpw.mods.fml.relauncher.{Side, SideOnly} - trait TSimpleRSICGateLogic[T <: RedstoneGateICPart] extends RedstoneICGateLogic[T] { def getDelay(shape: Int) = 0 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala index 0c1e2fdd1..472596073 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/BufferCell.scala @@ -7,14 +7,16 @@ package mrtjp.projectred.fabrication.circuitparts.cells import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} - +import mrtjp.projectred.fabrication.circuitparts.{ + ArrayGateICLogicCrossing, + ArrayGateICPart, + ICGateRenderer +} class BufferCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { override def powerUp = (gate.state & 2) == 0 } - class RenderBufferCell extends ICGateRenderer[ArrayGateICPart] { val wires = generateWireModels("BUFFCELL", 2) val torches = diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala index 49667a274..a6c0daf08 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/InvertCell.scala @@ -7,14 +7,16 @@ package mrtjp.projectred.fabrication.circuitparts.cells import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} - +import mrtjp.projectred.fabrication.circuitparts.{ + ArrayGateICLogicCrossing, + ArrayGateICPart, + ICGateRenderer +} class InvertCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { override def powerUp = (gate.state & 2) != 0 } - class RenderInvertCell extends ICGateRenderer[ArrayGateICPart] { val wires = generateWireModels("INVCELL", 1) val torch = new RedstoneTorchModel(8, 8) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala index 9e31e49ae..325867403 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/cells/NullCell.scala @@ -5,15 +5,22 @@ */ package mrtjp.projectred.fabrication.circuitparts.cells -import mrtjp.projectred.fabrication.circuitparts.{ArrayGateICLogicCrossing, ArrayGateICPart, ICGateRenderer} -import mrtjp.projectred.fabrication.{BaseComponentModel, CellStandModel, CellTopWireModel, NullCellBottomWireModel} - +import mrtjp.projectred.fabrication.circuitparts.{ + ArrayGateICLogicCrossing, + ArrayGateICPart, + ICGateRenderer +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + CellStandModel, + CellTopWireModel, + NullCellBottomWireModel +} class NullCell(gate: ArrayGateICPart) extends ArrayGateICLogicCrossing(gate) { override def powerUp = false } - class RenderNullCell extends ICGateRenderer[ArrayGateICPart] { val top = new CellTopWireModel val bottom = new NullCellBottomWireModel diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala index 5fd1c4f72..b23c20f05 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/AnalogIO.scala @@ -7,9 +7,8 @@ package mrtjp.projectred.fabrication.circuitparts.io import mrtjp.projectred.fabrication.ICComponentStore.signalColour - class AnalogIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) + extends IOICGateLogic(gate) with TFreqIOICGateLogic with TRSIOICGateLogic { override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Analog @@ -27,4 +26,4 @@ class RenderAnalogIO extends RenderIO { override def dynColour(gate: IOGateICPart) = signalColour( (gate.getLogic[AnalogIOICGateLogic].freq * 17).toByte ) -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala index 8133a54d9..141cd5278 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/BundledIO.scala @@ -7,9 +7,8 @@ package mrtjp.projectred.fabrication.circuitparts.io import mrtjp.core.color.Colors - class BundledIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) + extends IOICGateLogic(gate) with TFreqIOICGateLogic { override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Bundled diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala index 883fd1535..fb704a64d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala @@ -6,12 +6,20 @@ package mrtjp.projectred.fabrication.circuitparts.io import codechicken.lib.data.MCDataInput -import mrtjp.projectred.fabrication.circuitparts.{CircuitPartDefs, RedstoneGateICPart, TComplexGateICPart} -import mrtjp.projectred.fabrication.gui.nodes.configuration.{ConfigurationAnalogIO, ConfigurationBundledIO, ConfigurationSimpleIO} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPartDefs, + RedstoneGateICPart, + TComplexGateICPart +} +import mrtjp.projectred.fabrication.gui.nodes.configuration.{ + ConfigurationAnalogIO, + ConfigurationBundledIO, + ConfigurationSimpleIO +} import mrtjp.projectred.fabrication.gui.nodes.{ConfigurationNode, TConfigurable} class IOGateICPart - extends RedstoneGateICPart + extends RedstoneGateICPart with TIOCircuitPart with TComplexGateICPart with TConfigurable { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala index 470173206..ae6e1c9c5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOICGateLogic.scala @@ -6,13 +6,17 @@ package mrtjp.projectred.fabrication.circuitparts.io import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.fabrication.circuitparts.{ICGateDefinition, RedstoneICGateLogic, TComplexICGateLogic, TICOrient} - +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateDefinition, + RedstoneICGateLogic, + TComplexICGateLogic, + TICOrient +} object IOICGateLogic { def create(gate: IOGateICPart, subID: Int) = subID match { - case ICGateDefinition.IOSimple.ordinal => new SimpleIOICGateLogic(gate) - case ICGateDefinition.IOAnalog.ordinal => new AnalogIOICGateLogic(gate) + case ICGateDefinition.IOSimple.ordinal => new SimpleIOICGateLogic(gate) + case ICGateDefinition.IOAnalog.ordinal => new AnalogIOICGateLogic(gate) case ICGateDefinition.IOBundled.ordinal => new BundledIOICGateLogic(gate) case _ => throw new IllegalArgumentException("Invalid gate subID: " + subID) } @@ -23,7 +27,7 @@ object IOICGateLogic { } abstract class IOICGateLogic(val gate: IOGateICPart) - extends RedstoneICGateLogic[IOGateICPart] + extends RedstoneICGateLogic[IOGateICPart] with TComplexICGateLogic[IOGateICPart] { import TIOCircuitPart._ @@ -113,4 +117,4 @@ abstract class IOICGateLogic(val gate: IOGateICPart) toggleWorldInput() gate.world.onInputChanged(1 << gate.rotation) } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala index bf6496076..f027ca104 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/SimpleIO.scala @@ -7,9 +7,8 @@ package mrtjp.projectred.fabrication.circuitparts.io import mrtjp.projectred.fabrication.ICComponentStore.signalColour - class SimpleIOICGateLogic(gate: IOGateICPart) - extends IOICGateLogic(gate) + extends IOICGateLogic(gate) with TRSIOICGateLogic { override def getConnMode(gate: IOGateICPart) = TIOCircuitPart.Simple diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala index 488d91bcd..d23748508 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala @@ -33,7 +33,7 @@ trait TFreqIOICGateLogic extends IOICGateLogic { override def read(in: MCDataInput, key: Int) = key match { case 12 => freq = in.readUByte() - case _ => super.read(in, key) + case _ => super.read(in, key) } def sendFreqUpdate() { @@ -67,9 +67,9 @@ trait TFreqIOICGateLogic extends IOICGateLogic { override def setWorldOutput(state: Boolean) { val s = ((gate.world.iostate(gate.rotation) >>> 16) & ~(1 << freq)) | (if (state) - 1 - else - 0) << freq + 1 + else + 0) << freq gate.world.setOutput(gate.rotation, s) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala index 5cb8dc06b..fe05033aa 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TIOCircuitPart.scala @@ -27,4 +27,4 @@ trait TIOCircuitPart { def getIOMode: Int def getConnMode: Int -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala index 4eb17a07d..d9ce7055a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/SRLatch.scala @@ -7,7 +7,12 @@ package mrtjp.projectred.fabrication.circuitparts.latches import mrtjp.projectred.core.TFaceOrient.{flipMaskZ, shiftMask} import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic, + TExtraStateLogic +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} object SRLatch { @@ -17,7 +22,7 @@ object SRLatch { } class SRLatch(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with TExtraStateLogic { override def outputMask(shape: Int) = if ((shape >> 1) == 0) 0xf else 5 override def inputMask(shape: Int) = 0xa @@ -47,12 +52,12 @@ class SRLatch(gate: SequentialGateICPart) if ( stateInput != 0xa && newInput != 0 && newInput != stateInput ) // state needs changing - { - gate.setState(newInput) - setState2(newInput) - gate.onOutputChange(oldOutput) // always going low - gate.scheduleTick(0) - } else { + { + gate.setState(newInput) + setState2(newInput) + gate.onOutputChange(oldOutput) // always going low + gate.scheduleTick(0) + } else { gate.setState(oldOutput << 4 | newInput) gate.onInputChange() } @@ -74,28 +79,28 @@ class SRLatch(gate: SequentialGateICPart) var stateInput = state2 if ((gate.shape & 1) != 0) // reverse - { - input = flipMaskZ(input) - stateInput = flipMaskZ(stateInput) - } + { + input = flipMaskZ(input) + stateInput = flipMaskZ(stateInput) + } if (stateInput == 0xa) // disabled - { - if (input == 0xa) { - gate.scheduleTick(0) - return 0 + { + if (input == 0xa) { + gate.scheduleTick(0) + return 0 + } + + stateInput = + if (input == 0) + if (gate.world.network.getWorld.rand.nextBoolean()) 2 else 8 + else input + + setState2( + if ((gate.shape & 1) != 0) flipMaskZ(stateInput) else stateInput + ) } - stateInput = - if (input == 0) - if (gate.world.network.getWorld.rand.nextBoolean()) 2 else 8 - else input - - setState2( - if ((gate.shape & 1) != 0) flipMaskZ(stateInput) else stateInput - ) - } - var output = shiftMask(stateInput, 1) if ((gate.shape & 2) == 0) output |= stateInput if ((gate.shape & 1) != 0) output = flipMaskZ(output) // reverse @@ -103,7 +108,6 @@ class SRLatch(gate: SequentialGateICPart) } } - class RenderSRLatch extends ICGateRenderer[SequentialGateICPart] { val wires1 = generateWireModels("RSLATCH", 2) val wires2 = generateWireModels("RSLATCH2", 4) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala index 14b70b24a..69ad4b9e8 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/ToggleLatch.scala @@ -6,12 +6,20 @@ package mrtjp.projectred.fabrication.circuitparts.latches import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, LeverModel, RedstoneTorchModel} - +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic, + TExtraStateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + LeverModel, + RedstoneTorchModel +} class ToggleLatch(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with TExtraStateLogic { override def outputMask(shape: Int) = 5 override def inputMask(shape: Int) = 0xa @@ -56,7 +64,6 @@ class ToggleLatch(gate: SequentialGateICPart) } } - class RenderToggleLatch extends ICGateRenderer[SequentialGateICPart] { val wires = generateWireModels("TOGLATCH", 2) val torches = Seq(new RedstoneTorchModel(4, 4), new RedstoneTorchModel(4, 12)) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala index b47107648..caccb6c4b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/latches/TransparentLatch.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.latches import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object TransparentLatch extends ComboICGateLogic { override def outputMask(shape: Int) = if (shape == 0) 3 else 9 override def inputMask(shape: Int) = if (shape == 0) 0xc else 6 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala index b6b6db8e0..21c61d2dc 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Counter.scala @@ -10,11 +10,19 @@ import codechicken.lib.math.MathHelper import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.TFaceOrient.flipMaskZ import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import mrtjp.projectred.fabrication.circuitparts.{ + GateICPart, + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + PointerModel, + RedstoneTorchModel +} import net.minecraft.nbt.NBTTagCompound - trait ICounterGuiLogic { def getCounterMax: Int def setCounterMax(gate: GateICPart, i: Int) @@ -35,9 +43,8 @@ object Counter { } } - class Counter(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with ICounterGuiLogic { var value = 0 var max = 10 @@ -169,7 +176,6 @@ class Counter(gate: SequentialGateICPart) } } - class RenderCounter extends ICGateRenderer[SequentialGateICPart] { val wires = generateWireModels("COUNT", 2) val torches = Seq( diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala index b80176f31..94f2d4b06 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/DecRandomizer.scala @@ -6,12 +6,20 @@ package mrtjp.projectred.fabrication.circuitparts.misc import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} -import mrtjp.projectred.fabrication.{BaseComponentModel, RedChipModel, RedstoneTorchModel, YellowChipModel} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + RedChipModel, + RedstoneTorchModel, + YellowChipModel +} import java.util.Random - object DecRandomizer extends ComboICGateLogic { val rand = new Random @@ -34,7 +42,6 @@ object DecRandomizer extends ComboICGateLogic { } } - class RenderDecRandomizer extends ICGateRenderer[ComboICGatePart] { val wires = generateWireModels("DECRAND", 6) val chips = Seq( diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala index 94810240e..845448d6c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Randomizer.scala @@ -7,12 +7,15 @@ package mrtjp.projectred.fabrication.circuitparts.misc import mrtjp.projectred.core.TFaceOrient import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, YellowChipModel} import java.util.Random - object Randomizer extends ComboICGateLogic { val rand = new Random diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala index eaf2f5ad0..4c3b5adbf 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/misc/Synchronizer.scala @@ -7,12 +7,20 @@ package mrtjp.projectred.fabrication.circuitparts.misc import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, RedChipModel, RedstoneTorchModel} - +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic, + TExtraStateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + RedChipModel, + RedstoneTorchModel +} class Synchronizer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with TExtraStateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = 14 @@ -67,7 +75,6 @@ class Synchronizer(gate: SequentialGateICPart) } } - class RenderSynchronizer extends ICGateRenderer[SequentialGateICPart] { val wires = generateWireModels("SYNC", 6) val torch = new RedstoneTorchModel(8, 3) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala index 1a78c96c6..8cd432712 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/AND.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object AND extends ComboICGateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = ~shape << 1 & 0xe diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala index a0dd3167b..80b06e8c7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Buffer.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object Buffer extends ComboICGateLogic { override def outputMask(shape: Int) = ~((shape & 1) << 1 | (shape & 2) << 2) & 0xb diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala index b2e29fdb0..0b600f66c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/Multiplexer.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object Multiplexer extends ComboICGateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = 0xe diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala index b69b24f04..5ca8d24d1 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NAND.scala @@ -6,7 +6,11 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} object NAND extends ComboICGateLogic { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala index 48344b251..b7ff9ee57 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOR.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object NOR extends ComboICGateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = ~shape << 1 & 0xe diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala index 2440a979b..fcdbec146 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/NOT.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object NOT extends ComboICGateLogic { override def outputMask(shape: Int) = ~((shape & 1) << 1 | (shape & 2) >> 1 | (shape & 4) << 1) & 0xb diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala index 1118fe3d1..f2c978148 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/OR.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object OR extends ComboICGateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = ~shape << 1 & 0xe diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala index e5fa094fa..4f7765d97 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XNOR.scala @@ -6,10 +6,13 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object XNOR extends ComboICGateLogic { override def outputMask(shape: Int) = 1 override def inputMask(shape: Int) = 10 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala index 5a907cd46..8962df195 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/primitives/XOR.scala @@ -7,8 +7,11 @@ package mrtjp.projectred.fabrication.circuitparts.primitives import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} - +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} object XOR extends ComboICGateLogic { override def outputMask(shape: Int) = 1 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala index 604995171..509beee6a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Pulse.scala @@ -6,7 +6,10 @@ package mrtjp.projectred.fabrication.circuitparts.timing import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} class RenderPulse extends ICGateRenderer[ComboICGatePart] { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala index 3efdda4e7..b9ce81d83 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Repeater.scala @@ -7,10 +7,13 @@ package mrtjp.projectred.fabrication.circuitparts.timing import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ComboICGateLogic, ComboICGatePart, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + ComboICGateLogic, + ComboICGatePart, + ICGateRenderer +} import mrtjp.projectred.fabrication.{BaseComponentModel, RedstoneTorchModel} - object Repeater extends ComboICGateLogic { val delays = Array(2, 4, 6, 8, 16, 32, 64, 128, 256) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala index c8cf34f90..e09027384 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Sequencer.scala @@ -10,11 +10,19 @@ import codechicken.lib.math.MathHelper import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.Configurator import mrtjp.projectred.core.TFaceOrient.flipMaskZ -import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import mrtjp.projectred.fabrication.circuitparts.{ + GateICPart, + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + PointerModel, + RedstoneTorchModel +} import net.minecraft.nbt.NBTTagCompound - object Sequencer { def cycleShape(shape: Int): Int = { shape ^ 1 @@ -22,7 +30,7 @@ object Sequencer { } class Sequencer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with ITimerGuiLogic { var pointer_max = 40 var saveTime = -1L @@ -92,7 +100,6 @@ class Sequencer(gate: SequentialGateICPart) } } - class RenderSequencer extends ICGateRenderer[SequentialGateICPart] { val torches = Seq( new RedstoneTorchModel(8, 8), diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala index bb3a462ab..d23d60fb3 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/StateCell.scala @@ -8,8 +8,18 @@ package mrtjp.projectred.fabrication.circuitparts.timing import codechicken.lib.math.MathHelper import mrtjp.projectred.core.TFaceOrient.flipMaskZ import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart, SequentialICGateLogic, TExtraStateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedChipModel, RedstoneTorchModel} +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic, + TExtraStateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + PointerModel, + RedChipModel, + RedstoneTorchModel +} object StateCell { def cycleShape(shape: Int): Int = { @@ -17,9 +27,8 @@ object StateCell { } } - class StateCell(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with TTimerGateLogic with TExtraStateLogic { override def outputMask(shape: Int) = { @@ -80,7 +89,6 @@ class StateCell(gate: SequentialGateICPart) } } - class RenderStateCell extends ICGateRenderer[SequentialGateICPart] { val wires = generateWireModels("STATECELL", 5) val torches = diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala index 93ebb5039..804ddaf66 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/timing/Timer.scala @@ -11,19 +11,26 @@ import codechicken.multipart.handler.MultipartSaveLoad import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.core.Configurator import mrtjp.projectred.fabrication.ICComponentStore.generateWireModels -import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, SequentialGateICPart, SequentialICGateLogic} -import mrtjp.projectred.fabrication.{BaseComponentModel, PointerModel, RedstoneTorchModel} +import mrtjp.projectred.fabrication.circuitparts.{ + GateICPart, + ICGateRenderer, + SequentialGateICPart, + SequentialICGateLogic +} +import mrtjp.projectred.fabrication.{ + BaseComponentModel, + PointerModel, + RedstoneTorchModel +} import net.minecraft.nbt.NBTTagCompound - trait ITimerGuiLogic { def getTimerMax: Int def setTimerMax(gate: GateICPart, t: Int) } - class Timer(gate: SequentialGateICPart) - extends SequentialICGateLogic(gate) + extends SequentialICGateLogic(gate) with TTimerGateLogic { override def outputMask(shape: Int) = 0xb override def inputMask(shape: Int) = 0xe @@ -59,7 +66,6 @@ class Timer(gate: SequentialGateICPart) } } - trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { var pointer_max = 38 var pointer_start = -1L @@ -104,14 +110,14 @@ trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { } def getTotalTime = // client-side safe version of getTotalWorldTime (workaround for no client world) - { - if (gate.world.network == null) - saveTime // ic was loaded directly from stack, possibly for in-hand render - else if (gate.world.network.getWorld == null) - MultipartSaveLoad.loadingWorld.getTotalWorldTime // ic is being loaded with a workbench tile or gate - else - gate.world.network.getWorld.getTotalWorldTime // normal access during operation - } + { + if (gate.world.network == null) + saveTime // ic was loaded directly from stack, possibly for in-hand render + else if (gate.world.network.getWorld == null) + MultipartSaveLoad.loadingWorld.getTotalWorldTime // ic is being loaded with a workbench tile or gate + else + gate.world.network.getWorld.getTotalWorldTime // normal access during operation + } def pointerValue = if (pointer_start < 0) 0 else (getTotalTime - pointer_start).toInt @@ -169,7 +175,6 @@ trait TTimerGateLogic extends SequentialICGateLogic with ITimerGuiLogic { } } - class RenderTimer extends ICGateRenderer[SequentialGateICPart] { val wires = generateWireModels("TIME", 3) val torches = Seq(new RedstoneTorchModel(8, 3), new RedstoneTorchModel(8, 8)) @@ -195,4 +200,4 @@ class RenderTimer extends ICGateRenderer[SequentialGateICPart] { gate.getLogic[TTimerGateLogic].interpPointer(frame) * MathHelper.pi * 2 pointer.angle = ang } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala index 7dc0ed730..d6fde5e46 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala @@ -29,7 +29,6 @@ class AlloyWireICPart extends RedwireICPart { override def getPickOp = CircuitOpDefs.AlloyWire.getOp } - object RenderICAlloyWire { var connMap: Byte = 0 var signal: Byte = 0 @@ -53,4 +52,4 @@ object RenderICAlloyWire { ) finishRender() } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala index 94204c39b..c319ae793 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala @@ -14,12 +14,20 @@ import mrtjp.core.color.Colors import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication.circuitparts.IWireICPart._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, IWireICPart, TICBundledAcquisitions} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + CircuitPartDefs, + IWireICPart, + TICBundledAcquisitions +} import mrtjp.projectred.fabrication.operations.CircuitOpDefs -import mrtjp.projectred.transmission.BundledCommons.{packDigital, raiseSignal, unpackDigital} +import mrtjp.projectred.transmission.BundledCommons.{ + packDigital, + raiseSignal, + unpackDigital +} import net.minecraft.nbt.NBTTagCompound - trait IBundledCableICPart extends IWireICPart with IICBundledEmitter { def getBundledSignal: Array[Byte] def calculateSignal: Array[Byte] @@ -28,14 +36,12 @@ trait IBundledCableICPart extends IWireICPart with IICBundledEmitter { def getBundledColour: Int } - trait IICBundledEmitter { def getBundledSignal(r: Int): Array[Byte] } - class BundledCableICPart - extends WireICPart + extends WireICPart with TICBundledAcquisitions with IBundledCableICPart { var signal = new Array[Byte](16) @@ -67,7 +73,7 @@ class BundledCableICPart override def read(in: MCDataInput, key: Int) = key match { case 10 => signal = unpackDigital(signal, in.readUShort()) - case _ => super.read(in, key) + case _ => super.read(in, key) } override def onSignalUpdate() { @@ -81,8 +87,8 @@ class BundledCableICPart case b: IBundledCableICPart => b.getBundledColour == -1 || colour == -1 || b.getBundledColour == colour case ins: IInsulatedRedwireICPart => true - case be: IICBundledEmitter => true - case _ => false + case be: IICBundledEmitter => true + case _ => false } protected var propagatingMask = 0xffff @@ -137,7 +143,7 @@ class BundledCableICPart if (s > (tmpSignal(i.getInsulatedColour) & 0xff)) tmpSignal(i.getInsulatedColour) = s.toByte case b: IICBundledEmitter => raiseSignal(tmpSignal, b.getBundledSignal(r)) - case _ => + case _ => } tmpSignal } @@ -185,7 +191,7 @@ class BundledCableICPart @SideOnly(Side.CLIENT) override def getPartName = (if (colour != -1) Colors(colour & 0xff).name + " " - else "") + "Bundled cable" + else "") + "Bundled cable" @SideOnly(Side.CLIENT) override def getPickOp = CircuitOpDefs @@ -206,7 +212,6 @@ class BundledCableICPart } } - object RenderICBundledCable { var connMap: Byte = 0 var colour: Byte = 0 diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala index 01e982e2c..9c86bb0c0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala @@ -11,7 +11,13 @@ import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TClientNetCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + CircuitPartDefs, + TPoweredCircuitPart, + TClientNetCircuitPart, + TICAcquisitions +} import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumChatFormatting @@ -127,7 +133,6 @@ class ButtonICPart } } - object RenderICButton { var on = false diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala index a74017215..96f52861e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala @@ -16,12 +16,10 @@ import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs} import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound - trait IInsulatedRedwireICPart extends IRedwireICPart { def getInsulatedColour: Int } - class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { var colour: Byte = 0 @@ -49,13 +47,13 @@ class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { override def resolveSignal(part: Any, r: Int) = part match { case b: IBundledCableICPart => (b.getBundledSignal.apply(colour) & 0xff) - 1 - case _ => super.resolveSignal(part, r) + case _ => super.resolveSignal(part, r) } override def canConnectPart(part: CircuitPart, r: Int) = part match { - case b: IBundledCableICPart => true + case b: IBundledCableICPart => true case iw: InsulatedWireICPart => iw.colour == colour - case _ => super.canConnectPart(part, r) + case _ => super.canConnectPart(part, r) } override def getInsulatedColour = colour @@ -76,8 +74,6 @@ class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { .getOp } - - object RenderICInsulatedWire { var connMap: Byte = 0 var signal: Byte = 0 @@ -110,4 +106,3 @@ object RenderICInsulatedWire { finishRender() } } - diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala index 3f03eb332..c705ffbca 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala @@ -11,12 +11,17 @@ import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TClientNetCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + CircuitPartDefs, + TPoweredCircuitPart, + TClientNetCircuitPart, + TICAcquisitions +} import mrtjp.projectred.fabrication.operations.CircuitOpDefs import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.EnumChatFormatting - class LeverICPart extends CircuitPart with TICAcquisitions @@ -102,7 +107,6 @@ class LeverICPart } } - object RenderICLever { var on = false @@ -120,4 +124,4 @@ object RenderICLever { .render(t, new IconTransformation(if (on) leverOnIcon else leverOffIcon)) finishRender() } -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala index f28f01cee..1ad689b84 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala @@ -10,10 +10,14 @@ import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs, TPoweredCircuitPart, TICAcquisitions} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + CircuitPartDefs, + TPoweredCircuitPart, + TICAcquisitions +} import mrtjp.projectred.fabrication.operations.CircuitOpDefs - class TorchICPart extends CircuitPart with TICAcquisitions @@ -47,7 +51,6 @@ class TorchICPart } } - object RenderICTorch { def render(t: Transformation, ortho: Boolean) { prepairRender() diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala index 560f45a3b..99da04134 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Redwire.scala @@ -8,15 +8,16 @@ package mrtjp.projectred.fabrication.circuitparts.wire import codechicken.lib.data.{MCDataInput, MCDataOutput} import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TPoweredCircuitPart, TICRSAcquisitions, TRSPropagatingICPart} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + TPoweredCircuitPart, + TICRSAcquisitions, + TRSPropagatingICPart +} import net.minecraft.nbt.NBTTagCompound - - - - abstract class RedwireICPart - extends WireICPart + extends WireICPart with TICRSAcquisitions with TRSPropagatingICPart with IRedwireICPart { @@ -44,7 +45,7 @@ abstract class RedwireICPart override def read(in: MCDataInput, key: Int) = key match { case 10 => signal = in.readByte() - case _ => super.read(in, key) + case _ => super.read(in, key) } override def onSignalUpdate() { @@ -54,7 +55,7 @@ abstract class RedwireICPart override def discoverOverride(r: Int, part: CircuitPart) = part match { case pow: TPoweredCircuitPart => pow.canConnectRS(rotFromStraight(r)) - case _ => super.discoverOverride(r, part) + case _ => super.discoverOverride(r, part) } override def canConnectRS(r: Int) = ICPropagator.redwiresConnectable @@ -73,16 +74,16 @@ abstract class RedwireICPart else 0 override def canConnectPart(part: CircuitPart, r: Int) = part match { - case re: IICRedwireEmitter => true + case re: IICRedwireEmitter => true case pc: TPoweredCircuitPart => true - case _ => false + case _ => false } override def resolveSignal(part: Any, r: Int) = part match { case t: IRedwireICPart if t.diminishOnSide(r) => t.getRedwireSignal(r) - 1 - case t: IICRedwireEmitter => t.getRedwireSignal(r) - case t: TPoweredCircuitPart => t.rsOutputLevel(r) - case _ => 0 + case t: IICRedwireEmitter => t.getRedwireSignal(r) + case t: TPoweredCircuitPart => t.rsOutputLevel(r) + case _ => 0 } override def calculateSignal = { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala index 9ffa0612b..3d7d53146 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Wire.scala @@ -9,17 +9,21 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import mrtjp.core.color.Colors import mrtjp.projectred.fabrication.circuitparts.IWireICPart._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TErrorCircuitPart, IWireICPart, TConnectableICPart, TPropagatingICPart} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + TErrorCircuitPart, + IWireICPart, + TConnectableICPart, + TPropagatingICPart +} import net.minecraft.nbt.NBTTagCompound - trait IRedwireICPart extends IWireICPart with IICRedwireEmitter trait IICRedwireEmitter { def getRedwireSignal(r: Int): Int } - abstract class WireICPart extends CircuitPart with TConnectableICPart diff --git a/src/main/scala/mrtjp/projectred/fabrication/components.scala b/src/main/scala/mrtjp/projectred/fabrication/components.scala index f89d7ac5f..81c5ab0bc 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/components.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/components.scala @@ -8,7 +8,12 @@ package mrtjp.projectred.fabrication import codechicken.lib.math.MathHelper import codechicken.lib.render.CCRenderState.IVertexOperation import codechicken.lib.render.uv.{IconTransformation, UVTransformation} -import codechicken.lib.render.{CCModel, CCRenderState, ColourMultiplier, TextureUtils} +import codechicken.lib.render.{ + CCModel, + CCRenderState, + ColourMultiplier, + TextureUtils +} import codechicken.lib.vec._ import mrtjp.core.color.Colors import mrtjp.core.vec.{Size, Vec2} @@ -138,8 +143,16 @@ object ICComponentStore { def orthoPartT(position: Vec2, scale: Double): TransformationList = { new TransformationList( - new Scale(RenderCircuit.BASE_SCALE * scale, 1, -RenderCircuit.BASE_SCALE * scale), - new Translation(position.dx * RenderCircuit.BASE_SCALE * scale, 0, -position.dy * RenderCircuit.BASE_SCALE * scale), + new Scale( + RenderCircuit.BASE_SCALE * scale, + 1, + -RenderCircuit.BASE_SCALE * scale + ), + new Translation( + position.dx * RenderCircuit.BASE_SCALE * scale, + 0, + -position.dy * RenderCircuit.BASE_SCALE * scale + ), new Rotation(1.571, 1, 0, 0) ) } @@ -279,7 +292,11 @@ class ArrowModel extends ICComponentModel { // 0: in, 1: out, 2: inout var arrowDirection: Int = 0 - override def renderModel(t: Transformation, orient: Int, ortho: Boolean): Unit = { + override def renderModel( + t: Transformation, + orient: Int, + ortho: Boolean + ): Unit = { val m = faceModels(dynamicIdx(orient, ortho)) val t0 = dynamicT(orient) `with` t m.render( diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala index 7bc097247..4b0c50842 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala @@ -20,7 +20,6 @@ trait IGuiCircuitPart extends TClientNetCircuitPart { def createGui: CircuitGui } - class CircuitGui(val part: IGuiCircuitPart) extends Gui with TNode { var size = Size.zeroSize @@ -71,10 +70,10 @@ class CircuitGui(val part: IGuiCircuitPart) extends Gui with TNode { } override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { if (parent == null) false // we cant check for consume here, so manually check if closed else diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 1247880aa..9db0f28e2 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -24,7 +24,6 @@ import org.lwjgl.opengl.GL11 import java.math.MathContext - class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var pref: PrefboardNode = null var toolSets = Seq[ICToolsetNode]() @@ -41,19 +40,21 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { addChild(opPreview) pref = new PrefboardNode( - tile.circuit, tile.hasBP, - op => {opPreview.updatePreview(op)}, + tile.circuit, + tile.hasBP, + op => { opPreview.updatePreview(op) }, node => { - if(configurationNode != null) { + if (configurationNode != null) { configurationNode.removeFromParent() configurationNode = null } configurationNode = node - if(configurationNode != null) { + if (configurationNode != null) { configurationNode.position = Point(260, 17) addChild(configurationNode) } - }) + } + ) pref.zPosition = -0.01 // Must be below clip nodes pref.opPickDelegate = { op => if (op == null) { @@ -70,7 +71,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolSets.foreach(_.pickOp(op)) } clip.addChild(pref) - if(tile.circuit.parts.nonEmpty) { + if (tile.circuit.parts.nonEmpty) { pref.scaleGuiToCircuit() } else { pref.offset = Vec2(0, 0) @@ -94,7 +95,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { toolset.opSelectDelegate = { op => pref.currentOp = op pref.updatePreview() - if(configurationNode != null) { + if (configurationNode != null) { configurationNode.removeFromParent() configurationNode = null } @@ -151,8 +152,10 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { val textboxICName = new SimpleTextboxNode() textboxICName.position = Point(80, 4) textboxICName.size = Size(115, 11) - textboxICName.text = tile.circuit.name - textboxICName.textChangedDelegate = { () => tile.sendICNameToServer(textboxICName.text) } + textboxICName.text = tile.circuit.name + textboxICName.textChangedDelegate = { () => + tile.sendICNameToServer(textboxICName.text) + } addChild(textboxICName) val dminus = new MCButtonNode @@ -200,7 +203,11 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { addChild(info) } - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean): Boolean = { + override def keyPressed_Impl( + c: Char, + keycode: Int, + consumed: Boolean + ): Boolean = { import Keyboard._ if (!consumed) keycode match { case KEY_W => @@ -211,13 +218,14 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { true case KEY_S => pref.offset += Vec2(0, 2 / pref.scale) - true + true case KEY_D => pref.offset += Vec2(2 / pref.scale, 0) true case _ => false - } else false + } + else false } override def drawBack_Impl(mouse: Point, frame: Float) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala index 402cbb410..7615aa3c0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/PrefboardRenderer.scala @@ -15,13 +15,16 @@ import mrtjp.projectred.fabrication.RenderCircuit import net.minecraft.client.Minecraft import net.minecraft.util.ResourceLocation - object PrefboardRenderer { def renderOrtho(size: Size, scale: Double, gridTranslation: Vec2) { - val offset = gridTranslation - Vec2(gridTranslation.dx.toInt, gridTranslation.dy.toInt) + val offset = + gridTranslation - Vec2(gridTranslation.dx.toInt, gridTranslation.dy.toInt) - val uv = new UVScale(size.width / (RenderCircuit.BASE_SCALE * scale) + 2, size.height / (RenderCircuit.BASE_SCALE * scale) + 2) + val uv = new UVScale( + size.width / (RenderCircuit.BASE_SCALE * scale) + 2, + size.height / (RenderCircuit.BASE_SCALE * scale) + 2 + ) val boardModel = faceModels.map(_.copy().apply(uv)) val state = CCRenderState.instance @@ -30,8 +33,16 @@ object PrefboardRenderer { state.setDynamicInstance() val t = new TransformationList( - new Scale(size.width + 2 * RenderCircuit.BASE_SCALE * scale, 1, -(size.height + 2 * RenderCircuit.BASE_SCALE * scale)), - new Translation(-(offset.dx + 1) * RenderCircuit.BASE_SCALE * scale, 0, (offset.dy + 1) * RenderCircuit.BASE_SCALE * scale), + new Scale( + size.width + 2 * RenderCircuit.BASE_SCALE * scale, + 1, + -(size.height + 2 * RenderCircuit.BASE_SCALE * scale) + ), + new Translation( + -(offset.dx + 1) * RenderCircuit.BASE_SCALE * scale, + 0, + (offset.dy + 1) * RenderCircuit.BASE_SCALE * scale + ), new Rotation(0.5 * MathHelper.pi, 1, 0, 0) ) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala index 8830a846a..d17d48aa0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala @@ -9,7 +9,11 @@ import codechicken.lib.vec.Translation import mrtjp.core.gui.TNode import mrtjp.core.vec.Point import mrtjp.projectred.fabrication.ICComponentStore -import mrtjp.projectred.fabrication.circuitparts.{GateICPart, ICGateRenderer, TClientNetCircuitPart} +import mrtjp.projectred.fabrication.circuitparts.{ + GateICPart, + ICGateRenderer, + TClientNetCircuitPart +} trait TConfigurable extends TClientNetCircuitPart { def createConfigurationNode: ConfigurationNode diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index 856773dc6..1b786be84 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -13,7 +13,6 @@ import mrtjp.projectred.fabrication.operations.CircuitOp import scala.collection.immutable.ListMap import scala.collection.JavaConversions._ - class ICToolsetNode extends TNode { var opSet = Seq.empty[CircuitOp] var title = "" @@ -124,7 +123,7 @@ class ICToolsetNode extends TNode { setUnfocused() buttonOpMap.find(_._2 == op) match { case Some((b, _)) => b.clickDelegate() - case _ => + case _ => } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala index 9d595e208..c9829836e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/InfoNode.scala @@ -12,7 +12,6 @@ import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.gui.GuiICWorkbench import net.minecraft.client.gui.Gui - class InfoNode extends TNode { val size = Size(18, 18) override def frame = Rect(position, size) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala index fa8ca08cb..6cecc4ba2 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/OpPreviewNode.scala @@ -9,7 +9,6 @@ import mrtjp.core.gui.TNode import mrtjp.core.vec.Point import mrtjp.projectred.fabrication.operations.CircuitOp - class OpPreviewNode extends TNode { var currentOp: CircuitOp = null diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index efa06bc3b..912c56a6a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -10,10 +10,21 @@ import mrtjp.core.gui.{ClipNode, TNode} import mrtjp.core.vec.{Point, Rect, Vec2} import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic -import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, TransparentLatch} -import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, DecRandomizer, Randomizer} +import mrtjp.projectred.fabrication.circuitparts.latches.{ + SRLatch, + TransparentLatch +} +import mrtjp.projectred.fabrication.circuitparts.misc.{ + Counter, + DecRandomizer, + Randomizer +} import mrtjp.projectred.fabrication.circuitparts.primitives._ -import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} +import mrtjp.projectred.fabrication.circuitparts.timing.{ + Repeater, + Sequencer, + StateCell +} import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} import mrtjp.projectred.fabrication.operations._ import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} @@ -23,11 +34,16 @@ import org.lwjgl.input.{Keyboard, Mouse} import scala.collection.JavaConversions._ import scala.collection.convert.WrapAsJava -class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUpdateDelegate: CircuitOp => Unit, setConfigNode: TNode => Unit) extends TNode { +class PrefboardNode( + circuit: IntegratedCircuit, + hasBlueprint: Boolean, + previewUpdateDelegate: CircuitOp => Unit, + setConfigNode: TNode => Unit +) extends TNode { var currentOp: CircuitOp = null /** 0 - off 1 - name only 2 - minor details 3 - all details - */ + */ var detailLevel = 1 var scale = 1.0 @@ -48,10 +64,9 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp private var rightMouseDown = false private var mouseStart = Point(0, 0) - - /** - * Converts coordinates in the gui to coordinates in the circuit (with rounding) - */ + /** Converts coordinates in the gui to coordinates in the circuit (with + * rounding) + */ private def toGridPoint(p: Vec2): Point = { val circuitCoord = p / (RenderCircuit.BASE_SCALE * scale) + offset Point( @@ -68,7 +83,6 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp ) } - private def toCenteredGuiPoint(gridP: Point) = { val dp = frame.size.vectorize / 16 Point(gridP.vectorize * dp + dp / 2) @@ -80,7 +94,7 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp } override def drawBack_Impl(mouse: Point, rframe: Float) { - if(hasBlueprint) { + if (hasBlueprint) { val f = frame RenderCircuit.renderOrtho( circuit, @@ -95,7 +109,11 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp currentOp match { case _: OpGate | _: OpWire | _: SimplePlacementOp => if (circuit.getPart(toGridPoint(mouse.vectorize)) == null) - currentOp.renderHover(toGridPoint(mouse).vectorize, scale, offset) + currentOp.renderHover( + toGridPoint(mouse).vectorize, + scale, + offset + ) case _: CircuitOpErase => currentOp.renderHover(toGridPoint(mouse).vectorize, scale, offset) } @@ -103,7 +121,11 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp currentOp.renderDrag( mouseStart.vectorize, toGridPoint(mouse).vectorize, - CircuitOp.partsBetweenPoints(mouseStart.vectorize, toGridPoint(mouse).vectorize, circuit), + CircuitOp.partsBetweenPoints( + mouseStart.vectorize, + toGridPoint(mouse).vectorize, + circuit + ), scale, offset ) @@ -114,7 +136,7 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp } override def drawFront_Impl(mouse: Point, rframe: Float) { - if(!leftMouseDown && rayTest(mouse)) { + if (!leftMouseDown && rayTest(mouse)) { val point = toGridPoint(mouse.vectorize) val part = circuit.getPart(point) if (part != null) { @@ -142,10 +164,16 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp } private var mousePosition = Point(0, 0) - override def mouseDragged_Impl(p: Point, button: Int, time: Long, consumed: Boolean): Boolean = { - if(!consumed && rayTest(p) && button == 0 && currentOp == null) { - if(time > 20) { - offset = offset - (p - mousePosition).vectorize / (RenderCircuit.BASE_SCALE * scale) + override def mouseDragged_Impl( + p: Point, + button: Int, + time: Long, + consumed: Boolean + ): Boolean = { + if (!consumed && rayTest(p) && button == 0 && currentOp == null) { + if (time > 20) { + offset = + offset - (p - mousePosition).vectorize / (RenderCircuit.BASE_SCALE * scale) } mousePosition = p true @@ -156,10 +184,10 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp } override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { if (!consumed && rayTest(p)) button match { case 0 => leftMouseDown = true @@ -280,9 +308,9 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp op.configuration = TransparentLatch.cycleShape(op.configuration) case ICGateDefinition.DecRandomizer.ordinal => op.configuration = DecRandomizer.cycleShape(op.configuration) - case ICGateDefinition.IOAnalog.ordinal - | ICGateDefinition.IOSimple.ordinal - | ICGateDefinition.IOBundled.ordinal => + case ICGateDefinition.IOAnalog.ordinal | + ICGateDefinition.IOSimple.ordinal | + ICGateDefinition.IOBundled.ordinal => op.configuration = IOICGateLogic.cycleShape(op.configuration) case ICGateDefinition.Sequencer.ordinal => op.configuration = Sequencer.cycleShape(op.configuration) @@ -339,12 +367,13 @@ class PrefboardNode(circuit: IntegratedCircuit, hasBlueprint: Boolean, previewUp scale = newScale } - /** - * Scales the prefboard to the circuit with some border - */ + /** Scales the prefboard to the circuit with some border + */ def scaleGuiToCircuit() = { val circuitBounds = circuit.getPartsBoundingBox() - val circuitBoundsWithPadding = circuitBounds.union(Rect(circuitBounds.origin.subtract(1, 1), circuitBounds.size.add(3))) + val circuitBoundsWithPadding = circuitBounds.union( + Rect(circuitBounds.origin.subtract(1, 1), circuitBounds.size.add(3)) + ) // Required scaling to fit whole circuit on the screen val requiredScale = math.min( (parent.frame.size.width / RenderCircuit.BASE_SCALE.toDouble) / circuitBoundsWithPadding.size.width, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala index 0ad864e01..5227b692b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala @@ -19,19 +19,29 @@ class ColorPicker(onPickColor: Int => Unit) extends TNode { override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { val edge = size.width / 4 - for(i <- 0 to 15) { - GuiDraw.drawRect(position.x + (i % 4) * edge, position.y + (i / 4) * edge, edge, edge, Colors(i).argb) + for (i <- 0 to 15) { + GuiDraw.drawRect( + position.x + (i % 4) * edge, + position.y + (i / 4) * edge, + edge, + edge, + Colors(i).argb + ) } } - override def mouseClicked_Impl(p: Point, button: Int, consumed: Boolean): Boolean = { - if(!consumed && rayTest(p)) { + override def mouseClicked_Impl( + p: Point, + button: Int, + consumed: Boolean + ): Boolean = { + if (!consumed && rayTest(p)) { val relPos = p.subtract(position) - val index = (relPos.y / (size.height / 4)) * 4 + relPos.x / (size.width / 4) + val index = + (relPos.y / (size.height / 4)) * 4 + relPos.x / (size.width / 4) onPickColor(index) true - } - else + } else false } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala index bb3223a69..ce37ae63d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala @@ -9,21 +9,26 @@ import codechicken.lib.gui.GuiDraw import mrtjp.core.color.Colors import mrtjp.core.gui.SimpleTextboxNode import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.fabrication.circuitparts.io.{AnalogIOICGateLogic, IOGateICPart} +import mrtjp.projectred.fabrication.circuitparts.io.{ + AnalogIOICGateLogic, + IOGateICPart +} import scala.util.Try -class ConfigurationAnalogIO(gate: IOGateICPart) extends ConfigurationSimpleIO(gate) { +class ConfigurationAnalogIO(gate: IOGateICPart) + extends ConfigurationSimpleIO(gate) { private val logic = gate.getLogicPrimitive.asInstanceOf[AnalogIOICGateLogic] val freq = new SimpleTextboxNode freq.position = Point(20, 110) freq.size = Size(30, 12) freq.text = "0x%x".format(logic.freq) - freq.textChangedDelegate = { () => { - val num = Try(Integer.parseInt(freq.text.substring(2), 16)) - gate.sendFrequency(num.getOrElse(0)) - } + freq.textChangedDelegate = { () => + { + val num = Try(Integer.parseInt(freq.text.substring(2), 16)) + gate.sendFrequency(num.getOrElse(0)) + } } addChild(freq) @@ -31,6 +36,12 @@ class ConfigurationAnalogIO(gate: IOGateICPart) extends ConfigurationSimpleIO(ga super.drawBack_Impl(mouse, rframe) val pos_text = position.add(5, 100) - GuiDraw.drawString("Frequency:", pos_text.x, pos_text.y, Colors.GREY.argb, false) + GuiDraw.drawString( + "Frequency:", + pos_text.x, + pos_text.y, + Colors.GREY.argb, + false + ) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala index 4b63d3ff9..5215cd0bd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala @@ -8,11 +8,11 @@ package mrtjp.projectred.fabrication.gui.nodes.configuration import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart -class ConfigurationBundledIO(gate: IOGateICPart) extends ConfigurationSimpleIO(gate){ - val colorPicker = new ColorPicker( - onPickColor = color => { - gate.sendFrequency(color) - }) +class ConfigurationBundledIO(gate: IOGateICPart) + extends ConfigurationSimpleIO(gate) { + val colorPicker = new ColorPicker(onPickColor = color => { + gate.sendFrequency(color) + }) colorPicker.position = Point(5, 100) colorPicker.size = Size(60, 60) addChild(colorPicker) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala index caa6a00f8..843dc3e4b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala @@ -14,18 +14,24 @@ import mrtjp.projectred.fabrication.circuitparts.misc.ICounterGuiLogic import scala.util.Try -class ConfigurationCounter(gate: SequentialGateICPart) extends ConfigurationRotationConfig(gate) { - private val counterLogic = gate.getLogicPrimitive.asInstanceOf[ICounterGuiLogic] +class ConfigurationCounter(gate: SequentialGateICPart) + extends ConfigurationRotationConfig(gate) { + private val counterLogic = + gate.getLogicPrimitive.asInstanceOf[ICounterGuiLogic] val max = new SimpleTextboxNode() max.position = Point(30, 118) max.size = Size(30, 12) max.text = counterLogic.getCounterMax.toString max.allowedcharacters = "0123456789" - max.textChangedDelegate = { () => { - val num = Try(max.text.toInt) - gate.sendClientPacket(_.writeByte(4).writeByte(0).writeShort(num.getOrElse(1))) - } } + max.textChangedDelegate = { () => + { + val num = Try(max.text.toInt) + gate.sendClientPacket( + _.writeByte(4).writeByte(0).writeShort(num.getOrElse(1)) + ) + } + } addChild(max) val inc = new SimpleTextboxNode() @@ -33,10 +39,14 @@ class ConfigurationCounter(gate: SequentialGateICPart) extends ConfigurationRota inc.size = Size(30, 12) inc.text = counterLogic.getCounterIncr.toString inc.allowedcharacters = "0123456789" - inc.textChangedDelegate = { () => { - val num = Try(inc.text.toInt) - gate.sendClientPacket(_.writeByte(4).writeByte(1).writeShort(num.getOrElse(1))) - } } + inc.textChangedDelegate = { () => + { + val num = Try(inc.text.toInt) + gate.sendClientPacket( + _.writeByte(4).writeByte(1).writeShort(num.getOrElse(1)) + ) + } + } addChild(inc) val dec = new SimpleTextboxNode() @@ -44,10 +54,14 @@ class ConfigurationCounter(gate: SequentialGateICPart) extends ConfigurationRota dec.size = Size(30, 12) dec.text = counterLogic.getCounterDecr.toString dec.allowedcharacters = "0123456789" - dec.textChangedDelegate = { () => { - val num = Try(dec.text.toInt) - gate.sendClientPacket(_.writeByte(4).writeByte(2).writeShort(num.getOrElse(1))) - } } + dec.textChangedDelegate = { () => + { + val num = Try(dec.text.toInt) + gate.sendClientPacket( + _.writeByte(4).writeByte(2).writeShort(num.getOrElse(1)) + ) + } + } addChild(dec) override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { @@ -56,7 +70,10 @@ class ConfigurationCounter(gate: SequentialGateICPart) extends ConfigurationRota val pos_state = position.add(5, 102) GuiDraw.drawString( "State: " + counterLogic.getCounterValue.toString, - pos_state.x, pos_state.y, Colors.GREY.argb, false + pos_state.x, + pos_state.y, + Colors.GREY.argb, + false ) val pos_max = position.add(5, 120) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala index 6146d7892..845ff85f1 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala @@ -9,7 +9,8 @@ import mrtjp.core.gui.MCButtonNode import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.fabrication.circuitparts.GateICPart -class ConfigurationRotationConfig(gate: GateICPart) extends ConfigurationRotation(gate) { +class ConfigurationRotationConfig(gate: GateICPart) + extends ConfigurationRotation(gate) { val conf = new MCButtonNode conf.position = Point(8, 80) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala index ca2576a5a..0ada8a0a5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala @@ -11,7 +11,8 @@ import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart import mrtjp.projectred.fabrication.{ArrowModel, ICComponentStore} -class ConfigurationSimpleIO(gate: IOGateICPart) extends ConfigurationRotation(gate) { +class ConfigurationSimpleIO(gate: IOGateICPart) + extends ConfigurationRotation(gate) { val arrowModel = new ArrowModel @@ -23,8 +24,8 @@ class ConfigurationSimpleIO(gate: IOGateICPart) extends ConfigurationRotation(ga in.position = Point(5, 80) in.size = Size(20, 15) - in.clickDelegate = { - () => gate.sendClientPacket(_.writeByte(1)) + in.clickDelegate = { () => + gate.sendClientPacket(_.writeByte(1)) } addChild(in) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala index 51cf0c35d..d6c03f51c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala @@ -12,11 +12,15 @@ import mrtjp.core.gui.SimpleTextboxNode import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.fabrication.ICComponentStore import mrtjp.projectred.fabrication.circuitparts.timing.ITimerGuiLogic -import mrtjp.projectred.fabrication.circuitparts.{ICGateRenderer, SequentialGateICPart} +import mrtjp.projectred.fabrication.circuitparts.{ + ICGateRenderer, + SequentialGateICPart +} import scala.util.Try -class ConfigurationTimer(gate: SequentialGateICPart) extends ConfigurationRotation(gate) { +class ConfigurationTimer(gate: SequentialGateICPart) + extends ConfigurationRotation(gate) { private val timerLogic = gate.getLogicPrimitive.asInstanceOf[ITimerGuiLogic] val text = new SimpleTextboxNode @@ -26,7 +30,9 @@ class ConfigurationTimer(gate: SequentialGateICPart) extends ConfigurationRotati text.text = "%.2f".format(timerLogic.getTimerMax * 0.05) text.textChangedDelegate = () => { val time = Try(text.text.replaceAll(",", ".").toDouble) - gate.sendClientPacket(_.writeByte(3).writeShort((time.getOrElse(1d) * 20).toInt)) + gate.sendClientPacket( + _.writeByte(3).writeShort((time.getOrElse(1d) * 20).toInt) + ) } addChild(text) @@ -36,7 +42,10 @@ class ConfigurationTimer(gate: SequentialGateICPart) extends ConfigurationRotati val pos_state = position.add(13, 82) GuiDraw.drawString( "Interval:", - pos_state.x, pos_state.y, Colors.GREY.argb, false + pos_state.x, + pos_state.y, + Colors.GREY.argb, + false ) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index 235eefdf7..05f3bf053 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -11,7 +11,6 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.{Point, Size, Vec2} import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} - trait CircuitOp { var id = -1 @@ -22,83 +21,114 @@ trait CircuitOp { def getConfiguration(): Int def writeOp( - circuit: IntegratedCircuit, - start: Point, - end: Point, - out: MCDataOutput - ) + circuit: IntegratedCircuit, + start: Point, + end: Point, + out: MCDataOutput + ) def readOp(circuit: IntegratedCircuit, in: MCDataInput) @SideOnly(Side.CLIENT) def getOpName: String - /** - * Render the selected Operation, when on the mouse cursor - * @param position Position in Grid coordinates - * @param scale Prefboard scaling - */ + /** Render the selected Operation, when on the mouse cursor + * @param position + * Position in Grid coordinates + * @param scale + * Prefboard scaling + */ @SideOnly(Side.CLIENT) def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit - /** - * Render the selected Operation when dragging - * @param start Start in Grid coordinates - * @param end End in Grid coordinates - * @param positionsWithParts Positions in Rect(start, end) with existing parts - * @param scale Prefboard scaling - * @param prefboardOffset Prefboard offset - */ + /** Render the selected Operation when dragging + * @param start + * Start in Grid coordinates + * @param end + * End in Grid coordinates + * @param positionsWithParts + * Positions in Rect(start, end) with existing parts + * @param scale + * Prefboard scaling + * @param prefboardOffset + * Prefboard offset + */ @SideOnly(Side.CLIENT) - def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit - - /** - * Render the part, that will be placed by this operation - */ + def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit + + /** Render the part, that will be placed by this operation + */ @SideOnly(Side.CLIENT) def renderImage(x: Double, y: Double, width: Double, height: Double) - /** - * Same as renderImage, however it ignores configuration and rotation (e.g. toolbar) - */ + /** Same as renderImage, however it ignores configuration and rotation (e.g. + * toolbar) + */ @SideOnly(Side.CLIENT) - def renderImageStatic(x: Double, y: Double, width: Double, height: Double): Unit = - renderImage(x, y ,width, height) + def renderImageStatic( + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = + renderImage(x, y, width, height) } object CircuitOp { def getOperation(id: Int) = CircuitOpDefs(id).getOp - /** - * Draw one Tile - * @param position In Grid Coordinates - */ + /** Draw one Tile + * @param position + * In Grid Coordinates + */ def renderHolo(position: Vec2, scale: Double, colour: Int): Unit = { val start = position * RenderCircuit.BASE_SCALE * scale - val end = start + Vec2(RenderCircuit.BASE_SCALE * scale, RenderCircuit.BASE_SCALE * scale) - GuiDraw.drawRect(start.dx.toInt, start.dy.toInt, (end - start).dx.toInt, (end - start).dy.toInt, colour) + val end = start + Vec2( + RenderCircuit.BASE_SCALE * scale, + RenderCircuit.BASE_SCALE * scale + ) + GuiDraw.drawRect( + start.dx.toInt, + start.dy.toInt, + (end - start).dx.toInt, + (end - start).dy.toInt, + colour + ) } - /** - * Draw Multiple tiles in a rect excluding end - * @param start In Grid Coordinates - * @param end In Grid coordinates - */ + /** Draw Multiple tiles in a rect excluding end + * @param start + * In Grid Coordinates + * @param end + * In Grid coordinates + */ def renderHolo(start: Vec2, end: Vec2, scale: Double, colour: Int): Unit = { val s = start * RenderCircuit.BASE_SCALE * scale val e = end * RenderCircuit.BASE_SCALE * scale - GuiDraw.drawRect(s.dx.toInt, s.dy.toInt, (e - s).dx.toInt, (e - s).dy.toInt, colour) + GuiDraw.drawRect( + s.dx.toInt, + s.dy.toInt, + (e - s).dx.toInt, + (e - s).dy.toInt, + colour + ) } def renderHolo( - x: Double, - y: Double, - xSize: Double, - ySize: Double, - csize: Size, - point: Point, - colour: Int - ) { + x: Double, + y: Double, + xSize: Double, + ySize: Double, + csize: Size, + point: Point, + colour: Int + ) { val x1 = (x + xSize / csize.width * point.x).toInt val y1 = (y + ySize / csize.height * point.y).toInt val x2 = (x + xSize / csize.width * (point.x + 1)).toInt @@ -107,11 +137,25 @@ object CircuitOp { GuiDraw.drawRect(x1, y1, x2 - x1, y2 - y1, colour) } - def partsBetweenPoints(start: Vec2, end: Vec2, circuit: IntegratedCircuit): Seq[Vec2] = { + def partsBetweenPoints( + start: Vec2, + end: Vec2, + circuit: IntegratedCircuit + ): Seq[Vec2] = { var partPositions: Seq[Vec2] = Seq.empty - for(x <- math.min(start.dx.toInt, end.dx.toInt) to math.max(start.dx.toInt, end.dx.toInt)) { - for(y <- math.min(start.dy.toInt, end.dy.toInt) to math.max(start.dy.toInt, end.dy.toInt)) { - if(circuit.getPart(x, y) != null) { + for ( + x <- math.min(start.dx.toInt, end.dx.toInt) to math.max( + start.dx.toInt, + end.dx.toInt + ) + ) { + for ( + y <- math.min(start.dy.toInt, end.dy.toInt) to math.max( + start.dy.toInt, + end.dy.toInt + ) + ) { + if (circuit.getPart(x, y) != null) { partPositions = partPositions :+ Vec2(x, y) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala index e79101441..8af05fb4e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala @@ -8,7 +8,6 @@ package mrtjp.projectred.fabrication.operations import mrtjp.core.util.Enum import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition - object CircuitOpDefs extends Enum { type EnumVal = OpDef @@ -109,6 +108,3 @@ object CircuitOpDefs extends Enum { def getOp = op } } - - - diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala index 6f10e8bef..d57e673e0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala @@ -62,19 +62,31 @@ class CircuitOpErase extends CircuitOp { } @SideOnly(Side.CLIENT) - override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { CircuitOp.renderHolo(position - prefboardOffset, scale, 0x33ff0000) } @SideOnly(Side.CLIENT) - override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + override def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = { var (topLeft, bottomRight) = ( - Vec2(math.min(start.dx, end.dx), math.min(start.dy, end.dy)).subtract(prefboardOffset), - Vec2(math.max(start.dx, end.dx), math.max(start.dy, end.dy)).subtract(prefboardOffset) + Vec2(math.min(start.dx, end.dx), math.min(start.dy, end.dy)) + .subtract(prefboardOffset), + Vec2(math.max(start.dx, end.dx), math.max(start.dy, end.dy)) + .subtract(prefboardOffset) ) bottomRight = bottomRight.add(1, 1) CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) - for(posWithPart <- positionsWithParts) { + for (posWithPart <- positionsWithParts) { CircuitOp.renderHolo(posWithPart - prefboardOffset, scale, 0x44ff0000) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala index dff0b97fc..0d9ccac72 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala @@ -8,8 +8,11 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.circuitparts.CircuitPartDefs -import mrtjp.projectred.fabrication.circuitparts.wire.{RenderICButton, RenderICLever, RenderICTorch} - +import mrtjp.projectred.fabrication.circuitparts.wire.{ + RenderICButton, + RenderICLever, + RenderICTorch +} class CircuitOpTorch extends SimplePlacementOp { override def doPartRender(t: Transformation) = RenderICTorch.render(t, true) @@ -20,7 +23,6 @@ class CircuitOpTorch extends SimplePlacementOp { override def getOpName = "Torch" } - class CircuitOpButton extends SimplePlacementOp { override def doPartRender(t: Transformation) { RenderICButton.prepairInv() @@ -33,7 +35,6 @@ class CircuitOpButton extends SimplePlacementOp { override def getOpName = "Button" } - class CircuitOpLever extends SimplePlacementOp { override def doPartRender(t: Transformation) { RenderICLever.prepairInv() @@ -44,4 +45,4 @@ class CircuitOpLever extends SimplePlacementOp { @SideOnly(Side.CLIENT) override def getOpName = "Lever" -} \ No newline at end of file +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index 7b2f63e7a..588a435b2 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -11,10 +11,14 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication._ -import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, GateICPart, ICGateDefinition, ICGateRenderer} +import mrtjp.projectred.fabrication.circuitparts.{ + CircuitPart, + GateICPart, + ICGateDefinition, + ICGateRenderer +} import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo - class OpGate(meta: Int) extends CircuitOp { var rotation: Int = 0 @@ -55,14 +59,24 @@ class OpGate(meta: Int) extends CircuitOp { } @SideOnly(Side.CLIENT) - override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { val t = orthoPartT(position.subtract(prefboardOffset), scale) doRender(t, rotation, configuration) renderHolo(position.subtract(prefboardOffset), scale, 0x33ffffff) } @SideOnly(Side.CLIENT) - def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = { // Gates can't be dragged, so only the first will be rendered val t = orthoPartT(start - prefboardOffset, scale) doRender(t, rotation, configuration) @@ -80,14 +94,23 @@ class OpGate(meta: Int) extends CircuitOp { doRender(t, rotation, configuration) } - override def renderImageStatic(x: Double, y: Double, width: Double, height: Double): Unit = { + override def renderImageStatic( + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = { val t = orthoGridT(width, height) `with` new Translation(x, y, 0) doRender(t, 0, 0) } @SideOnly(Side.CLIENT) def doRender(t: Transformation, rot: Int, configuration: Int) { - ICGateRenderer.renderWithConfiguration(configuration, Rotation.quarterRotations(rot).at(Vector3.center) `with` t, meta) + ICGateRenderer.renderWithConfiguration( + configuration, + Rotation.quarterRotations(rot).at(Vector3.center) `with` t, + meta + ) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala index 83e3fc4c0..1ac705ceb 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala @@ -14,7 +14,6 @@ import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.circuitparts.CircuitPart import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo - abstract class SimplePlacementOp extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = circuit.getPart(end.x, end.y) == null @@ -24,11 +23,11 @@ abstract class SimplePlacementOp extends CircuitOp { override def getConfiguration(): Int = 0 override def writeOp( - circuit: IntegratedCircuit, - start: Point, - end: Point, - out: MCDataOutput - ) { + circuit: IntegratedCircuit, + start: Point, + end: Point, + out: MCDataOutput + ) { out.writeByte(end.x).writeByte(end.y) } @@ -40,24 +39,34 @@ abstract class SimplePlacementOp extends CircuitOp { @SideOnly(Side.CLIENT) override def renderImage( - x: Double, - y: Double, - width: Double, - height: Double - ): Unit = { + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = { val t = orthoGridT(width, height) `with` new Translation(x, y, 0) doPartRender(t) } @SideOnly(Side.CLIENT) - override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { val t = orthoPartT(position - prefboardOffset, scale) doPartRender(t) renderHolo(position.subtract(prefboardOffset), scale, 0x33ff0000) } @SideOnly(Side.CLIENT) - override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + override def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = { val t = orthoPartT(end - prefboardOffset, scale) doPartRender(t) renderHolo(end - prefboardOffset, scale, 0x44ffffff) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala index 49cc67a21..dde9e45f0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala @@ -16,7 +16,6 @@ import mrtjp.projectred.fabrication.circuitparts.wire._ import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, CircuitPartDefs} import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo - abstract class OpWire extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = circuit.getPart(start.x, start.y) == null @@ -40,16 +39,16 @@ abstract class OpWire extends CircuitOp { val end = Point(in.readInt(), in.readInt()) val corner = start + Point((end - start).vectorize.axialProject) - for(x <- math.min(start.x, corner.x) to math.max(start.x, corner.x)) { - for(y <- math.min(start.y, corner.y) to math.max(start.y, corner.y)) { - if(circuit.getPart(x, y) == null) { + for (x <- math.min(start.x, corner.x) to math.max(start.x, corner.x)) { + for (y <- math.min(start.y, corner.y) to math.max(start.y, corner.y)) { + if (circuit.getPart(x, y) == null) { circuit.setPart(x, y, createPart) } } } - for(x <- math.min(corner.x, end.x) to math.max(corner.x, end.x)) { - for(y <- math.min(corner.y, end.y) to math.max(corner.y, end.y)) { - if(circuit.getPart(x, y) == null) { + for (x <- math.min(corner.x, end.x) to math.max(corner.x, end.x)) { + for (y <- math.min(corner.y, end.y) to math.max(corner.y, end.y)) { + if (circuit.getPart(x, y) == null) { circuit.setPart(x, y, createPart) } } @@ -59,32 +58,72 @@ abstract class OpWire extends CircuitOp { def createPart: CircuitPart @SideOnly(Side.CLIENT) - override def renderHover(position: Vec2, scale: Double, prefboardOffset: Vec2): Unit = { + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { val t = orthoPartT(position.subtract(prefboardOffset), scale) doRender(t, 0) renderHolo(position.subtract(prefboardOffset), scale, 0x33ffffff) } @SideOnly(Side.CLIENT) - override def renderDrag(start: Vec2, end: Vec2, positionsWithParts: Seq[Vec2], scale: Double, prefboardOffset: Vec2): Unit = { + override def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = { val corner = start + (end - start).axialProject - for(x <- math.min(start.dx.toInt, corner.dx.toInt) to math.max(start.dx.toInt, corner.dx.toInt)) { - for(y <- math.min(start.dy.toInt, corner.dy.toInt) to math.max(start.dy.toInt, corner.dy.toInt)) { - if(!positionsWithParts.contains(Point(x, y))) { + for ( + x <- math.min(start.dx.toInt, corner.dx.toInt) to math.max( + start.dx.toInt, + corner.dx.toInt + ) + ) { + for ( + y <- math.min(start.dy.toInt, corner.dy.toInt) to math.max( + start.dy.toInt, + corner.dy.toInt + ) + ) { + if (!positionsWithParts.contains(Point(x, y))) { val t = orthoPartT(Vec2(x, y) - prefboardOffset, scale) doRender(t, 0) } - renderHolo(Vec2(x, y) - prefboardOffset, corner.subtract(prefboardOffset), scale, 0x44ffffff) + renderHolo( + Vec2(x, y) - prefboardOffset, + corner.subtract(prefboardOffset), + scale, + 0x44ffffff + ) } } - for(x <- math.min(corner.dx.toInt, end.dx.toInt) to math.max(corner.dx.toInt, end.dx.toInt)) { - for(y <- math.min(corner.dy.toInt, end.dy.toInt) to math.max(corner.dy.toInt, end.dy.toInt)) { - if(!positionsWithParts.contains(Point(x, y))) { + for ( + x <- math.min(corner.dx.toInt, end.dx.toInt) to math.max( + corner.dx.toInt, + end.dx.toInt + ) + ) { + for ( + y <- math.min(corner.dy.toInt, end.dy.toInt) to math.max( + corner.dy.toInt, + end.dy.toInt + ) + ) { + if (!positionsWithParts.contains(Point(x, y))) { val t = orthoPartT(Vec2(x, y) - prefboardOffset, scale) doRender(t, 0) } - renderHolo(Vec2(x, y) - prefboardOffset, corner.subtract(prefboardOffset), scale, 0x44ffffff) + renderHolo( + Vec2(x, y) - prefboardOffset, + corner.subtract(prefboardOffset), + scale, + 0x44ffffff + ) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala b/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala index cd879d30b..fa4271e64 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/wirepropagation.scala @@ -153,7 +153,3 @@ class ICPropagationRun { class ICPropagation(part: IWireICPart, from: CircuitPart, mode: Int) { def go() { part.updateAndPropagate(from, mode) } } - - - - From 18bca4fe1469ad7da01a90efeb9f74be0b07bed7 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:43:24 +0200 Subject: [PATCH 10/21] Remove CircuitGui file --- .../fabrication/gui/CircuitGui.scala | 107 ------------------ .../fabrication/gui/nodes/PrefboardNode.scala | 18 +-- 2 files changed, 3 insertions(+), 122 deletions(-) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala deleted file mode 100644 index 4b0c50842..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/CircuitGui.scala +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication.gui - -import codechicken.lib.gui.GuiDraw -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.color.Colors -import mrtjp.core.gui.{GuiLib, MCButtonNode, TNode} -import mrtjp.core.vec.{Point, Rect, Size} -import mrtjp.projectred.fabrication.circuitparts.TClientNetCircuitPart -import net.minecraft.client.gui.Gui -import org.lwjgl.input.Keyboard -import org.lwjgl.opengl.GL11 - -trait IGuiCircuitPart extends TClientNetCircuitPart { - @SideOnly(Side.CLIENT) - def createGui: CircuitGui -} - -class CircuitGui(val part: IGuiCircuitPart) extends Gui with TNode { - var size = Size.zeroSize - - override def frame = Rect(position, size) - - var lineColor = Colors.LIME.argb(0xaa) - var linePointerCalc = { () => Point.zeroPoint } - - private def moverFrame = Rect(position + Point(4, 9), Size(4, 6)) - - private var mouseDown = false - private var mouseInit = Point.zeroPoint - - { - val close = new MCButtonNode - close.position = Point(4, 4) - close.size = Size(5, 5) - close.clickDelegate = { () => removeFromParent() } - addChild(close) - } - - override def frameUpdate_Impl(mouse: Point, rframe: Float) { - if (mouseDown) { - position += mouse - mouseInit - mouseInit = mouse - } - - if (part.world == null) removeFromParent() - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) - GuiDraw.drawRect( - moverFrame.x, - moverFrame.y, - moverFrame.width, - moverFrame.height, - Colors.LIGHT_GREY.argb - ) - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - val from = linePointerCalc() - val to = from.clamp(frame) - GL11.glColor4d(1, 1, 1, 1) - GuiLib.drawLine(from.x, from.y, to.x, to.y, lineColor) - GuiDraw.drawRect(to.x - 3, to.y - 3, 6, 6, lineColor) - } - - override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { - if (parent == null) - false // we cant check for consume here, so manually check if closed - else - hitTest(p).find(_.isInstanceOf[CircuitGui]) match { - case Some(gui) if gui == this => - val guis = parent.childrenByZ.collect { case g: CircuitGui => g } - val otherGuis = guis.filter(_ != this) - for (i <- otherGuis.indices) - otherGuis(i).pushZTo(0.1 * i) - pushZTo(0.1 * otherGuis.size) - - if (moverFrame.contains(p)) { - mouseDown = true - mouseInit = p - } - true - case _ => false - } - } - - override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { - mouseDown = false - false - } - - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = - if (!consumed && keycode == Keyboard.KEY_ESCAPE) { - removeFromParent() - true - } else false -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 912c56a6a..08dc73428 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -10,22 +10,10 @@ import mrtjp.core.gui.{ClipNode, TNode} import mrtjp.core.vec.{Point, Rect, Vec2} import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic -import mrtjp.projectred.fabrication.circuitparts.latches.{ - SRLatch, - TransparentLatch -} -import mrtjp.projectred.fabrication.circuitparts.misc.{ - Counter, - DecRandomizer, - Randomizer -} +import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, TransparentLatch} +import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, DecRandomizer, Randomizer} import mrtjp.projectred.fabrication.circuitparts.primitives._ -import mrtjp.projectred.fabrication.circuitparts.timing.{ - Repeater, - Sequencer, - StateCell -} -import mrtjp.projectred.fabrication.gui.{CircuitGui, IGuiCircuitPart} +import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} import mrtjp.projectred.fabrication.operations._ import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} import net.minecraft.util.EnumChatFormatting From 8b18db8dcba78946cfcd94298c3571b0f3b9cbed Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:51:05 +0200 Subject: [PATCH 11/21] Fixed selection IO Mode. Improved Colorpicker --- .../circuitparts/io/IOGateICPart.scala | 8 ++++ .../circuitparts/io/TFreqIOICGateLogic.scala | 16 ------- .../fabrication/gui/nodes/PrefboardNode.scala | 17 ++++++-- .../gui/nodes/configuration/ColorPicker.scala | 42 +++++++++++++++---- .../ConfigurationBundledIO.scala | 9 ++-- .../configuration/ConfigurationSimpleIO.scala | 10 +++-- 6 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala index fb704a64d..3afc58fad 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/IOGateICPart.scala @@ -42,6 +42,14 @@ class IOGateICPart f.gate.onChange() case _ => } + case 6 => + getLogicIO match { + case f: IOICGateLogic => + f.gate.setShape(in.readByte()) + this.sendShapeUpdate() + f.gate.onChange() + case _ => + } case _ => super.readClientPacket(in, key) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala index d23748508..bff3b5e8f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/io/TFreqIOICGateLogic.scala @@ -40,22 +40,6 @@ trait TFreqIOICGateLogic extends IOICGateLogic { gate.writeStreamOf(12).writeByte(freq) } - def freqUp() { - if (freq < 15) { - freq += 1 - sendFreqUpdate() - gate.onChange() - } - } - - def freqDown() { - if (freq > 0) { - freq -= 1 - sendFreqUpdate() - gate.onChange() - } - } - override def resolveInputFromWorld = if ((gate.world.iostate(gate.rotation) & 1 << freq) != 0) 255 else 0 diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 08dc73428..60de4eb21 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -10,10 +10,21 @@ import mrtjp.core.gui.{ClipNode, TNode} import mrtjp.core.vec.{Point, Rect, Vec2} import mrtjp.projectred.fabrication.circuitparts.ICGateDefinition import mrtjp.projectred.fabrication.circuitparts.io.IOICGateLogic -import mrtjp.projectred.fabrication.circuitparts.latches.{SRLatch, TransparentLatch} -import mrtjp.projectred.fabrication.circuitparts.misc.{Counter, DecRandomizer, Randomizer} +import mrtjp.projectred.fabrication.circuitparts.latches.{ + SRLatch, + TransparentLatch +} +import mrtjp.projectred.fabrication.circuitparts.misc.{ + Counter, + DecRandomizer, + Randomizer +} import mrtjp.projectred.fabrication.circuitparts.primitives._ -import mrtjp.projectred.fabrication.circuitparts.timing.{Repeater, Sequencer, StateCell} +import mrtjp.projectred.fabrication.circuitparts.timing.{ + Repeater, + Sequencer, + StateCell +} import mrtjp.projectred.fabrication.operations._ import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} import net.minecraft.util.EnumChatFormatting diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala index 5227b692b..4d1e885cf 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ColorPicker.scala @@ -10,7 +10,7 @@ import mrtjp.core.color.Colors import mrtjp.core.gui.TNode import mrtjp.core.vec.{Point, Rect, Size} -class ColorPicker(onPickColor: Int => Unit) extends TNode { +class ColorPicker(var color: Int, onPickColor: Int => Unit) extends TNode { var size = Size.zeroSize @@ -20,13 +20,36 @@ class ColorPicker(onPickColor: Int => Unit) extends TNode { val edge = size.width / 4 for (i <- 0 to 15) { - GuiDraw.drawRect( - position.x + (i % 4) * edge, - position.y + (i / 4) * edge, - edge, - edge, - Colors(i).argb - ) + // Top Left Corner + val x = position.x + (i % 4) * edge + val y = position.y + (i / 4) * edge + + if (i != color) { + GuiDraw.drawRect( + x, + y, + edge, + edge, + Colors(i).argb + ) + } else { + // Border + GuiDraw.drawRect( + x, + y, + edge, + edge, + 0xffff7777 + ) + // Color + GuiDraw.drawRect( + x + 2, + y + 2, + edge - 4, + edge - 4, + Colors(i).argb + ) + } } } @@ -39,7 +62,8 @@ class ColorPicker(onPickColor: Int => Unit) extends TNode { val relPos = p.subtract(position) val index = (relPos.y / (size.height / 4)) * 4 + relPos.x / (size.width / 4) - onPickColor(index) + color = index + onPickColor(color) true } else false diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala index 5215cd0bd..e49bdae48 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationBundledIO.scala @@ -10,9 +10,12 @@ import mrtjp.projectred.fabrication.circuitparts.io.IOGateICPart class ConfigurationBundledIO(gate: IOGateICPart) extends ConfigurationSimpleIO(gate) { - val colorPicker = new ColorPicker(onPickColor = color => { - gate.sendFrequency(color) - }) + val colorPicker = new ColorPicker( + gate.getIOMode, + onPickColor = color => { + gate.sendFrequency(color) + } + ) colorPicker.position = Point(5, 100) colorPicker.size = Size(60, 60) addChild(colorPicker) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala index 0ada8a0a5..fca252e6a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationSimpleIO.scala @@ -25,7 +25,7 @@ class ConfigurationSimpleIO(gate: IOGateICPart) in.position = Point(5, 80) in.size = Size(20, 15) in.clickDelegate = { () => - gate.sendClientPacket(_.writeByte(1)) + gate.sendClientPacket(_.writeByte(6).writeByte(0)) } addChild(in) @@ -35,7 +35,9 @@ class ConfigurationSimpleIO(gate: IOGateICPart) } out.position = Point(25, 80) out.size = Size(20, 15) - out.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + out.clickDelegate = { () => + gate.sendClientPacket(_.writeByte(6).writeByte(1)) + } addChild(out) val inout = new IconButtonNode { @@ -44,7 +46,9 @@ class ConfigurationSimpleIO(gate: IOGateICPart) } inout.position = Point(45, 80) inout.size = Size(20, 15) - inout.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } + inout.clickDelegate = { () => + gate.sendClientPacket(_.writeByte(6).writeByte(2)) + } addChild(inout) private def renderIcon(icon: Int, position: Point): Unit = { From 33880b7f12034d40761a826fb3d8943f6659d2b1 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:59:28 +0200 Subject: [PATCH 12/21] Handle ID of CircuitOp in the CircuitOp Trait itself. Added comments. Removed unused code --- .../fabrication/IntegratedCircuit.scala | 8 +-- .../fabrication/operations/CircuitOp.scala | 67 +++++++++++-------- .../operations/CircuitOpErase.scala | 3 +- .../fabrication/operations/OpGate.scala | 7 +- .../operations/SimplePlacementOp.scala | 1 + .../fabrication/operations/WireOps.scala | 1 + 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index fac9a0cb3..e0675ccc6 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -136,7 +136,7 @@ class IntegratedCircuit { setPart_do(in.readInt(), in.readInt(), part) part.readDesc(in) case 2 => removePart(in.readInt(), in.readInt()) - case 3 => CircuitOp.getOperation(in.readUByte()).readOp(this, in) + case 3 => CircuitOp.readOp(this, in) case 4 => getPart(in.readInt(), in.readInt()) match { case g: TClientNetCircuitPart => g.readClientPacket(in) @@ -161,7 +161,7 @@ class IntegratedCircuit { def sendOpUse(op: CircuitOp, start: Point, end: Point) = { if (op.checkOp(this, start, end)) { - op.writeOp(this, start, end, network.getICStreamOf(3).writeByte(op.id)) + op.writeOp(this, start, end, network.getICStreamOf(3)) true } else false } @@ -174,10 +174,6 @@ class IntegratedCircuit { writer(s) } - def sendIOUpdate(r: Int) { - network.getICStreamOf(5).writeByte(r).writeInt(iostate(r)) - } - def sendInputUpdate(r: Int) { network.getICStreamOf(6).writeByte(r).writeShort(iostate(r) & 0xffff) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index 05f3bf053..bb92292ea 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -9,6 +9,7 @@ import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.gui.GuiDraw import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.{Point, Size, Vec2} +import mrtjp.projectred.fabrication.circuitparts.CircuitPart import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} trait CircuitOp { @@ -20,14 +21,18 @@ trait CircuitOp { def getConfiguration(): Int + /** Writes this Circuit operation to the stream. Also writes id + */ def writeOp( circuit: IntegratedCircuit, start: Point, end: Point, out: MCDataOutput - ) + ): Unit = { + out.writeByte(id) + } - def readOp(circuit: IntegratedCircuit, in: MCDataInput) + protected def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit @SideOnly(Side.CLIENT) def getOpName: String @@ -81,11 +86,28 @@ trait CircuitOp { } object CircuitOp { - def getOperation(id: Int) = CircuitOpDefs(id).getOp - /** Draw one Tile + type List = Seq[(Point, CircuitOp)] + + /** Read operation from stream and create Circuit Part in circuit + * @param circuit + * The circuit in which the part is being created + * @param in + * Stream + */ + def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit = { + getOperation(in.readUByte()).readOp(circuit, in) + } + + /** IDs as in CircuitOpDefs -> CircuitOp + */ + private def getOperation(id: Int): CircuitOp = CircuitOpDefs(id).getOp + + /** Draw a rectangle in the size of one tile * @param position * In Grid Coordinates + * @param colour + * in ARGB */ def renderHolo(position: Vec2, scale: Double, colour: Int): Unit = { val start = position * RenderCircuit.BASE_SCALE * scale @@ -102,15 +124,21 @@ object CircuitOp { ) } - /** Draw Multiple tiles in a rect excluding end - * @param start + /** Same as other renderHolo, only for drawing a rectangle over multiple cells + * of the grid + * @param topLeft * In Grid Coordinates - * @param end - * In Grid coordinates + * @param bottomRight + * In Grid coordinates, excluding that cell */ - def renderHolo(start: Vec2, end: Vec2, scale: Double, colour: Int): Unit = { - val s = start * RenderCircuit.BASE_SCALE * scale - val e = end * RenderCircuit.BASE_SCALE * scale + def renderHolo( + topLeft: Vec2, + bottomRight: Vec2, + scale: Double, + colour: Int + ): Unit = { + val s = topLeft * RenderCircuit.BASE_SCALE * scale + val e = bottomRight * RenderCircuit.BASE_SCALE * scale GuiDraw.drawRect( s.dx.toInt, s.dy.toInt, @@ -120,23 +148,6 @@ object CircuitOp { ) } - def renderHolo( - x: Double, - y: Double, - xSize: Double, - ySize: Double, - csize: Size, - point: Point, - colour: Int - ) { - val x1 = (x + xSize / csize.width * point.x).toInt - val y1 = (y + ySize / csize.height * point.y).toInt - val x2 = (x + xSize / csize.width * (point.x + 1)).toInt - val y2 = (y + ySize / csize.height * (point.y + 1)).toInt - - GuiDraw.drawRect(x1, y1, x2 - x1, y2 - y1, colour) - } - def partsBetweenPoints( start: Vec2, end: Vec2, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala index d57e673e0..b533e5368 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala @@ -28,11 +28,12 @@ class CircuitOpErase extends CircuitOp { end: Point, out: MCDataOutput ) { + super.writeOp(circuit, start, end, out) out.writeInt(start.x).writeInt(start.y) out.writeInt(end.x).writeInt(end.y) } - override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { + override def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit = { val start = Point(in.readInt(), in.readInt()) val end = Point(in.readInt(), in.readInt()) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index 588a435b2..04eaad131 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -39,22 +39,23 @@ class OpGate(meta: Int) extends CircuitOp { end: Point, out: MCDataOutput ) { + super.writeOp(circuit, start, end, out) out.writeByte(start.x).writeByte(start.y) out.writeByte(rotation) out.writeByte(configuration) } override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { - val point = Point(in.readByte(), in.readByte()) + val position = Point(in.readByte(), in.readByte()) rotation = in.readUByte() configuration = in.readUByte() - if (circuit.getPart(point) == null) { + if (circuit.getPart(position) == null) { val part = CircuitPart .createPart(ICGateDefinition(meta).gateType) .asInstanceOf[GateICPart] part.preparePlacement(rotation, configuration, meta) - circuit.setPart(point, part) + circuit.setPart(position, part) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala index 1ac705ceb..444ffec48 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala @@ -28,6 +28,7 @@ abstract class SimplePlacementOp extends CircuitOp { end: Point, out: MCDataOutput ) { + super.writeOp(circuit, start, end, out) out.writeByte(end.x).writeByte(end.y) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala index dde9e45f0..19da3d50d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala @@ -30,6 +30,7 @@ abstract class OpWire extends CircuitOp { end: Point, out: MCDataOutput ) { + super.writeOp(circuit, start, end, out) out.writeInt(start.x).writeInt(start.y) out.writeInt(end.x).writeInt(end.y) } From 61426aa1a905339dd1a92b64099cc6c103baeb32 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:45:32 +0200 Subject: [PATCH 13/21] Added Copy, Cut and Paste Tools --- .../fabrication/IntegratedCircuit.scala | 55 +++++++---- .../circuitparts/CircuitPart.scala | 4 +- .../fabrication/circuitparts/GateICPart.scala | 15 ++- .../circuitparts/wire/AlloyWire.scala | 2 +- .../circuitparts/wire/BundledCable.scala | 2 +- .../circuitparts/wire/Button.scala | 2 +- .../circuitparts/wire/InsulatedWire.scala | 2 +- .../fabrication/circuitparts/wire/Lever.scala | 2 +- .../circuitparts/wire/RedstoneTorch.scala | 2 +- .../fabrication/gui/GuiICWorkbench.scala | 3 + .../fabrication/gui/nodes/PrefboardNode.scala | 8 +- .../fabrication/operations/CircuitOp.scala | 27 +++-- .../operations/CircuitOpDefs.scala | 11 ++- .../fabrication/operations/OpAreaBase.scala | 98 +++++++++++++++++++ .../fabrication/operations/OpCopy.scala | 50 ++++++++++ .../fabrication/operations/OpCut.scala | 36 +++++++ .../{CircuitOpErase.scala => OpErase.scala} | 24 ++--- .../fabrication/operations/OpGate.scala | 9 +- .../fabrication/operations/OpPaste.scala | 73 ++++++++++++++ ...cementOp.scala => OpSimplePlacement.scala} | 11 ++- .../{ICPartOps.scala => OpsICPart.scala} | 6 +- .../{WireOps.scala => OpsWire.scala} | 9 +- 22 files changed, 380 insertions(+), 71 deletions(-) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala rename src/main/scala/mrtjp/projectred/fabrication/operations/{CircuitOpErase.scala => OpErase.scala} (78%) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala rename src/main/scala/mrtjp/projectred/fabrication/operations/{SimplePlacementOp.scala => OpSimplePlacement.scala} (89%) rename src/main/scala/mrtjp/projectred/fabrication/operations/{ICPartOps.scala => OpsICPart.scala} (87%) rename src/main/scala/mrtjp/projectred/fabrication/operations/{WireOps.scala => OpsWire.scala} (97%) diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index e0675ccc6..168fb4f27 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -129,23 +129,30 @@ class IntegratedCircuit { // etc } - def read(in: MCDataInput, key: Int) = key match { - case 0 => readDesc(in) - case 1 => - val part = CircuitPart.createPart(in.readUByte()) - setPart_do(in.readInt(), in.readInt(), part) - part.readDesc(in) - case 2 => removePart(in.readInt(), in.readInt()) - case 3 => CircuitOp.readOp(this, in) - case 4 => - getPart(in.readInt(), in.readInt()) match { - case g: TClientNetCircuitPart => g.readClientPacket(in) - case _ => log.error("Server IC stream received invalid client packet") + def read(in: MCDataInput, key: Int) = { + if (!network.isRemote) { + key match { + case 3 => CircuitOp.readOp(this, in) + case 4 => + getPart(in.readInt(), in.readInt()) match { + case g: TClientNetCircuitPart => g.readClientPacket(in) + case _ => + log.error("Server IC stream received invalid client packet") + } + } + } else { + key match { + case 0 => readDesc(in) + case 1 => + val part = CircuitPart.createPart(in.readUByte()) + setPart_do(in.readInt(), in.readInt(), part) + part.readDesc(in) + case 2 => removePart(in.readInt(), in.readInt()) + case 5 => iostate(in.readUByte()) = in.readInt() + case 6 => setInput(in.readUByte(), in.readShort()) + case 7 => setOutput(in.readUByte(), in.readShort()) } - case 5 => iostate(in.readUByte()) = in.readInt() - case 6 => setInput(in.readUByte(), in.readShort()) - case 7 => setOutput(in.readUByte(), in.readShort()) - case _ => + } } def sendPartAdded(part: CircuitPart) { @@ -161,7 +168,7 @@ class IntegratedCircuit { def sendOpUse(op: CircuitOp, start: Point, end: Point) = { if (op.checkOp(this, start, end)) { - op.writeOp(this, start, end, network.getICStreamOf(3)) + op.clientSendOperation(this, start, end, network.getICStreamOf(3)) true } else false } @@ -247,6 +254,20 @@ class IntegratedCircuit { def getPart(x: Int, y: Int): CircuitPart = parts.getOrElse((x, y), null) + def getParts( + topLeft: Point, + bottomRight: Point + ): Map[(Int, Int), CircuitPart] = { + parts + .filter(element => + element._1._1 >= topLeft.x && + element._1._1 < bottomRight.x && + element._1._2 >= topLeft.y && + element._1._2 < bottomRight.y + ) + .toMap + } + def removePart(x: Int, y: Int) { val part = getPart(x, y) if (part != null) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala index e9db03410..d010a6cb9 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala @@ -87,8 +87,10 @@ abstract class CircuitPart { @SideOnly(Side.CLIENT) def getPartName: String + /** Returns Circuit Operation, that would create this CircuitPart + */ @SideOnly(Side.CLIENT) - def getPickOp: CircuitOp = null + def getCircuitOperation: CircuitOp = null @SideOnly(Side.CLIENT) def getRolloverData(detailLevel: Int): Seq[String] = diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala index 179c410c5..c54c0d7fc 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/GateICPart.scala @@ -8,7 +8,11 @@ package mrtjp.projectred.fabrication.circuitparts import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.vec.Transformation import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.projectred.fabrication.operations.CircuitOpDefs +import mrtjp.projectred.fabrication.operations.{ + CircuitOp, + CircuitOpDefs, + OpGate +} import net.minecraft.nbt.NBTTagCompound abstract class GateICPart @@ -207,6 +211,11 @@ abstract class GateICPart } @SideOnly(Side.CLIENT) - override def getPickOp = - CircuitOpDefs.values(CircuitOpDefs.SimpleIO.ordinal + subID).getOp + override def getCircuitOperation: CircuitOp = { + val op = new OpGate(subID) + op.id = CircuitOpDefs.SimpleIO.ordinal + subID + op.rotation = orientation + op.configuration = gateShape + op + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala index d6fde5e46..fce7b7181 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala @@ -26,7 +26,7 @@ class AlloyWireICPart extends RedwireICPart { override def getPartName = "Alloy wire" @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs.AlloyWire.getOp + override def getCircuitOperation = CircuitOpDefs.AlloyWire.getOp } object RenderICAlloyWire { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala index c319ae793..40f43675d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala @@ -194,7 +194,7 @@ class BundledCableICPart else "") + "Bundled cable" @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs + override def getCircuitOperation = CircuitOpDefs .values(CircuitOpDefs.NeutralBundledCable.ordinal + colour + 1) .getOp diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala index 9c86bb0c0..13f8f902b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Button.scala @@ -112,7 +112,7 @@ class ButtonICPart override def getPartName = "Button" @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs.Button.getOp + override def getCircuitOperation = CircuitOpDefs.Button.getOp @SideOnly(Side.CLIENT) override def getRolloverData(detailLevel: Int) = { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala index 96f52861e..130dd70c4 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/InsulatedWire.scala @@ -68,7 +68,7 @@ class InsulatedWireICPart extends RedwireICPart with IInsulatedRedwireICPart { override def getPartName = Colors(colour & 0xff).name + " Insulated wire" @SideOnly(Side.CLIENT) - override def getPickOp = + override def getCircuitOperation = CircuitOpDefs .values(CircuitOpDefs.WhiteInsulatedWire.ordinal + colour) .getOp diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala index c705ffbca..e755e06cc 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/Lever.scala @@ -86,7 +86,7 @@ class LeverICPart override def getPartName = "Lever" @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs.Lever.getOp + override def getCircuitOperation = CircuitOpDefs.Lever.getOp @SideOnly(Side.CLIENT) override def getRolloverData(detailLevel: Int) = { diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala index 1ad689b84..796650bc7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/RedstoneTorch.scala @@ -39,7 +39,7 @@ class TorchICPart override def getPartName = "Torch" @SideOnly(Side.CLIENT) - override def getPickOp = CircuitOpDefs.Torch.getOp + override def getCircuitOperation = CircuitOpDefs.Torch.getOp @SideOnly(Side.CLIENT) override def renderDynamic( diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 9db0f28e2..88c8e9f74 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -105,6 +105,9 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { } addToolset("", Seq(Erase)) + addToolset("", Seq(Cut)) + addToolset("", Seq(Copy)) + addToolset("", Seq(Paste)) addToolset("Debug", Seq(Torch, Lever, Button)) addToolset("", Seq(AlloyWire)) addToolsetRange("Insulated wires", WhiteInsulatedWire, BlackInsulatedWire) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 60de4eb21..afe23a2aa 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -106,14 +106,14 @@ class PrefboardNode( if (rayTest(mouse) && !leftMouseDown) { // Render: Erase always, other stuff only if there are no already placed parts under the cursor currentOp match { - case _: OpGate | _: OpWire | _: SimplePlacementOp => + case _: OpGate | _: OpWire | _: OpSimplePlacement => if (circuit.getPart(toGridPoint(mouse.vectorize)) == null) currentOp.renderHover( toGridPoint(mouse).vectorize, scale, offset ) - case _: CircuitOpErase => + case _: OpAreaBase => currentOp.renderHover(toGridPoint(mouse).vectorize, scale, offset) } } else if (leftMouseDown) { @@ -271,6 +271,8 @@ class PrefboardNode( case op: OpGate => op.rotation += 1 if (op.rotation == 4) op.rotation = 0 + case op: OpAreaBase => + op.rotateClipboard() case _ => } } @@ -337,7 +339,7 @@ class PrefboardNode( val part = circuit.getPart(toGridPoint(pos.vectorize)) opPickDelegate(if (part != null) { setConfigNode(null) - part.getPickOp + part.getCircuitOperation } else null) updatePreview() } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index bb92292ea..ccea33f6d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -8,22 +8,30 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} import codechicken.lib.gui.GuiDraw import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.vec.{Point, Size, Vec2} -import mrtjp.projectred.fabrication.circuitparts.CircuitPart +import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.{IntegratedCircuit, RenderCircuit} +/** Circuit Operations describe the communication between server and client: + * + * - 1: Client sends operation to the server with [[clientSendOperation]] + * - 2: Server receives operation with [[serverReceiveOperation]] and sends + * updates back to the client(s). The sending back is done in + * [[IntegratedCircuit]] + * - 3: Client(s) receive updated circuit. This step is handled in + * [[IntegratedCircuit]] + */ trait CircuitOp { var id = -1 + /** Can this operation be executed + */ def checkOp(circuit: IntegratedCircuit, start: Point, end: Point): Boolean def getRotation(): Int def getConfiguration(): Int - /** Writes this Circuit operation to the stream. Also writes id - */ - def writeOp( + def clientSendOperation( circuit: IntegratedCircuit, start: Point, end: Point, @@ -32,7 +40,10 @@ trait CircuitOp { out.writeByte(id) } - protected def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit + protected def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ): Unit @SideOnly(Side.CLIENT) def getOpName: String @@ -87,8 +98,6 @@ trait CircuitOp { object CircuitOp { - type List = Seq[(Point, CircuitOp)] - /** Read operation from stream and create Circuit Part in circuit * @param circuit * The circuit in which the part is being created @@ -96,7 +105,7 @@ object CircuitOp { * Stream */ def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit = { - getOperation(in.readUByte()).readOp(circuit, in) + getOperation(in.readUByte()).serverReceiveOperation(circuit, in) } /** IDs as in CircuitOpDefs -> CircuitOp diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala index 8af05fb4e..b269098fb 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpDefs.scala @@ -12,12 +12,15 @@ object CircuitOpDefs extends Enum { type EnumVal = OpDef // tools - val Erase = OpDef(new CircuitOpErase) + val Erase = OpDef(new OpErase) + val Cut = OpDef(new OpCut) + val Copy = OpDef(new OpCopy) + val Paste = OpDef(new OpPaste) // primitives - val Torch = OpDef(new CircuitOpTorch) - val Lever = OpDef(new CircuitOpLever) - val Button = OpDef(new CircuitOpButton) + val Torch = OpDef(new OpTorch) + val Lever = OpDef(new OpLever) + val Button = OpDef(new OpButton) // alloy wire val AlloyWire = OpDef(new OpAlloyWire) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala new file mode 100644 index 000000000..b32671d00 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.vec.{Point, Vec2} +import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.projectred.fabrication.circuitparts.CircuitPart +import mrtjp.projectred.fabrication.operations.OpAreaBase.clipboard + +object OpAreaBase { + type List = Seq[(Point, CircuitOp)] + + /** clipboard for copy/past/cut operations + */ + var clipboard: List = Seq() +} + +abstract class OpAreaBase extends CircuitOp { + + override def checkOp( + circuit: IntegratedCircuit, + start: Point, + end: Point + ): Boolean = true + + override def getConfiguration(): Int = 0 + + override def getRotation(): Int = 0 + + /** Draw partially transparent rectangle over area + */ + @SideOnly(Side.CLIENT) + override def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = { + var (topLeft, bottomRight) = ( + Vec2( + math.min(start.dx, end.dx), + math.min(start.dy, end.dy) + ) - prefboardOffset, + Vec2( + math.max(start.dx, end.dx), + math.max(start.dy, end.dy) + ) - prefboardOffset + ) + bottomRight = bottomRight.add(1, 1) + CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) + } + + /** Saves parts to [[OpAreaBase.clipboard]] + */ + protected def saveToClipboard(parts: Map[(Int, Int), CircuitPart]): Unit = { + val (x, y) = if (parts.nonEmpty) { + parts + .reduce((a, b) => + ((math.min(a._1._1, b._1._1), math.min(a._1._2, b._1._2)), null) + ) + ._1 + } else (0, 0) + OpAreaBase.clipboard = parts + .map(element => { + ( + Point(element._1._1 - x, element._1._2 - y), + element._2.getCircuitOperation + ) + }) + .toList + } + + def rotateClipboard(): Unit = { + if (clipboard.size > 1) { + val p2 = clipboard + .reduce((a, b) => + (Point(math.max(a._1.x, b._1.x), math.max(a._1.y, b._1.y)), null) + ) + ._1 + clipboard = clipboard.map { item => + ( + Point(-item._1.y + p2.y, item._1.x), + item._2 match { + case a: OpGate => + a.rotation = (a.rotation + 1) % 4 + a + case a => a + } + ) + }.toList + } + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala new file mode 100644 index 000000000..e48bca159 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import mrtjp.core.vec.{Point, Vec2} +import mrtjp.projectred.fabrication.IntegratedCircuit + +class OpCopy extends OpAreaBase { + + override def clientSendOperation( + circuit: IntegratedCircuit, + start: Point, + end: Point, + out: MCDataOutput + ): Unit = { + // Save Parts in clipboard (only client) + val topLeft = Point(math.min(start.x, end.x), math.min(start.y, end.y)) + val bottomRight = Point(math.max(start.x, end.x), math.max(start.y, end.y)) + val parts = circuit.getParts(topLeft, bottomRight + Point(1, 1)) + saveToClipboard(parts) + super.clientSendOperation(circuit, start, end, out) + } + + // Nothing to process + override protected def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ): Unit = {} + + override def getOpName: String = "Copy" + + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { + // TODO + } + + override def renderImage( + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = {} +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala new file mode 100644 index 000000000..161bf6537 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.data.MCDataOutput +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.IntegratedCircuit + +class OpCut extends OpErase { + override def clientSendOperation( + circuit: IntegratedCircuit, + start: Point, + end: Point, + out: MCDataOutput + ): Unit = { + // Save Parts in clipboard (only client + val topLeft = Point(math.min(start.x, end.x), math.min(start.y, end.y)) + val bottomRight = Point(math.max(start.x, end.x), math.max(start.y, end.y)) + val parts = circuit.getParts(topLeft, bottomRight + Point(1, 1)) + saveToClipboard(parts) + // Delete parts + super.clientSendOperation(circuit, start, end, out) + } + + override def renderImage( + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = {} + + override def getOpName: String = "Cut" +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala similarity index 78% rename from src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala index b533e5368..11bde7e53 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala @@ -14,26 +14,27 @@ import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.ICComponentStore._ import mrtjp.projectred.fabrication.IntegratedCircuit -class CircuitOpErase extends CircuitOp { +class OpErase extends OpAreaBase { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = true - override def getRotation(): Int = 0 - override def getConfiguration(): Int = 0 - override def writeOp( + override def clientSendOperation( circuit: IntegratedCircuit, start: Point, end: Point, out: MCDataOutput ) { - super.writeOp(circuit, start, end, out) + super.clientSendOperation(circuit, start, end, out) out.writeInt(start.x).writeInt(start.y) out.writeInt(end.x).writeInt(end.y) } - override def readOp(circuit: IntegratedCircuit, in: MCDataInput): Unit = { + override def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ): Unit = { val start = Point(in.readInt(), in.readInt()) val end = Point(in.readInt(), in.readInt()) @@ -71,7 +72,6 @@ class CircuitOpErase extends CircuitOp { CircuitOp.renderHolo(position - prefboardOffset, scale, 0x33ff0000) } - @SideOnly(Side.CLIENT) override def renderDrag( start: Vec2, end: Vec2, @@ -79,14 +79,8 @@ class CircuitOpErase extends CircuitOp { scale: Double, prefboardOffset: Vec2 ): Unit = { - var (topLeft, bottomRight) = ( - Vec2(math.min(start.dx, end.dx), math.min(start.dy, end.dy)) - .subtract(prefboardOffset), - Vec2(math.max(start.dx, end.dx), math.max(start.dy, end.dy)) - .subtract(prefboardOffset) - ) - bottomRight = bottomRight.add(1, 1) - CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) + super.renderDrag(start, end, positionsWithParts, scale, prefboardOffset) + // Mark elements that are going to get removed for (posWithPart <- positionsWithParts) { CircuitOp.renderHolo(posWithPart - prefboardOffset, scale, 0x44ff0000) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index 04eaad131..fca79f84f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -33,19 +33,22 @@ class OpGate(meta: Int) extends CircuitOp { override def getConfiguration(): Int = configuration - override def writeOp( + override def clientSendOperation( circuit: IntegratedCircuit, start: Point, end: Point, out: MCDataOutput ) { - super.writeOp(circuit, start, end, out) + super.clientSendOperation(circuit, start, end, out) out.writeByte(start.x).writeByte(start.y) out.writeByte(rotation) out.writeByte(configuration) } - override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { + override def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ) { val position = Point(in.readByte(), in.readByte()) rotation = in.readUByte() configuration = in.readUByte() diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala new file mode 100644 index 000000000..506652956 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.operations + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import mrtjp.core.vec.{Point, Vec2} +import mrtjp.projectred.fabrication.IntegratedCircuit + +class OpPaste extends OpAreaBase { + + override def checkOp( + circuit: IntegratedCircuit, + start: Point, + end: Point + ): Boolean = { + OpAreaBase.clipboard.forall(op => circuit.getPart(start + op._1) == null) + } + + override def clientSendOperation( + circuit: IntegratedCircuit, + start: Point, + end: Point, + out: MCDataOutput + ): Unit = { + super.clientSendOperation(circuit, start, end, out) + out.writeInt(OpAreaBase.clipboard.size) + OpAreaBase.clipboard.foreach { op => + op._2.clientSendOperation(circuit, start + op._1, end + op._1, out) + } + } + + override protected def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ): Unit = { + for (_ <- 0 until in.readInt()) { + CircuitOp.readOp(circuit, in) + } + } + + override def getOpName: String = "Paste" + + override def renderHover( + position: Vec2, + scale: Double, + prefboardOffset: Vec2 + ): Unit = { + for (part <- OpAreaBase.clipboard) { + part._2.renderHover(position + part._1.vectorize, scale, prefboardOffset) + } + } + + override def renderDrag( + start: Vec2, + end: Vec2, + positionsWithParts: Seq[Vec2], + scale: Double, + prefboardOffset: Vec2 + ): Unit = + renderHover(start, scale, prefboardOffset) + + override def renderImage( + x: Double, + y: Double, + width: Double, + height: Double + ): Unit = { + // TODO render paste icon + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala similarity index 89% rename from src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala index 444ffec48..074306186 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/SimplePlacementOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala @@ -14,7 +14,7 @@ import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.circuitparts.CircuitPart import mrtjp.projectred.fabrication.operations.CircuitOp.renderHolo -abstract class SimplePlacementOp extends CircuitOp { +abstract class OpSimplePlacement extends CircuitOp { override def checkOp(circuit: IntegratedCircuit, start: Point, end: Point) = circuit.getPart(end.x, end.y) == null @@ -22,17 +22,20 @@ abstract class SimplePlacementOp extends CircuitOp { override def getConfiguration(): Int = 0 - override def writeOp( + override def clientSendOperation( circuit: IntegratedCircuit, start: Point, end: Point, out: MCDataOutput ) { - super.writeOp(circuit, start, end, out) + super.clientSendOperation(circuit, start, end, out) out.writeByte(end.x).writeByte(end.y) } - override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { + override def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ) { val point = Point(in.readUByte(), in.readUByte()) if (circuit.getPart(point.x, point.y) == null) circuit.setPart(point.x, point.y, createPart) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala similarity index 87% rename from src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala index 0d9ccac72..e22ef7fe5 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/ICPartOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala @@ -14,7 +14,7 @@ import mrtjp.projectred.fabrication.circuitparts.wire.{ RenderICTorch } -class CircuitOpTorch extends SimplePlacementOp { +class OpTorch extends OpSimplePlacement { override def doPartRender(t: Transformation) = RenderICTorch.render(t, true) override def createPart = CircuitPartDefs.Torch.createPart @@ -23,7 +23,7 @@ class CircuitOpTorch extends SimplePlacementOp { override def getOpName = "Torch" } -class CircuitOpButton extends SimplePlacementOp { +class OpButton extends OpSimplePlacement { override def doPartRender(t: Transformation) { RenderICButton.prepairInv() RenderICButton.render(t, true) @@ -35,7 +35,7 @@ class CircuitOpButton extends SimplePlacementOp { override def getOpName = "Button" } -class CircuitOpLever extends SimplePlacementOp { +class OpLever extends OpSimplePlacement { override def doPartRender(t: Transformation) { RenderICLever.prepairInv() RenderICLever.render(t, true) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala similarity index 97% rename from src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala rename to src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala index 19da3d50d..f187a3d82 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/WireOps.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala @@ -24,18 +24,21 @@ abstract class OpWire extends CircuitOp { override def getConfiguration(): Int = 0 - override def writeOp( + override def clientSendOperation( circuit: IntegratedCircuit, start: Point, end: Point, out: MCDataOutput ) { - super.writeOp(circuit, start, end, out) + super.clientSendOperation(circuit, start, end, out) out.writeInt(start.x).writeInt(start.y) out.writeInt(end.x).writeInt(end.y) } - override def readOp(circuit: IntegratedCircuit, in: MCDataInput) { + override def serverReceiveOperation( + circuit: IntegratedCircuit, + in: MCDataInput + ) { val start = Point(in.readInt(), in.readInt()) val end = Point(in.readInt(), in.readInt()) val corner = start + Point((end - start).vectorize.axialProject) From 41feb7f9be600306a38eb21a88992799483a6336 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Thu, 14 Aug 2025 14:20:59 +0200 Subject: [PATCH 14/21] Localized probably most strings in GUI --- .../assets/projectred/lang/en_US.lang | 30 ++++ .../circuitparts/CircuitPart.scala | 4 +- .../circuitparts/ICGateDefinition.scala | 160 ++++++++++++++---- .../circuitparts/wire/AlloyWire.scala | 2 +- .../circuitparts/wire/BundledCable.scala | 4 +- .../fabrication/gui/GuiICWorkbench.scala | 59 +++++-- .../gui/nodes/ConfigurationNode.scala | 5 + .../fabrication/gui/nodes/ICToolsetNode.scala | 5 +- .../configuration/ConfigurationAnalogIO.scala | 5 +- .../configuration/ConfigurationCounter.scala | 28 ++- .../configuration/ConfigurationRotation.scala | 2 +- .../ConfigurationRotationConfig.scala | 2 +- .../configuration/ConfigurationTimer.scala | 2 +- .../fabrication/operations/CircuitOp.scala | 2 + .../fabrication/operations/OpCopy.scala | 2 +- .../fabrication/operations/OpCut.scala | 2 +- .../fabrication/operations/OpErase.scala | 2 +- .../fabrication/operations/OpGate.scala | 2 +- .../fabrication/operations/OpPaste.scala | 2 +- .../fabrication/operations/OpsICPart.scala | 6 +- .../fabrication/operations/OpsWire.scala | 3 +- 21 files changed, 263 insertions(+), 66 deletions(-) diff --git a/src/main/resources/assets/projectred/lang/en_US.lang b/src/main/resources/assets/projectred/lang/en_US.lang index bc2f75b6c..1dc7a29be 100644 --- a/src/main/resources/assets/projectred/lang/en_US.lang +++ b/src/main/resources/assets/projectred/lang/en_US.lang @@ -602,3 +602,33 @@ item.projectred.fabrication.icblueprint.name=IC Blueprint item.projectred.fabrication.icchip.name=IC Chip item.projectred.fabrication.icchip|0.name=IC Chip item.projectred.fabrication.icchip|1.name=Creative Mode IC Chip +gui.projectred.fabrication.debug=Debug +gui.projectred.fabrication.insulated_wires=Insulated wires +gui.projectred.fabrication.bundled_cables=Bundled cables +gui.projectred.fabrication.ios=IOs +gui.projectred.fabrication.primitives=Primitives +gui.projectred.fabrication.timing_and_clocks=Timing and Clocks +gui.projectred.fabrication.latches=Latches +gui.projectred.fabrication.misc=Misc +gui.projectred.fabrication.reset_view=Reset View +gui.projectred.fabrication.detail=Detail +gui.projectred.fabrication.copy=Copy +gui.projectred.fabrication.cut=Cut +gui.projectred.fabrication.paste=Paste +gui.projectred.fabrication.erase=Erase +gui.projectred.fabrication.io_simple=Simple IO +gui.projectred.fabrication.io_analog=Analog IO +gui.projectred.fabrication.io_bundled=Bundled IO +gui.projectred.fabrication.rotate=Rotate +gui.projectred.fabrication.configure=Configure +gui.projectred.fabrication.frequency=Frequency +gui.projectred.fabrication.state=State +gui.projectred.fabrication.max=Max +gui.projectred.fabrication.inc=Inc +gui.projectred.fabrication.dec=Dec +gui.projectred.fabrication.timer_interval=Interval + + +tile.projectred.integration.icblock.name=IC Workbench/Printer +tile.projectred.integration.icblock|0.name=IC Workbench +tile.projectred.integration.icblock|1.name=IC Printer diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala index d010a6cb9..63767522c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/CircuitPart.scala @@ -11,6 +11,7 @@ import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.operations.CircuitOp import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.StatCollector object CircuitPart { def createPart(id: Int) = CircuitPartDefs(id).createPart @@ -94,7 +95,8 @@ abstract class CircuitPart { @SideOnly(Side.CLIENT) def getRolloverData(detailLevel: Int): Seq[String] = - if (detailLevel > 0) Seq(getPartName) else Seq.empty + if (detailLevel > 0) Seq(StatCollector.translateToLocal(getPartName)) + else Seq.empty @SideOnly(Side.CLIENT) def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) {} diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala index 5bb7d4769..b77e833b0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/ICGateDefinition.scala @@ -13,54 +13,154 @@ object ICGateDefinition extends Enum { import mrtjp.projectred.integration.{GateDefinition => gd} - val IOSimple = ICGateDef("Simple IO", CircuitPartDefs.IOGate.id) - val IOAnalog = ICGateDef("Analog IO", CircuitPartDefs.IOGate.id) - val IOBundled = ICGateDef("Bundled IO", CircuitPartDefs.IOGate.id) + val IOSimple = + ICGateDef("gui.projectred.fabrication.io_simple", CircuitPartDefs.IOGate.id) + val IOAnalog = + ICGateDef("gui.projectred.fabrication.io_analog", CircuitPartDefs.IOGate.id) + val IOBundled = ICGateDef( + "gui.projectred.fabrication.io_bundled", + CircuitPartDefs.IOGate.id + ) - val OR = ICGateDef("OR gate", CircuitPartDefs.SimpleGate.id, gd.OR) - val NOR = ICGateDef("NOR gate", CircuitPartDefs.SimpleGate.id, gd.NOR) - val NOT = ICGateDef("NOT gate", CircuitPartDefs.SimpleGate.id, gd.NOT) - val AND = ICGateDef("AND gate", CircuitPartDefs.SimpleGate.id, gd.AND) - val NAND = ICGateDef("NAND gate", CircuitPartDefs.SimpleGate.id, gd.NAND) - val XOR = ICGateDef("XOR gate", CircuitPartDefs.SimpleGate.id, gd.XOR) - val XNOR = ICGateDef("XNOR gate", CircuitPartDefs.SimpleGate.id, gd.XNOR) + val OR = ICGateDef( + "item.projectred.integration.gate|0.name", + CircuitPartDefs.SimpleGate.id, + gd.OR + ) + val NOR = ICGateDef( + "item.projectred.integration.gate|1.name", + CircuitPartDefs.SimpleGate.id, + gd.NOR + ) + val NOT = ICGateDef( + "item.projectred.integration.gate|2.name", + CircuitPartDefs.SimpleGate.id, + gd.NOT + ) + val AND = ICGateDef( + "item.projectred.integration.gate|3.name", + CircuitPartDefs.SimpleGate.id, + gd.AND + ) + val NAND = ICGateDef( + "item.projectred.integration.gate|4.name", + CircuitPartDefs.SimpleGate.id, + gd.NAND + ) + val XOR = ICGateDef( + "item.projectred.integration.gate|5.name", + CircuitPartDefs.SimpleGate.id, + gd.XOR + ) + val XNOR = ICGateDef( + "item.projectred.integration.gate|6.name", + CircuitPartDefs.SimpleGate.id, + gd.XNOR + ) val Buffer = - ICGateDef("Buffer gate", CircuitPartDefs.SimpleGate.id, gd.Buffer) + ICGateDef( + "item.projectred.integration.gate|7.name", + CircuitPartDefs.SimpleGate.id, + gd.Buffer + ) val Multiplexer = - ICGateDef("Multiplexer", CircuitPartDefs.SimpleGate.id, gd.Multiplexer) - val Pulse = ICGateDef("Pulse Former", CircuitPartDefs.SimpleGate.id, gd.Pulse) + ICGateDef( + "item.projectred.integration.gate|8.name", + CircuitPartDefs.SimpleGate.id, + gd.Multiplexer + ) + val Pulse = ICGateDef( + "item.projectred.integration.gate|9.name", + CircuitPartDefs.SimpleGate.id, + gd.Pulse + ) val Repeater = - ICGateDef("Repeater", CircuitPartDefs.SimpleGate.id, gd.Repeater) + ICGateDef( + "item.projectred.integration.gate|10.name", + CircuitPartDefs.SimpleGate.id, + gd.Repeater + ) val Randomizer = - ICGateDef("Randomizer", CircuitPartDefs.SimpleGate.id, gd.Randomizer) + ICGateDef( + "item.projectred.integration.gate|11.name", + CircuitPartDefs.SimpleGate.id, + gd.Randomizer + ) val SRLatch = - ICGateDef("SR Latch", CircuitPartDefs.ComplexGate.id, gd.SRLatch) + ICGateDef( + "item.projectred.integration.gate|12.name", + CircuitPartDefs.ComplexGate.id, + gd.SRLatch + ) val ToggleLatch = - ICGateDef("Toggle Latch", CircuitPartDefs.ComplexGate.id, gd.ToggleLatch) + ICGateDef( + "item.projectred.integration.gate|13.name", + CircuitPartDefs.ComplexGate.id, + gd.ToggleLatch + ) val TransparentLatch = ICGateDef( - "Transparent Latch", + "item.projectred.integration.gate|14.name", CircuitPartDefs.SimpleGate.id, gd.TransparentLatch ) - val Timer = ICGateDef("Timer", CircuitPartDefs.ComplexGate.id, gd.Timer) + val Timer = ICGateDef( + "item.projectred.integration.gate|17.name", + CircuitPartDefs.ComplexGate.id, + gd.Timer + ) val Sequencer = - ICGateDef("Sequencer", CircuitPartDefs.ComplexGate.id, gd.Sequencer) - val Counter = ICGateDef("Counter", CircuitPartDefs.ComplexGate.id, gd.Counter) + ICGateDef( + "item.projectred.integration.gate|18.name", + CircuitPartDefs.ComplexGate.id, + gd.Sequencer + ) + val Counter = ICGateDef( + "item.projectred.integration.gate|19.name", + CircuitPartDefs.ComplexGate.id, + gd.Counter + ) val StateCell = - ICGateDef("State Cell", CircuitPartDefs.ComplexGate.id, gd.StateCell) + ICGateDef( + "item.projectred.integration.gate|20.name", + CircuitPartDefs.ComplexGate.id, + gd.StateCell + ) val Synchronizer = - ICGateDef("Synchronizer", CircuitPartDefs.ComplexGate.id, gd.Synchronizer) + ICGateDef( + "item.projectred.integration.gate|21.name", + CircuitPartDefs.ComplexGate.id, + gd.Synchronizer + ) val DecRandomizer = - ICGateDef("Dec Randomizer", CircuitPartDefs.SimpleGate.id, gd.DecRandomizer) + ICGateDef( + "item.projectred.integration.gate|33.name", + CircuitPartDefs.SimpleGate.id, + gd.DecRandomizer + ) val NullCell = - ICGateDef("Null Cell", CircuitPartDefs.ArrayGate.id, gd.NullCell) + ICGateDef( + "item.projectred.integration.gate|23.name", + CircuitPartDefs.ArrayGate.id, + gd.NullCell + ) val InvertCell = - ICGateDef("Invert Cell", CircuitPartDefs.ArrayGate.id, gd.InvertCell) + ICGateDef( + "item.projectred.integration.gate|24.name", + CircuitPartDefs.ArrayGate.id, + gd.InvertCell + ) val BufferCell = - ICGateDef("Buffer Cell", CircuitPartDefs.ArrayGate.id, gd.BufferCell) + ICGateDef( + "item.projectred.integration.gate|25.name", + CircuitPartDefs.ArrayGate.id, + gd.BufferCell + ) - case class ICGateDef(unlocal: String, gateType: Int, intDef: GateDef = null) - extends Value { - override def name = unlocal + case class ICGateDef( + unlocalized: String, + gateType: Int, + intDef: GateDef = null + ) extends Value { + override def name = unlocalized } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala index fce7b7181..9b45e886a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/AlloyWire.scala @@ -23,7 +23,7 @@ class AlloyWireICPart extends RedwireICPart { } @SideOnly(Side.CLIENT) - override def getPartName = "Alloy wire" + override def getPartName = "item.projectred.transmission.wire|0.name" @SideOnly(Side.CLIENT) override def getCircuitOperation = CircuitOpDefs.AlloyWire.getOp diff --git a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala index 40f43675d..44ed5be52 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/circuitparts/wire/BundledCable.scala @@ -190,8 +190,8 @@ class BundledCableICPart } @SideOnly(Side.CLIENT) - override def getPartName = (if (colour != -1) Colors(colour & 0xff).name + " " - else "") + "Bundled cable" + override def getPartName = + "item.projectred.transmission.wire|" + colour + ".name" @SideOnly(Side.CLIENT) override def getCircuitOperation = CircuitOpDefs diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 88c8e9f74..67124f26e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -19,6 +19,7 @@ import mrtjp.projectred.fabrication.{FabricationProxy, TileICWorkbench} import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui import net.minecraft.entity.player.EntityPlayer +import net.minecraft.util.StatCollector import org.lwjgl.input.Keyboard import org.lwjgl.opengl.GL11 @@ -29,6 +30,10 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var toolSets = Seq[ICToolsetNode]() var configurationNode: TNode = null + def translate(unlocalizedName: String): String = { + StatCollector.translateToLocal(unlocalizedName) + } + override def onAddedToParent_Impl() { val clip = new ClipNode clip.position = Point(7, 18) @@ -108,13 +113,27 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { addToolset("", Seq(Cut)) addToolset("", Seq(Copy)) addToolset("", Seq(Paste)) - addToolset("Debug", Seq(Torch, Lever, Button)) + addToolset( + translate("gui.projectred.fabrication.debug"), + Seq(Torch, Lever, Button) + ) addToolset("", Seq(AlloyWire)) - addToolsetRange("Insulated wires", WhiteInsulatedWire, BlackInsulatedWire) - addToolsetRange("Bundled cables", NeutralBundledCable, BlackBundledCable) - addToolset("IOs", Seq(SimpleIO, BundledIO, AnalogIO)) + addToolsetRange( + translate("gui.projectred.fabrication.insulated_wires"), + WhiteInsulatedWire, + BlackInsulatedWire + ) + addToolsetRange( + translate("gui.projectred.fabrication.bundled_cables"), + NeutralBundledCable, + BlackBundledCable + ) + addToolset( + translate("gui.projectred.fabrication.ios"), + Seq(SimpleIO, BundledIO, AnalogIO) + ) addToolset( - "Primatives", + translate("gui.projectred.fabrication.primitives"), Seq( ORGate, NORGate, @@ -128,7 +147,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { ) ) addToolset( - "Timing and Clocks", + translate("gui.projectred.fabrication.timing_and_clocks"), Seq( PulseFormerGate, RepeaterGate, @@ -138,12 +157,12 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { ) ) addToolset( - "Latches", + translate("gui.projectred.fabrication.latches"), Seq(SRLatchGate, ToggleLatchGate, TransparentLatchGate) ) addToolset("Cells", Seq(NullCellGate, InvertCellGate, BufferCellGate)) addToolset( - "Misc", + translate("gui.projectred.fabrication.misc"), Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) ) } @@ -192,7 +211,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { val resetView = new MCButtonNode resetView.position = Point(200, 3) resetView.size = Size(60, 12) - resetView.text = "Reset View" + resetView.text = translate("gui.projectred.fabrication.reset_view") resetView.clickDelegate = { () => if (tile.hasBP && tile.circuit.parts.nonEmpty) { pref.scaleGuiToCircuit() @@ -236,11 +255,25 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { PRResources.guiPrototyper.bind() Gui.func_146110_a(0, 0, 0, 0, size.width, size.height, 512, 512) - GuiDraw.drawString("IC Workbench", 8, 6, Colors.GREY.argb, false) + GuiDraw.drawString( + translate("tile.projectred.integration.icblock|0.name"), + 8, + 6, + Colors.GREY.argb, + false + ) - GuiDraw.drawStringC("detail", 273, 190, 42, 14, Colors.GREY.argb, false) GuiDraw.drawStringC( - pref.detailLevel + "", + translate("gui.projectred.fabrication.detail"), + 273, + 190, + 42, + 14, + Colors.GREY.argb, + false + ) + GuiDraw.drawStringC( + pref.detailLevel.toString, 279, 200, 30, @@ -250,7 +283,7 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { ) GuiDraw.drawStringC( - BigDecimal(pref.scale, new MathContext(2)) + "", + BigDecimal(pref.scale, new MathContext(2)).toString(), 278, 4, 30, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala index d17d48aa0..88751d98a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ConfigurationNode.scala @@ -14,6 +14,7 @@ import mrtjp.projectred.fabrication.circuitparts.{ ICGateRenderer, TClientNetCircuitPart } +import net.minecraft.util.StatCollector trait TConfigurable extends TClientNetCircuitPart { def createConfigurationNode: ConfigurationNode @@ -34,4 +35,8 @@ abstract class ConfigurationNode(gate: GateICPart) extends TNode { rframe ) } + + protected def translate(unlocalizedName: String): String = { + StatCollector.translateToLocal(unlocalizedName) + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index 1b786be84..df67db0a4 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -9,6 +9,7 @@ import codechicken.lib.gui.GuiDraw import mrtjp.core.gui.{ButtonNode, IconButtonNode, TNode} import mrtjp.core.vec.{Point, Size} import mrtjp.projectred.fabrication.operations.CircuitOp +import net.minecraft.util.StatCollector import scala.collection.immutable.ListMap import scala.collection.JavaConversions._ @@ -58,7 +59,7 @@ class ICToolsetNode extends TNode { } groupButton.size = buttonSize groupButton.tooltipBuilder = { - _ += buttonOpMap(selectedButton).getOpName + _ += StatCollector.translateToLocal(buttonOpMap(selectedButton).getOpName) } groupButton.clickDelegate = { () => selectedButton.clickDelegate() } addChild(groupButton) @@ -113,7 +114,7 @@ class ICToolsetNode extends TNode { } } b.tooltipBuilder = { - _ += op.getOpName + _ += StatCollector.translateToLocal(op.getOpName) } b.clickDelegate = { () => buttonClicked(op, b) } b diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala index ce37ae63d..89b9bd7aa 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationAnalogIO.scala @@ -13,6 +13,7 @@ import mrtjp.projectred.fabrication.circuitparts.io.{ AnalogIOICGateLogic, IOGateICPart } +import net.minecraft.util.StatCollector import scala.util.Try @@ -37,7 +38,9 @@ class ConfigurationAnalogIO(gate: IOGateICPart) val pos_text = position.add(5, 100) GuiDraw.drawString( - "Frequency:", + StatCollector.translateToLocal( + "gui.projectred.fabrication.frequency" + ) + ":", pos_text.x, pos_text.y, Colors.GREY.argb, diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala index 843dc3e4b..e1a730059 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationCounter.scala @@ -69,7 +69,9 @@ class ConfigurationCounter(gate: SequentialGateICPart) val pos_state = position.add(5, 102) GuiDraw.drawString( - "State: " + counterLogic.getCounterValue.toString, + translate( + "gui.projectred.fabrication.state" + ) + ": " + counterLogic.getCounterValue.toString, pos_state.x, pos_state.y, Colors.GREY.argb, @@ -77,12 +79,30 @@ class ConfigurationCounter(gate: SequentialGateICPart) ) val pos_max = position.add(5, 120) - GuiDraw.drawString("Max", pos_max.x, pos_max.y, Colors.GREY.argb, false) + GuiDraw.drawString( + translate("gui.projectred.fabrication.max"), + pos_max.x, + pos_max.y, + Colors.GREY.argb, + false + ) val pos_inc = position.add(5, 140) - GuiDraw.drawString("Inc", pos_inc.x, pos_inc.y, Colors.GREY.argb, false) + GuiDraw.drawString( + translate("gui.projectred.fabrication.inc"), + pos_inc.x, + pos_inc.y, + Colors.GREY.argb, + false + ) val pos_dec = position.add(5, 160) - GuiDraw.drawString("Dec", pos_dec.x, pos_dec.y, Colors.GREY.argb, false) + GuiDraw.drawString( + translate("gui.projectred.fabrication.dec"), + pos_dec.x, + pos_dec.y, + Colors.GREY.argb, + false + ) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala index 3d5ee33b3..82a3758dd 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotation.scala @@ -14,7 +14,7 @@ class ConfigurationRotation(gate: GateICPart) extends ConfigurationNode(gate) { val rotate = new MCButtonNode rotate.position = Point(8, 60) rotate.size = Size(50, 15) - rotate.text = "rotate" + rotate.text = translate("gui.projectred.fabrication.rotate") rotate.clickDelegate = { () => gate.sendClientPacket(_.writeByte(0)) } addChild(rotate) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala index 845ff85f1..fd136e63b 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationRotationConfig.scala @@ -15,7 +15,7 @@ class ConfigurationRotationConfig(gate: GateICPart) val conf = new MCButtonNode conf.position = Point(8, 80) conf.size = Size(50, 15) - conf.text = "configure" + conf.text = translate("gui.projectred.fabrication.configure") conf.clickDelegate = { () => gate.sendClientPacket(_.writeByte(1)) } addChild(conf) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala index d6c03f51c..26cf351ee 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/configuration/ConfigurationTimer.scala @@ -41,7 +41,7 @@ class ConfigurationTimer(gate: SequentialGateICPart) val pos_state = position.add(13, 82) GuiDraw.drawString( - "Interval:", + translate("gui.projectred.fabrication.timer_interval") + ":", pos_state.x, pos_state.y, Colors.GREY.argb, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala index ccea33f6d..2c92a4748 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/CircuitOp.scala @@ -45,6 +45,8 @@ trait CircuitOp { in: MCDataInput ): Unit + /** Get unlocalized name + */ @SideOnly(Side.CLIENT) def getOpName: String diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala index e48bca159..cc1cc9353 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala @@ -31,7 +31,7 @@ class OpCopy extends OpAreaBase { in: MCDataInput ): Unit = {} - override def getOpName: String = "Copy" + override def getOpName: String = "gui.projectred.fabrication.copy" override def renderHover( position: Vec2, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala index 161bf6537..27ce58010 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala @@ -32,5 +32,5 @@ class OpCut extends OpErase { height: Double ): Unit = {} - override def getOpName: String = "Cut" + override def getOpName: String = "gui.projectred.fabrication.cut" } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala index 11bde7e53..49a732ece 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpErase.scala @@ -87,5 +87,5 @@ class OpErase extends OpAreaBase { } @SideOnly(Side.CLIENT) - override def getOpName = "Erase" + override def getOpName = "gui.projectred.fabrication.erase" } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala index fca79f84f..a57d7ea27 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpGate.scala @@ -118,5 +118,5 @@ class OpGate(meta: Int) extends CircuitOp { } @SideOnly(Side.CLIENT) - override def getOpName = ICGateDefinition(meta).unlocal + override def getOpName = ICGateDefinition(meta).unlocalized } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala index 506652956..31be97790 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala @@ -41,7 +41,7 @@ class OpPaste extends OpAreaBase { } } - override def getOpName: String = "Paste" + override def getOpName: String = "gui.projectred.fabrication.paste" override def renderHover( position: Vec2, diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala index e22ef7fe5..64a6710d2 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsICPart.scala @@ -20,7 +20,7 @@ class OpTorch extends OpSimplePlacement { override def createPart = CircuitPartDefs.Torch.createPart @SideOnly(Side.CLIENT) - override def getOpName = "Torch" + override def getOpName = "tile.notGate.name" } class OpButton extends OpSimplePlacement { @@ -32,7 +32,7 @@ class OpButton extends OpSimplePlacement { override def createPart = CircuitPartDefs.Button.createPart @SideOnly(Side.CLIENT) - override def getOpName = "Button" + override def getOpName = "tile.button.name" } class OpLever extends OpSimplePlacement { @@ -44,5 +44,5 @@ class OpLever extends OpSimplePlacement { override def createPart = CircuitPartDefs.Lever.createPart @SideOnly(Side.CLIENT) - override def getOpName = "Lever" + override def getOpName = "tile.lever.name" } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala index f187a3d82..41b904895 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala @@ -209,7 +209,8 @@ class OpInsulatedWire(colour: Int) extends OpWire { } @SideOnly(Side.CLIENT) - override def getOpName = Colors(colour & 0xff).name + " Insulated wire" + override def getOpName = + "item.projectred.transmission.wire|" + colour + ".name" } class OpBundledCable(colour: Int) extends OpWire { From cb4393f4583bb021ce67aac87e13aee8884600d7 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Thu, 14 Aug 2025 21:04:17 +0200 Subject: [PATCH 15/21] Toolbar fixes --- .../fabrication/gui/GuiICWorkbench.scala | 113 ++---------------- .../fabrication/gui/nodes/ICToolsetNode.scala | 88 +++++++------- .../fabrication/gui/nodes/PrefboardNode.scala | 34 +++--- .../fabrication/gui/nodes/ToolbarNode.scala | 106 ++++++++++++++++ 4 files changed, 176 insertions(+), 165 deletions(-) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 67124f26e..3c4e6c283 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -14,7 +14,6 @@ import mrtjp.core.vec.{Point, Size, Vec2} import mrtjp.core.world.WorldLib import mrtjp.projectred.core.libmc.PRResources import mrtjp.projectred.fabrication.gui.nodes._ -import mrtjp.projectred.fabrication.operations.{CircuitOpDefs, OpGate} import mrtjp.projectred.fabrication.{FabricationProxy, TileICWorkbench} import net.minecraft.client.Minecraft import net.minecraft.client.gui.Gui @@ -27,7 +26,6 @@ import java.math.MathContext class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { var pref: PrefboardNode = null - var toolSets = Seq[ICToolsetNode]() var configurationNode: TNode = null def translate(unlocalizedName: String): String = { @@ -44,10 +42,17 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { opPreview.position = Point(269, 18) addChild(opPreview) + val toolbar = new ToolbarNode( + op => { + opPreview.updatePreview(op) + pref.pickOp(op) + } + ) + toolbar.buildToolbar() + pref = new PrefboardNode( tile.circuit, tile.hasBP, - op => { opPreview.updatePreview(op) }, node => { if (configurationNode != null) { configurationNode.removeFromParent() @@ -58,23 +63,13 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { configurationNode.position = Point(260, 17) addChild(configurationNode) } + }, + op => { + opPreview.updatePreview(op) + toolbar.selectOp(op) } ) pref.zPosition = -0.01 // Must be below clip nodes - pref.opPickDelegate = { op => - if (op == null) { - // Reset rotation and configuration of selected Gate - pref.currentOp match { - case op: OpGate => - op.rotation = 0 - op.configuration = 0 - case _ => - } - pref.currentOp = null - pref.updatePreview() - } - toolSets.foreach(_.pickOp(op)) - } clip.addChild(pref) if (tile.circuit.parts.nonEmpty) { pref.scaleGuiToCircuit() @@ -83,90 +78,6 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { pref.scale = 1.0d } - val toolbar = new TNode {} - - { - import CircuitOpDefs._ - def addToolsetRange(name: String, from: OpDef, to: OpDef) { - addToolset(name, (from.getID to to.getID).map(CircuitOpDefs(_))) - } - - def addToolset(name: String, opset: Seq[OpDef]) { - val toolset = new ICToolsetNode - toolset.position = Point(17, 0) * toolbar.children.size - toolset.title = name - toolset.opSet = opset.map(_.getOp) - toolset.setup() - toolset.opSelectDelegate = { op => - pref.currentOp = op - pref.updatePreview() - if (configurationNode != null) { - configurationNode.removeFromParent() - configurationNode = null - } - } - toolbar.addChild(toolset) - toolSets :+= toolset - } - - addToolset("", Seq(Erase)) - addToolset("", Seq(Cut)) - addToolset("", Seq(Copy)) - addToolset("", Seq(Paste)) - addToolset( - translate("gui.projectred.fabrication.debug"), - Seq(Torch, Lever, Button) - ) - addToolset("", Seq(AlloyWire)) - addToolsetRange( - translate("gui.projectred.fabrication.insulated_wires"), - WhiteInsulatedWire, - BlackInsulatedWire - ) - addToolsetRange( - translate("gui.projectred.fabrication.bundled_cables"), - NeutralBundledCable, - BlackBundledCable - ) - addToolset( - translate("gui.projectred.fabrication.ios"), - Seq(SimpleIO, BundledIO, AnalogIO) - ) - addToolset( - translate("gui.projectred.fabrication.primitives"), - Seq( - ORGate, - NORGate, - NOTGate, - ANDGate, - NANDGate, - XORGate, - XNORGate, - BufferGate, - MultiplexerGate - ) - ) - addToolset( - translate("gui.projectred.fabrication.timing_and_clocks"), - Seq( - PulseFormerGate, - RepeaterGate, - TimerGate, - SequencerGate, - StateCellGate - ) - ) - addToolset( - translate("gui.projectred.fabrication.latches"), - Seq(SRLatchGate, ToggleLatchGate, TransparentLatchGate) - ) - addToolset("Cells", Seq(NullCellGate, InvertCellGate, BufferCellGate)) - addToolset( - translate("gui.projectred.fabrication.misc"), - Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) - ) - } - addChild(toolbar) toolbar.position = Point(size.width / 2 - toolbar.calculateAccumulatedFrame.width / 2, 235) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index df67db0a4..f29109c81 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -14,14 +14,12 @@ import net.minecraft.util.StatCollector import scala.collection.immutable.ListMap import scala.collection.JavaConversions._ -class ICToolsetNode extends TNode { +class ICToolsetNode(onSelect: CircuitOp => Unit) extends TNode { var opSet = Seq.empty[CircuitOp] var title = "" var buttonSize = Size(16, 16) var buttonGap = 1 - var opSelectDelegate = { _: CircuitOp => () } - private var focused = false private var buttonOpMap = ListMap.empty[ButtonNode, CircuitOp] @@ -65,67 +63,67 @@ class ICToolsetNode extends TNode { addChild(groupButton) } + private def createButtonFor(op: CircuitOp) = { + val b = new IconButtonNode { + override def drawButton(mouseover: Boolean) { + op.renderImageStatic( + position.x + 2, + position.y + 2, + size.width - 4, + size.height - 4 + ) + } + } + b.tooltipBuilder = { + _ += StatCollector.translateToLocal(op.getOpName) + } + b.clickDelegate = { () => { + onSelect(op) + buttonClicked(op, b) + } } + b + } + private def buttonClicked(op: CircuitOp, button: ButtonNode) { setFocused() - opSelectDelegate(op) + // Hide all other toolsets parent.children .collect { case t: ICToolsetNode if t != this => t } - .foreach(_.setUnfocused()) + .foreach(toolsetNode => toolsetNode.setUnfocused()) selectedButton.mouseoverLock = false button.mouseoverLock = true selectedButton = button } - def setUnfocused() { - if (focused) hideSubTools() - focused = false - groupButton.mouseoverLock = false + def select(op: CircuitOp): Unit = { + for((button, operation) <- buttonOpMap) { + if(op.id == operation.id) { + buttonClicked(op, button) + return + } + } } def setFocused() { - if (!focused) unhideSubTools() + if (!focused) { + if (buttonOpMap.size > 1) + for (b <- buttonOpMap.keys) + b.hidden = false + } focused = true groupButton.mouseoverLock = true } - private def unhideSubTools() { - if (buttonOpMap.size > 1) - for (b <- buttonOpMap.keys) - b.hidden = false - } - - private def hideSubTools() { - if (buttonOpMap.size > 1) - for (b <- buttonOpMap.keys) - b.hidden = true - } - - private def createButtonFor(op: CircuitOp) = { - val b = new IconButtonNode { - override def drawButton(mouseover: Boolean) { - op.renderImageStatic( - position.x + 2, - position.y + 2, - size.width - 4, - size.height - 4 - ) - } - } - b.tooltipBuilder = { - _ += StatCollector.translateToLocal(op.getOpName) - } - b.clickDelegate = { () => buttonClicked(op, b) } - b - } - - def pickOp(op: CircuitOp) { - setUnfocused() - buttonOpMap.find(_._2 == op) match { - case Some((b, _)) => b.clickDelegate() - case _ => + def setUnfocused() { + if (focused) { + if (buttonOpMap.size > 1) + for (b <- buttonOpMap.keys) + b.hidden = true } + focused = false + groupButton.mouseoverLock = false } override def drawFront_Impl(mouse: Point, rframe: Float) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index afe23a2aa..2ffbb933f 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -36,10 +36,10 @@ import scala.collection.convert.WrapAsJava class PrefboardNode( circuit: IntegratedCircuit, hasBlueprint: Boolean, - previewUpdateDelegate: CircuitOp => Unit, - setConfigNode: TNode => Unit + setConfigNode: TNode => Unit, + onPick: CircuitOp => Unit ) extends TNode { - var currentOp: CircuitOp = null + private var currentOp: CircuitOp = null /** 0 - off 1 - name only 2 - minor details 3 - all details */ @@ -48,17 +48,11 @@ class PrefboardNode( var offset: Vec2 = Vec2(0, 0) - def updatePreview(): Unit = { - previewUpdateDelegate(currentOp) - } - override def frame = Rect( position, parent.frame.size ) - var opPickDelegate = { _: CircuitOp => () } - private var leftMouseDown = false private var rightMouseDown = false private var mouseStart = Point(0, 0) @@ -82,11 +76,6 @@ class PrefboardNode( ) } - private def toCenteredGuiPoint(gridP: Point) = { - val dp = frame.size.vectorize / 16 - Point(gridP.vectorize * dp + dp / 2) - } - override def update_Impl() { if (mcInst.theWorld.getTotalWorldTime % 20 == 0) circuit.refreshErrors() @@ -243,14 +232,14 @@ class PrefboardNode( } override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { - updatePreview() import Keyboard._ if (!consumed) keycode match { case KEY_ESCAPE if leftMouseDown => leftMouseDown = false true case KEY_ESCAPE if currentOp != null => - opPickDelegate(null) + currentOp = null + onPick(null) true case KEY_Q => doPickOp() @@ -328,6 +317,11 @@ class PrefboardNode( } } + def pickOp(op: CircuitOp): Unit = { + setConfigNode(null) + currentOp = op + } + def doPickOp() { val root = getRoot val i = Mouse.getX * root.width / root.mc.displayWidth @@ -337,11 +331,13 @@ class PrefboardNode( val pos = parent.convertPointFromScreen(absPos) if (rayTest(pos)) { val part = circuit.getPart(toGridPoint(pos.vectorize)) - opPickDelegate(if (part != null) { + val op = if (part != null) { setConfigNode(null) part.getCircuitOperation - } else null) - updatePreview() + } else + null + currentOp = op + onPick(op) } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala new file mode 100644 index 000000000..8bc17dd7b --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.projectred.fabrication.gui.nodes + +import mrtjp.core.gui.TNode +import mrtjp.core.vec.Point +import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs.{ANDGate, AlloyWire, AnalogIO, BlackBundledCable, BlackInsulatedWire, BufferCellGate, BufferGate, BundledIO, Button, Copy, CounterGate, Cut, DecRandomizerGate, Erase, InvertCellGate, Lever, MultiplexerGate, NANDGate, NORGate, NOTGate, NeutralBundledCable, NullCellGate, ORGate, OpDef, Paste, PulseFormerGate, RandomizerGate, RepeaterGate, SRLatchGate, SequencerGate, SimpleIO, StateCellGate, SynchronizerGate, TimerGate, ToggleLatchGate, Torch, TransparentLatchGate, WhiteInsulatedWire, XNORGate, XORGate} +import net.minecraft.util.StatCollector + +class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { + + private def translate(str: String): String = { + StatCollector.translateToLocal(str) + } + + private var toolSets: Seq[ICToolsetNode] = Seq() + + def buildToolbar(): Unit = { + addToolset("", Seq(Erase)) + addToolset("", Seq(Cut)) + addToolset("", Seq(Copy)) + addToolset("", Seq(Paste)) + addToolset( + translate("gui.projectred.fabrication.debug"), + Seq(Torch, Lever, Button) + ) + addToolset("", Seq(AlloyWire)) + addToolsetRange( + translate("gui.projectred.fabrication.insulated_wires"), + WhiteInsulatedWire, + BlackInsulatedWire + ) + addToolsetRange( + translate("gui.projectred.fabrication.bundled_cables"), + NeutralBundledCable, + BlackBundledCable + ) + addToolset( + translate("gui.projectred.fabrication.ios"), + Seq(SimpleIO, BundledIO, AnalogIO) + ) + addToolset( + translate("gui.projectred.fabrication.primitives"), + Seq( + ORGate, + NORGate, + NOTGate, + ANDGate, + NANDGate, + XORGate, + XNORGate, + BufferGate, + MultiplexerGate + ) + ) + addToolset( + translate("gui.projectred.fabrication.timing_and_clocks"), + Seq( + PulseFormerGate, + RepeaterGate, + TimerGate, + SequencerGate, + StateCellGate + ) + ) + addToolset( + translate("gui.projectred.fabrication.latches"), + Seq(SRLatchGate, ToggleLatchGate, TransparentLatchGate) + ) + addToolset("Cells", Seq(NullCellGate, InvertCellGate, BufferCellGate)) + addToolset( + translate("gui.projectred.fabrication.misc"), + Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) + ) + } + + def selectOp(op: CircuitOp): Unit = { + if(op == null) { + children.collect { case b: ICToolsetNode => b }.foreach(node => { + node.setUnfocused() + }) + } + else { + children.collect { case b: ICToolsetNode => b }.foreach(node => { + node.select(op) + }) + } + } + + private def addToolsetRange(name: String, from: OpDef, to: OpDef): Unit = { + addToolset(name, (from.getID to to.getID).map(CircuitOpDefs(_))) + } + + private def addToolset(name: String, opset: Seq[OpDef]): Unit = { + val toolset = new ICToolsetNode({ op => onPick(op) }) + toolset.position = Point(17, 0) * children.size + toolset.title = name + toolset.opSet = opset.map(_.getOp) + toolset.setup() + addChild(toolset) + } +} From ac31ce420c05a9e2f3e168cd0d96f2e7c581bcee Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:14:19 +0200 Subject: [PATCH 16/21] Keybindings for copy/paste/cut and immediately start pasting after cut/copy --- .../fabrication/gui/GuiICWorkbench.scala | 10 ++- .../fabrication/gui/nodes/ICToolsetNode.scala | 14 ++-- .../fabrication/gui/nodes/PrefboardNode.scala | 18 ++++++ .../fabrication/gui/nodes/ToolbarNode.scala | 64 ++++++++++++++++--- 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index 3c4e6c283..c5c761da7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -42,12 +42,10 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { opPreview.position = Point(269, 18) addChild(opPreview) - val toolbar = new ToolbarNode( - op => { - opPreview.updatePreview(op) - pref.pickOp(op) - } - ) + val toolbar = new ToolbarNode(op => { + opPreview.updatePreview(op) + pref.pickOp(op) + }) toolbar.buildToolbar() pref = new PrefboardNode( diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index f29109c81..3881fc295 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -77,10 +77,12 @@ class ICToolsetNode(onSelect: CircuitOp => Unit) extends TNode { b.tooltipBuilder = { _ += StatCollector.translateToLocal(op.getOpName) } - b.clickDelegate = { () => { - onSelect(op) - buttonClicked(op, b) - } } + b.clickDelegate = { () => + { + onSelect(op) + buttonClicked(op, b) + } + } b } @@ -98,8 +100,8 @@ class ICToolsetNode(onSelect: CircuitOp => Unit) extends TNode { } def select(op: CircuitOp): Unit = { - for((button, operation) <- buttonOpMap) { - if(op.id == operation.id) { + for ((button, operation) <- buttonOpMap) { + if (op.id == operation.id) { buttonClicked(op, button) return } diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala index 2ffbb933f..854987a50 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/PrefboardNode.scala @@ -207,6 +207,12 @@ class PrefboardNode( mouseStart, mouseEnd ) + if ( + currentOp == CircuitOpDefs.Cut.op || currentOp == CircuitOpDefs.Copy.op + ) { + pickOp(CircuitOpDefs.Paste.op) + onPick(CircuitOpDefs.Paste.op) + } if (!opUsed && mouseStart == mouseEnd) { val part = circuit.getPart(mouseEnd) if (part != null) part.onClicked() @@ -250,6 +256,18 @@ class PrefboardNode( case KEY_C if currentOp != null => doConfigure() true + case KEY_C if Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) => + pickOp(CircuitOpDefs.Copy.op) + onPick(CircuitOpDefs.Copy.op) + true + case KEY_V if Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) => + pickOp(CircuitOpDefs.Paste.op) + onPick(CircuitOpDefs.Paste.op) + true + case KEY_X if Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) => + pickOp(CircuitOpDefs.Cut.op) + onPick(CircuitOpDefs.Cut.op) + true case _ => false } else false diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala index 8bc17dd7b..3d4dd8c9e 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala @@ -8,7 +8,48 @@ package mrtjp.projectred.fabrication.gui.nodes import mrtjp.core.gui.TNode import mrtjp.core.vec.Point import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs} -import mrtjp.projectred.fabrication.operations.CircuitOpDefs.{ANDGate, AlloyWire, AnalogIO, BlackBundledCable, BlackInsulatedWire, BufferCellGate, BufferGate, BundledIO, Button, Copy, CounterGate, Cut, DecRandomizerGate, Erase, InvertCellGate, Lever, MultiplexerGate, NANDGate, NORGate, NOTGate, NeutralBundledCable, NullCellGate, ORGate, OpDef, Paste, PulseFormerGate, RandomizerGate, RepeaterGate, SRLatchGate, SequencerGate, SimpleIO, StateCellGate, SynchronizerGate, TimerGate, ToggleLatchGate, Torch, TransparentLatchGate, WhiteInsulatedWire, XNORGate, XORGate} +import mrtjp.projectred.fabrication.operations.CircuitOpDefs.{ + ANDGate, + AlloyWire, + AnalogIO, + BlackBundledCable, + BlackInsulatedWire, + BufferCellGate, + BufferGate, + BundledIO, + Button, + Copy, + CounterGate, + Cut, + DecRandomizerGate, + Erase, + InvertCellGate, + Lever, + MultiplexerGate, + NANDGate, + NORGate, + NOTGate, + NeutralBundledCable, + NullCellGate, + ORGate, + OpDef, + Paste, + PulseFormerGate, + RandomizerGate, + RepeaterGate, + SRLatchGate, + SequencerGate, + SimpleIO, + StateCellGate, + SynchronizerGate, + TimerGate, + ToggleLatchGate, + Torch, + TransparentLatchGate, + WhiteInsulatedWire, + XNORGate, + XORGate +} import net.minecraft.util.StatCollector class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { @@ -79,15 +120,18 @@ class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { } def selectOp(op: CircuitOp): Unit = { - if(op == null) { - children.collect { case b: ICToolsetNode => b }.foreach(node => { - node.setUnfocused() - }) - } - else { - children.collect { case b: ICToolsetNode => b }.foreach(node => { - node.select(op) - }) + if (op == null) { + children + .collect { case b: ICToolsetNode => b } + .foreach(node => { + node.setUnfocused() + }) + } else { + children + .collect { case b: ICToolsetNode => b } + .foreach(node => { + node.select(op) + }) } } From d98bb70a0e3b8d51f1e5a8a06597d1798dfe7b92 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:27:51 +0200 Subject: [PATCH 17/21] Fix no dragging while pasting --- .../scala/mrtjp/projectred/fabrication/operations/OpPaste.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala index 31be97790..bcdd57695 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala @@ -28,7 +28,7 @@ class OpPaste extends OpAreaBase { super.clientSendOperation(circuit, start, end, out) out.writeInt(OpAreaBase.clipboard.size) OpAreaBase.clipboard.foreach { op => - op._2.clientSendOperation(circuit, start + op._1, end + op._1, out) + op._2.clientSendOperation(circuit, start + op._1, start + op._1, out) } } From 8aa20bb126b3c442e83814ea5485e2d434ff4380 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:36:40 +0200 Subject: [PATCH 18/21] Fix SimplePlacementOp Position Byte -> Int --- .../projectred/fabrication/operations/OpSimplePlacement.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala index 074306186..a0b3c29ef 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpSimplePlacement.scala @@ -29,14 +29,14 @@ abstract class OpSimplePlacement extends CircuitOp { out: MCDataOutput ) { super.clientSendOperation(circuit, start, end, out) - out.writeByte(end.x).writeByte(end.y) + out.writeInt(end.x).writeInt(end.y) } override def serverReceiveOperation( circuit: IntegratedCircuit, in: MCDataInput ) { - val point = Point(in.readUByte(), in.readUByte()) + val point = Point(in.readInt(), in.readInt()) if (circuit.getPart(point.x, point.y) == null) circuit.setPart(point.x, point.y, createPart) } From 770d68148b752a3814243e62563fea1481adcda0 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sun, 17 Aug 2025 12:57:33 +0200 Subject: [PATCH 19/21] Blueprints can be exported and imported. (compressed with deflate, then base64 encoded) --- .../assets/projectred/lang/en_US.lang | 6 + .../fabrication/gui/GuiICWorkbench.scala | 11 +- .../fabrication/gui/nodes/ICToolsetNode.scala | 3 +- .../fabrication/gui/nodes/StringExport.scala | 166 ++++++++++++++++++ .../fabrication/gui/nodes/ToolbarNode.scala | 61 ++++++- .../fabrication/operations/OpAreaBase.scala | 40 ++--- .../fabrication/operations/OpCopy.scala | 2 +- .../fabrication/operations/OpCut.scala | 2 +- .../fabrication/operations/OpsWire.scala | 15 -- 9 files changed, 256 insertions(+), 50 deletions(-) create mode 100644 src/main/scala/mrtjp/projectred/fabrication/gui/nodes/StringExport.scala diff --git a/src/main/resources/assets/projectred/lang/en_US.lang b/src/main/resources/assets/projectred/lang/en_US.lang index 1dc7a29be..c2a502ca5 100644 --- a/src/main/resources/assets/projectred/lang/en_US.lang +++ b/src/main/resources/assets/projectred/lang/en_US.lang @@ -627,6 +627,12 @@ gui.projectred.fabrication.max=Max gui.projectred.fabrication.inc=Inc gui.projectred.fabrication.dec=Dec gui.projectred.fabrication.timer_interval=Interval +gui.projectred.fabrication.import_string=Import string from clipboard +gui.projectred.fabrication.export_string=Export string to clipboard +gui.projectred.fabrication.export_success=Blueprint exported to clipboard! +gui.projectred.fabrication.invalid_string=Not a valid blueprint string +gui.projectred.fabrication.clipboard_unavailable=Can't access system clipboard +gui.projectred.fabrication.im_ex_port=Im-/Export Blueprint Strings tile.projectred.integration.icblock.name=IC Workbench/Printer diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala index c5c761da7..05d0d872c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/GuiICWorkbench.scala @@ -42,10 +42,13 @@ class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { opPreview.position = Point(269, 18) addChild(opPreview) - val toolbar = new ToolbarNode(op => { - opPreview.updatePreview(op) - pref.pickOp(op) - }) + val toolbar = new ToolbarNode( + tile.circuit, + op => { + opPreview.updatePreview(op) + pref.pickOp(op) + } + ) toolbar.buildToolbar() pref = new PrefboardNode( diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala index 3881fc295..d24ba2be7 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ICToolsetNode.scala @@ -14,9 +14,8 @@ import net.minecraft.util.StatCollector import scala.collection.immutable.ListMap import scala.collection.JavaConversions._ -class ICToolsetNode(onSelect: CircuitOp => Unit) extends TNode { +class ICToolsetNode(title: String, onSelect: CircuitOp => Unit) extends TNode { var opSet = Seq.empty[CircuitOp] - var title = "" var buttonSize = Size(16, 16) var buttonGap = 1 diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/StringExport.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/StringExport.scala new file mode 100644 index 000000000..49dbe5645 --- /dev/null +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/StringExport.scala @@ -0,0 +1,166 @@ +package mrtjp.projectred.fabrication.gui.nodes + +import codechicken.lib.gui.GuiDraw +import mrtjp.core.color.Colors +import mrtjp.core.gui.{GuiLib, MCButtonNode, TNode} +import mrtjp.core.vec.{Point, Rect, Size} +import mrtjp.projectred.fabrication.IntegratedCircuit +import mrtjp.projectred.fabrication.circuitparts.CircuitPart +import mrtjp.projectred.fabrication.operations.OpAreaBase +import net.minecraft.client.gui.Gui +import net.minecraft.nbt.{JsonToNBT, NBTTagCompound} +import net.minecraft.util.StatCollector + +import java.awt.Toolkit +import java.awt.datatransfer.{DataFlavor, StringSelection} +import java.io.ByteArrayOutputStream +import java.nio.charset.{Charset, StandardCharsets} +import java.util.Base64 +import java.util.zip.{DataFormatException, Deflater, Inflater} + +/** Export/Import of Circuits: Circuit as nbt -> Deflate -> Base64 + */ +class StringExport(circuit: IntegratedCircuit, onImport: () => Unit) + extends Gui + with TNode { + + position = Point(20, -150) + + override def frame: Rect = Rect(position, Size(180, 80)) + + var statusText = "" + var statusColor = Colors.RED + + { + val close = new MCButtonNode + close.position = Point(4, 4) + close.size = Size(5, 5) + close.clickDelegate = { () => removeFromParent() } + addChild(close) + + val buttonImport = new MCButtonNode + buttonImport.position = Point(10, 10) + buttonImport.size = Size(160, 20) + buttonImport.text = + StatCollector.translateToLocal("gui.projectred.fabrication.import_string") + buttonImport.clickDelegate = { () => + try { + importString() + onImport() + } catch { + case _: IllegalArgumentException | _: DataFormatException => + statusText = "gui.projectred.fabrication.invalid_string" + statusColor = Colors.RED + case _: IllegalStateException => + statusText = "gui.projectred.fabrication.clipboard_unavailable" + statusColor = Colors.RED + } + } + addChild(buttonImport) + + val buttonExport = new MCButtonNode + buttonExport.position = Point(10, 35) + buttonExport.size = Size(160, 20) + buttonExport.text = + StatCollector.translateToLocal("gui.projectred.fabrication.export_string") + buttonExport.clickDelegate = { () => + try { + exportString(circuit) + statusText = "gui.projectred.fabrication.export_success" + statusColor = Colors.GREEN + } catch { + case _: IllegalStateException => + statusText = "gui.projectred.fabrication.clipboard_unavailable" + statusColor = Colors.RED + } + } + addChild(buttonExport) + } + + override def drawBack_Impl(mouse: Point, rframe: Float): Unit = { + GuiLib.drawGuiBox( + position.x, + position.y, + frame.size.width, + frame.size.height, + 0 + ) + GuiDraw.drawString( + StatCollector.translateToLocal(statusText), + position.x + 5, + position.y + 60, + statusColor.argb, + false + ) + } + + private def exportString(circuit: IntegratedCircuit): Unit = { + val nbtTagCompound = new NBTTagCompound + circuit.save(nbtTagCompound) + val data = nbtTagCompound.toString.getBytes(Charset.forName("UTF-8")) + val compressed = compress(data) + val base64EncodedString = new StringSelection( + Base64.getEncoder.encodeToString(compressed) + ) + Toolkit.getDefaultToolkit.getSystemClipboard + .setContents(base64EncodedString, null) + } + + private def compress(input: Array[Byte]): Array[Byte] = { + + val bos = new ByteArrayOutputStream() + + val compressor = new Deflater() + compressor.setInput(input) + compressor.finish() + + val buffer = new Array[Byte](1024) + while (!compressor.finished()) { + val len = compressor.deflate(buffer) + bos.write(buffer, 0, len) + } + compressor.end() + + bos.toByteArray + } + + @throws[Exception] + private def importString(): Unit = { + val clipboard = Toolkit.getDefaultToolkit.getSystemClipboard + val clipboardString = + clipboard.getData(DataFlavor.stringFlavor).asInstanceOf[String] + val decoded = Base64.getDecoder.decode(clipboardString) + val decompressed = decompress(decoded) + + val nbt = + JsonToNBT.func_150315_a(new String(decompressed, StandardCharsets.UTF_8)) + val compound = nbt.asInstanceOf[NBTTagCompound] + val x = compound.getTagList("parts", 10) + val parts = (0 until x.tagCount()) + .map { i => + x.getCompoundTagAt(i) + } + .map { partTag => + val part = CircuitPart.createPart(partTag.getByte("id")) + part.load(partTag) + part.loc = (partTag.getInteger("xpos"), partTag.getInteger("ypos")) + (part.x, part.y) -> part + } + .toMap + OpAreaBase.saveToClipboard(parts) + } + + private def decompress(data: Array[Byte]): Array[Byte] = { + val inflater = new Inflater() + inflater.setInput(data) + + val output = new ByteArrayOutputStream() + val buffer = new Array[Byte](1024) + + while (!inflater.finished()) { + val count = inflater.inflate(buffer) + output.write(buffer, 0, count) + } + output.toByteArray + } +} diff --git a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala index 3d4dd8c9e..27dbef352 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/gui/nodes/ToolbarNode.scala @@ -5,8 +5,10 @@ */ package mrtjp.projectred.fabrication.gui.nodes -import mrtjp.core.gui.TNode -import mrtjp.core.vec.Point +import codechicken.lib.gui.GuiDraw +import mrtjp.core.gui.{IconButtonNode, TNode} +import mrtjp.core.vec.{Point, Size} +import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.operations.{CircuitOp, CircuitOpDefs} import mrtjp.projectred.fabrication.operations.CircuitOpDefs.{ ANDGate, @@ -50,16 +52,18 @@ import mrtjp.projectred.fabrication.operations.CircuitOpDefs.{ XNORGate, XORGate } +import net.minecraft.util.EnumChatFormatting.{AQUA, ITALIC} import net.minecraft.util.StatCollector -class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { +import scala.collection.JavaConversions._ + +class ToolbarNode(circuit: IntegratedCircuit, onPick: CircuitOp => Unit) + extends TNode { private def translate(str: String): String = { StatCollector.translateToLocal(str) } - private var toolSets: Seq[ICToolsetNode] = Seq() - def buildToolbar(): Unit = { addToolset("", Seq(Erase)) addToolset("", Seq(Cut)) @@ -117,6 +121,7 @@ class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { translate("gui.projectred.fabrication.misc"), Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) ) + addImExport() } def selectOp(op: CircuitOp): Unit = { @@ -140,11 +145,53 @@ class ToolbarNode(onPick: CircuitOp => Unit) extends TNode { } private def addToolset(name: String, opset: Seq[OpDef]): Unit = { - val toolset = new ICToolsetNode({ op => onPick(op) }) + val toolset = new ICToolsetNode(name, { op => onPick(op) }) toolset.position = Point(17, 0) * children.size - toolset.title = name toolset.opSet = opset.map(_.getOp) toolset.setup() addChild(toolset) } + + private def addImExport(): Unit = { + var button: IconButtonNode = null + button = new IconButtonNode { + override def drawFront_Impl(mouse: Point, rframe: Float): Unit = { + val p = parent.children + .filter { p => p.isInstanceOf[IconButtonNode] } + .head + .position + if ( + p.x < mouse.x && mouse.x < p.x + 16 && p.y < mouse.y && mouse.y < p.y + 16 + ) { + translateToScreen() + val Point(mx, my) = parent.convertPointToScreen(mouse) + GuiDraw.drawMultilineTip( + mx + 12, + my - 16, + Seq( + ITALIC.toString + StatCollector.translateToLocal( + "gui.projectred.fabrication.im_ex_port" + ) + ) + ) + translateFromScreen() + } + } + } + button.size = Size(16, 16) + button.position = Point(17, 0) * children.size + button.clickDelegate = { () => + var exportGui: StringExport = null + exportGui = new StringExport( + circuit, + () => { + exportGui.removeFromParent() + selectOp(Paste.op) + onPick(Paste.op) + } + ) + addChild(exportGui) + } + addChild(button) + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala index b32671d00..e86226ac3 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala @@ -17,6 +17,26 @@ object OpAreaBase { /** clipboard for copy/past/cut operations */ var clipboard: List = Seq() + + /** Saves parts to [[OpAreaBase.clipboard]] + */ + def saveToClipboard(parts: Map[(Int, Int), CircuitPart]): Unit = { + val (x, y) = if (parts.nonEmpty) { + parts + .reduce((a, b) => + ((math.min(a._1._1, b._1._1), math.min(a._1._2, b._1._2)), null) + ) + ._1 + } else (0, 0) + OpAreaBase.clipboard = parts + .map(element => { + ( + Point(element._1._1 - x, element._1._2 - y), + element._2.getCircuitOperation + ) + }) + .toList + } } abstract class OpAreaBase extends CircuitOp { @@ -55,26 +75,6 @@ abstract class OpAreaBase extends CircuitOp { CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) } - /** Saves parts to [[OpAreaBase.clipboard]] - */ - protected def saveToClipboard(parts: Map[(Int, Int), CircuitPart]): Unit = { - val (x, y) = if (parts.nonEmpty) { - parts - .reduce((a, b) => - ((math.min(a._1._1, b._1._1), math.min(a._1._2, b._1._2)), null) - ) - ._1 - } else (0, 0) - OpAreaBase.clipboard = parts - .map(element => { - ( - Point(element._1._1 - x, element._1._2 - y), - element._2.getCircuitOperation - ) - }) - .toList - } - def rotateClipboard(): Unit = { if (clipboard.size > 1) { val p2 = clipboard diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala index cc1cc9353..edeae92c9 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala @@ -21,7 +21,7 @@ class OpCopy extends OpAreaBase { val topLeft = Point(math.min(start.x, end.x), math.min(start.y, end.y)) val bottomRight = Point(math.max(start.x, end.x), math.max(start.y, end.y)) val parts = circuit.getParts(topLeft, bottomRight + Point(1, 1)) - saveToClipboard(parts) + OpAreaBase.saveToClipboard(parts) super.clientSendOperation(circuit, start, end, out) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala index 27ce58010..e0e15830d 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala @@ -20,7 +20,7 @@ class OpCut extends OpErase { val topLeft = Point(math.min(start.x, end.x), math.min(start.y, end.y)) val bottomRight = Point(math.max(start.x, end.x), math.max(start.y, end.y)) val parts = circuit.getParts(topLeft, bottomRight + Point(1, 1)) - saveToClipboard(parts) + OpAreaBase.saveToClipboard(parts) // Delete parts super.clientSendOperation(circuit, start, end, out) } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala index 41b904895..4bfce8142 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpsWire.scala @@ -130,21 +130,6 @@ abstract class OpWire extends CircuitOp { ) } } - - // TODO Connections -// if (circuit.getPart(px, py) == null) { -// val t = orthoPartT(x, y, xSize, ySize, circuit.size, px, py) -// var m = 0 -// if (px > start.x) { m |= 8; if (px != end2.x) m |= 2 } -// if (px < start.x) { m |= 2; if (px != end2.x) m |= 8 } -// if (py > start.y) { m |= 1; if (py != end2.y) m |= 4 } -// if (py < start.y) { m |= 4; if (py != end2.y) m |= 1 } -// if (px == start.x && end2.x > start.x) m |= 2 -// if (px == start.x && end2.x < start.x) m |= 8 -// if (py == start.y && end2.y > start.y) m |= 4 -// if (py == start.y && end2.y < start.y) m |= 1 -// doRender(t, m) -// } } @SideOnly(Side.CLIENT) From eb9981f8858e8c367e92675775544d65c6326eb8 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sun, 1 Feb 2026 16:50:33 +0100 Subject: [PATCH 20/21] Added some ugly icons --- .../projectred/textures/gui/ic_workbench.png | Bin 22740 -> 5558 bytes .../fabrication/operations/OpAreaBase.scala | 24 ++++++++++++++++++ .../fabrication/operations/OpCopy.scala | 5 +++- .../fabrication/operations/OpCut.scala | 5 +++- .../fabrication/operations/OpPaste.scala | 3 ++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/projectred/textures/gui/ic_workbench.png b/src/main/resources/assets/projectred/textures/gui/ic_workbench.png index 94b63e404d3623df55a1f9460791beb62f33c1ed..6afd14231ab912bd4abd34ee86a226b8f72964f8 100644 GIT binary patch literal 5558 zcmeHLX;f3mwmu9ZihzpPDk!3Xh)gPqBBQN`}0t8vce=c)qfO}K0oi9fBkp4!Zi_YTE~+fOGJ_~;65ZW{=t zKTrJCF@3tiapt8@ZTP^vs{gHiiI%$-y4Gh-eR{;&zU8)wq0@Z~(q^~o%oRa0M z^+38WGr2B!Ve(+IVemw@`*dnZ?gA%gSnncJ8Uqm>tioP7;aPm2uA#o*RhHqM%J;s4 z-%Cl|0uh+s)MKc>MBp;)Dj^pFpmPg`cRReU6)pHBk z7)-DeDM(`_Qvcw6()!4@{F3EP$>v9*&1Yo|3l29o)`rgYqiAa@vni*xKb;)cAyuv{ zJs*&ZSRgx;kPd4b<|L({x#omm?W9!b8c#BALN;*ADus26RY5MhBFpLXn3c=*!2|#-LD4O>8bn(H5iPiKR?)BMo;eTG^aZj$jHTMI<38_%TO& zHk*^_4r9iDUMeOPIL;=CX5YNZ;w9XM#G$y{YPOeBDJdw7#4;hJsg)j1$XO5D0hdRu zP|4cZdK8_1Ss4<69#1AwLQOFl8!uwq;a(f8qgrW!27wy2n!FObW))V0dvEw+C)|{} zWfd)$)Bd*eko}2q+k#Vmxq_aqUZ#>~cLg$W``7`1%d`z>zO|jlk?Q_H z`{m+8iL{Lyn)J|V0WuIKJ*gJC+(7Wfx8Aq~tT6Oiq^0as+gbSj2V&2j5_v}PhMlyo zTx(a(6))DXLYI^E!*b>dgGTD|<_o7QisovO`p?g-+$rf*DCw1R&j^lxY^yEbo`;mev z+w=oGUUJWD&ZeI_94omi%>2Bb^=%L|fs_3DW9rpYB|Z`SdycNrB#SC6v-&d4ysK|L zi?_$zIeaYnBxy^#j_=1Z7%6k9vp-toJv~j9C-cL9OlRSoJ3>PjU?WOpImcZb!d2)m z@}d&2`Fgt!R2>oE?o8OGq(D~n6AyhIBq#3qlACnl${Pc^uTGhHMNi2mD;)$x1!Mz8 z3!6suJr>Xr!{Nq1>t~W=^V08Sh81%9bC66V^U)qOhA9b~WHzXT4kDTIqX ziP`v3w6)AR2$~8(Hwt~quvxk&6YNgs1QPBo-Ja@H$at))&c(qIA%WQTrnXIiXSRPMGPFC9`3N^c2=$Z9C=|f-n zQ@y0uXSd5~q;jUK!YMZ6S4YbjzXNCETl5xt*hRg5hri7ZoKs?at}&X}A}cBicmZt% zUjJ8v>m;Rt9*#dv9}wvJeY$Yt)6+9?Kxc{CMY^#<9^v-A;LbOcQYe(=m6gKx*9+cX z_ZWMf{5{a>W*2|HIoC$g1Wb>guba&Exqki7*|TS-OWB3wq0C#9TU(Z;Jpu!d#K*_e zpL-Lw#tn-?MD_V5_K*)46%!N7(P{iO>VebEi6gp?>zTRd>M{RBC|U5SL0PwT~Z<6a#+ zh<$$DZl|WR$JNIWWI{e6pf1F076CcQFlfR!;=Y@k8-8tVP3O45*O~!YX&KM(z*8;p zExQ#J-;RvDd$R4eo7q#~hLOGfjS;~o3=FbUQ&W?Yk~~J=ywp&{5^2SJ44fOjelOpj zxGDCy*?%lgfM&~6(pt!In9NRF)!8>s|wniuB@RpJw zWW)_Z`&IxNs8nNKjM(m}g+|p(dDF=VV+^*ajFi@^y}A(EkOQvD%Y}y$cbKM{x#cgB zRtoKAEz5sX+G8CU76(Di4TI~GW7K3|BT}i+Ko0F^^f4`GRDA>3)25pADWEZ%u}--a#k4l3h< zw&O|}7FBdBWCy0$_~hE@gr#2{3ms>(o18G|z?5{yhOAJ!Mf%J;RweH>w{zHYvh1my zrJkz~-wYV2sYP99jeY#ZiR@a=kpfgI+ImD+HzR(d?8M0L@${4R##}RYF+=NveR7E_@fSRC8Z>LM*C^V$;o9AiEqAseKDa8K}Qr~=7aOp zRmDsi7#85FI+1$K_kbt1Fylb=4)5AF4eq?sw^d~nTTkVrB-1nW7GS1IW!`*3c&ii^(--v6`C&{N^1t^-4AXJi1?4@$o&^m&`3_sxtwf|FS}|Y^k`=a&jKr~ zom4pasA8qD&~g+$iy21vj4=b|3@xS*)_Z^2AQiOu>N~H|mv=t&|3)GitWD)77w5&U z)uSd+oNE95LZQo0uwtR5c51w7ku}a9Z_7l(uHmD140y{Q0vdkAW^i7gq@k<~PTR(?M5 z3#z511x6J7UntLhEN@fEbU{ih>JI}M{Ll}V_P!0HEaeP_^j&sR(Nm@s!u@aW1KhUF zeR_6KI6YBbJxIV~7dz_L=$BI0$F(Q#yRBcP@a6*CvOTPk28Z;qSD>Q3HubD^pC#fF zO80CXTt}C?Hbt`L>JBFYuZlUBcZ%~Pn~cU{tmq$q*7z@<{@uf%7YF?_L7N~27C~&a-2ej8JjlL^taKT&UHt3DclMe9ikSPKXEk@`=o3&K*MeW`KRlK= z@(?7QW{p~PV35BJ61C72W~Tg@MDqLe^a^Y2;@h{2Om?xzwW1v6ENt`)?5*xp_CsnH zp1-tv*Dm5}7O;3YPxDd@iZ%w%JJ<^YdO@X5i&j53Q0qpC;jU(VcE5yZtM0yN^DWpu zh&obc#Tr!{DC|{Ip(B6Hi3_W%)7!r==A|Nkg5&-PBVZ&H91r?Hn`-`SU@G-%-BYDRXT)o&0)PrgUsb?v9z*F=qecLk1;h@D{C%2q{nAuCMjV`FN=tkF+`1 zB|-*jZqIpyDs>{~(nVf4ws~e=&Ok+ce%9(B2hy_naiqYN+!el&Fi_(hyLIb-!*qa; zf9S|aW|>ACtv1~U#GqZQ+)-UW^fS?quU#Supkff%rdi7bwS*;W zSXEDxW=@FK*J=|&%Q;1b(~GhsL>tiDY&jLF%vJw<<3X}2eaLW$tTf8)g*%;Gh2Ac= zVAaBuH0H1^mU4(@olqY2J;LqIG6_F^QZ?cNR#;rMDlt2BIQX%rW3zaxptosVU8k=RuKKUB)vt~VFbfLo(_?8SR^|&Xa1LoU>Jwjo#n6l{rEstxn ze_?i`q+~Dg2jE<*Nv&J_`AQyKk=4CUU=9}q>xn#2&xD|%tiJB7W%g`>rXUkuz1j5z zed9c9=F04UK03`97wW9zA9Fbgu$BeO1gR=2tG!%8)N}#GCgtMrpA88FmmFqZp-w&? zAI7_O+E&U6i3zAmfg1>l4&TTyTIgND=HzQoLmmzY91*I$e{2?5Ees-2_S-i44?a+r z8O+@v7{QS3K`Y#dxd;I^>`)Uec8Q!X85oCkR!4$G0fL`#h5}Gr~U}KO+ zNc58CMfamYy2cvQ1m03|plN2hCOYk+wF!H$*%Rz=AZ- zF?gT8Uy~FvnCbCsB4rzpR<;W=3(2Vh}f&)qan zL12&*0pTBl%)G@4JKvs12mh~xoBLaK=N{XR`;>=mRfOW)9^|QbhYV96bA%-hZ){o~ z=6emj&>xXS2FuO~UDf((+C`9eo)w5_qd7`2KMGO*P^TGqOg#Ex9Z|Dg1R~b4RXJ{O z#!chAJSG9=9}8$-r5>j3g(V2|WS^|y1lRX ztqd4f;gnLjz97SG1awo)YHaP#2Few;Zf>hdz??Jydl|4}x@@ zigd;V^{6(2pCx#@e;-Y47*c^9QF?~7I(Q$(0<0eDwhEd(diSn?5%YV)Yn8vMgAg54 zcIJ&zxVzK@X=phJ3ZHtC-~hbmSoXsc$#y9%@Js;I6PW)$Z<+^u6uqAew@5(1+@-hu z)xPq#B94k)*kNjC_;nYCm?)#6KkOTS}>(}mF z3jn}+Elo8;09XZnTm>+%0pBJ)U(SMWEH0Ynt^mOHi1LpiN|cQg0M;7dR8m-m&&c`o+S%2ip#c}R928r3Zfy%w56_>Wfj7>cdp7sh=f<&D#nXK? zi+Rn8{TUMpxphqC%hby|F8>^3jvGJ>vULuH|KJQSK6kwk^LqI}| zpb>D55wNMYv+V{BKmZ#d|Gq{bAmMYY4+CI%nP&^bwQzu&19MglaFhcw>JFXT512^+ zn;mo>A%PYMAfaXIpb6v@0OhqCSnmML>i~&^XM=;r(eB)|GaF=+120J${*&WnEvj4(P{ zv0ihVKJRdceP14MZQ!-(gbRhu{_B?tTU&d3dRnv}saT?)nffkbA6S>0E;!Bj$QiJhx*MsMiy2-ohB3Mq_zUd3om@i;mn&)cdeWYbuXeP3``{1VIp=xm# zCSb|DAu18Vj|Cc*?B8{Y&8=4Klm>E+Dl+(lLv9_hTm4B#XoDH4{M|GFj296qUhZXH z9pD)Fw$5W|RB1uung9^spcQc(0Ibyb#f_ikDpfKAfZDZ_B00*OlNH;=%Gd0w_~T6l z>%0x(v*4hW`BH9RNoKo3)rY46=#0L6uAD2}5LB}(ZE^OitOzyEMxUkQn znG-Aa7N2BcRDR0Lf#!LAmcjO%8DA*#w%DN0JQbRZo6hrdSDoE_kXI*MT2s>SoH4hF zCfB$EaTPN7u=@RQxu*c^)cl!Z4av(V?;KQkxh_w&@RrQZ)9Qb+zOW}r#)WOY7XN~H zcc;Py#P$9c>5lBL!xU93CCcA#XM#U+k`RCLQ02C)7)zvG^=;mab?Hxb<{ZjcT@*59 zS9jZkans5Dj~T{Ha_&0E~N_@y?!W|3i8efr=7A>PPaI(G%{Z=89w z-4-SpY^Ev3_i9rZ2XuqaS=C1}{F_2lVM2wMR%zY7Y22`>LA?QQ$TuLC7B8i_lP|LB zwf(U>OvuY(+@eo|dJ=jb_P~2Mdw9kz*CyERJAU)C(Yw8d&yH&E=-tpO)w>2015-A+ z5og$b>$>qq=`ahG%QG%ou+>Hfy{sNMR} zFH9S%2Q=PCzh6D+v2OjDErFG1v3qyKZ)e($-Qlr4J4QEUN8|Y&mBtb>l0z~5vFxz~ z6El%~krP|OpRJA3juMRG6oDG2kyFSWWLA?2lWOCzG%F+DEOisOQFj{4%PZ+7UH^M#N#<_~or8mQhpc33rjAm<6t)^9tm&>qu3&HrzDVaN@Fq5>t1~@y}OD`Yio>Q==#R&UI`a6@Dko znIffID2X|IjC>{fidnj5`oVOKp%O&aaB4zI$^Ihqxsz zr>;%is;7XO$`U6ZOXj>@q~=kEPaTO#EVT+q)Fq^Lc$M_e?(&5$7%w=_rcPX`|d00B0Eey(?kn^A{Q9dWf+ zN0fXYPhJ^-V$JF{)V097^Es-8AK?;=;u|%v+pvYMffHxXhv=ND7LQgGkLP^S{2O&$XoA*sf764_y@zc+OkIwBe;>^H%ZT>l7th@;jS+pK2_~H*jul}niM5*tTV&U zK-J(RHm{!#Y6lHB&1}voNcJF4qer(Xeo`bRbt`tu%XGjx%&nixlovcLs5W>=NVE>> zRQ2auvS0FEss~a71Q@WZLryB6v|Kg!+4}@fS*Q}K4fE+v>#*{LYlX^Nl*3MCp6ad0 z5FvDsgL^JGV1T z0aYRy7!iKyxC)s^FESrHi0yN5ug<^(-C2B$KVJad9mQ02Eca5zALfv?`6?;zjV<;z zi!j~6VoV*%YC@hNucRl6)(k(-eb#nK=IUtD((tASo8Cs`C!f(Vg>aemm1G=6-jP4< z)wZ^K%O9d=4z0CmEh|qKJ&(=?azFle!JSvqwIvy`x{7a8}=`q@0Tl__3$@intsX)nnZ*Xh)|2~&m0MNYgPW8r7vHpuzVSa= z?s09R{*A`;nxMeC#qg;xcGW+^V#BJ>tUoi9D65D>zEdJD49ush*4ftyCT?5&bFn&W z+g7OG=cb|N+WMIK>(S%Uk!8*&k{1TchjwJQJ$dkCcWIR;T+(Xt(A;o^#~Tl>(HouY z20bUZ{r4_8&fK0ddXYL8xg#=iiE(wz#Jn9G(gpzX^EhKOl9`?^%8uYHjJmc;ui&erVK-QxxY*y9aG>{rUc|R(>uVeN+4pm zrNt2tI|)fCZW*Mwq%=YXDI>-W17)a$EEFaIkwBuP;V20h_t!sO#kJrkd7`}o%1}-H zYdBC+;B_RCTu@M`hlhu_2V9&$#6l&JNF-DO28F>O;0%bX7oLRngy3EImYsa_qlR&{ zBjQ|0I0BxV;umd8a3d-3@=^kQ|NFWxXP57R@UCCkffS*hXcwrYxCHcfM)r2!ZCu=l zPG6R0ZwJLVVVp5|k}GH@`CB`eZ#Vzn&3_8{UHzAV!JO#n{oeT7dYzqr8`_n$-yKBo z73oi5zgfB(d%0ksh8S0Z8_^E4-yPfv-|u!$!a4j%&QG2wn!j8-#uN7!W)#h`*_TpS z&X7E~SClFdgC-G(#sq?s;&PS!czyyOpD0zuy;l!yhr?4Is)XgC)J8ut{=*+e4Nbx* zQfwiT5)c^D7zRVZ5GXhtA|Zv6kXYelc_x()J%T;X!Rwn3X^4ajL=tH%DUFhrK*4_U zv0^5*5AX`IN0ZQh%gf5SEBx5op&STAXEaF>=ZwZ;pe}f`DFD*a?js1D_o5BgF2qstD9%qk|bU;eLVRq6Gdn6hTk&<>mKx8FhQVxPx$r@wA1nDlhx67(A_Zwe0H4tiN{R zN^l@~poth|EO-I_ypdm7{GH9?(Akh%8 zX~8L1wv?1T94%#wM1M>4iab(pk+PW;h{1CM?D-D`x$*lb?D1 ztwZhaB;v;^?Hti~EXH0D`fYFD2B_Ece>r!5uL~}N`KP)2?RowGB6rIf{kb!KJ1c(e zr1F&8H5Ax|!H$6b(*3~G{FkvGRkJ+bjM7b=+`i05A|${+s3hh8ucj;2)TZXNO;@U^ zO@COL;Bh2H*w<)O!z-*P_ms=GJ4WE+4@ME(8ubwM>;pJYjFXuf4!lKirJM!Ql3eDm6nc+3J7hHj*B)QDlHus6%g7Y z9T#mrR9ZSNDj>8)IxgCLsI+ukR6uBpbX>IgP-*G7sDRKG>9}a~q0-WEQ30VX(s9w| zL#3tTq5?u&q~oH^he}JwMFoVmNXJE+50#dViwX#Bk&cTtA1W;!7ZniNA{`fPK2%yd zE-E0jMLI6pe5kZ^TvR}4i*#JH`A});xTt{87U{TX^P$qxaZv%GEz)t(=0l~WX)QHnW6#$g+S|gePWe`j z)xlHSclfZ!xSYGL%)=XOr6$5}!oBMBk(@wZll__A$_JNDTkRj*pG~ZfzqZJ6@K4Q> zR>thx3FobBs@92k%(?J(u3}$ZgpO2@na`MS8 zojqE*IF%hH#2{pp>C`3Ky)+Q3p>4E;NM1Klo~olQ?6tJ5sz;63=k!b=x6ome3y!B1 zW8P}R0mLhnbH&8^-o0EOtY!XuA*poy&EiO9Bwl8~Ku}1@#cE5u(<-1muS3qKcW9us zQrjp=7q`_&yFsc(y1=<0vZ|`5Lw~%2V6^)lG-`|eLjwRX>zw@1-OabuM>Kr)8aowz zvuURR!^n~vaqxl`_(MxJjd6wj=aZ$dhH*N=xQ5FSLu`wc}UcK&R-a_48{(19V76QZiuvVSLse8=(0KiEc zbFVnJz)(BFFj-2=tvz?n)ZhBhVm<$jh;`9od|+TBZsuDN?0&IV=j+C*{L|Y` zXq|B*e$pLpxq}Szj0cw7guikjLBQPc{y`d3SuIZm@XTy~@R`_vL`S!|T4fCk1_$4F27m zojI_anqBgq5?bSvjRuw%hCak?x6bm@>EfShe{5t@rexG0c5`iqN%mR&r7B=%4V{q_Xn((VK5sTuZCLkvVRoJ(=2V zrdZ~0J^sxhgBTWMEIcJOJD)OqcQDREiHt1pqKTl%LsZiMYBN zaEV_WDDRBYP@EnRTbL!CNv%yTIEG5V3nk<4kOrOBK+7(11uF0M?5Z%%6tSM25GvuP zQg9CEMwXv#vGaNtA~e1@H`@O$==_%m0)hZs4(8djIR8mQ zNw28ACNy}|z=z1onp$_$zb>nIqE>ET%G>K>1ruCO?pOs_)0WB}%}(k%H{>U`8DQ?- zi>ZHHjZ=4XP+W?Ya!atvj>Z?nTQ3bZ7oM0Qx+@j8{mBCWh$3=(?XAXV1Jn8`O-C`r zW>OsZ(?gMaZXV5RC@sFc*u$OlxyLsxSe5k*$an4Hr=+F&>e&`p@x~1R_-j%ico(D2 zjM6B=q0T!SoKUq4z&+Nb1B-s`O7ZdW)fItEkWFCv+p0#3X6kBc%;mv)uFNEp4NVG` zRs|Fm7B*FnaG^AFlIQ-H~X&-i3Aw%X_wnN<(6J_&*h~si)u^{Ddu>fyoU3dwF}xx`pW$M z{7QGpx?H>8x-dQ3nWP%bHj{)0drrI4>jLkcU59ReOd$AAhb}EPTlqM*+s-Ubmk~Av zumI&68yO15L7j~Mf{edgb&bEk)=#6IWg~ScVvpv)^qf{i3O<5gR7e8RJ~kc9zDFEd z`q|bkR~P_yJRh!#u6)^brpB*#j>{;piDUAMY2TXx67fUJZP@m84WrYIqtkF{g{ZWF zv=4_%GY%_BN`^lSW{=kI@2dsG3%7$}d zGf=)JghEiRV_q&nzpuZ)+D1Y%;;!ZJn1<2BCyq<59o8lP@74dMGA?b8K- z&&+}h9>g9cC8e^ygY#4I{t+hzstvMc;8(Xhf=Je!4QTWJI6@-6e{mg#M8@))Bge9j zxQ#!G^v@qzD4pyTnuzpY(%KrmHM?-}7g8TkS}ORY1V{ z4^PASFt)b592^|6??a*Oc*<*`q6Y#d-~(0y`P7DZsjA9PP-readxI>o=PWZ=zE1oJ z`a&9EyCH!U+>MQmv5ASbwF3#Q$P#!vUIu&#RMq*-=DPVmu_Tlx+>O9z$Ahod*w`_Q zJ0dqX7tDy)!c;S1W|J}_0PG2$(*JB(ZL#s=t9U}^r%tzA4-Pc|__&d4rmn6o8oU}P zFArXhk}*v0eX=%LL|88}<+9YV6MhwrQqLTvwBaIYWDygSPR_&^YD@8)&hdH z+vNND2>z*CwJx%{5yqHeC6D{v!4qVYhNBn5I&_4+hH46o!p`iFcGG?~I92ohS#!64 zn38Z#6E4|&mwySNvy_}QB+FjT2n2-Hm-@~r-nlVW;xmmJmjUy2LwD7uk##j(lct%jygoXpsu%j=|lI-gCsvi(TYpwV)`=z#G$e~bAQ&7@*zHJa)=TFrENwmay7^Um7oop55Nw%<0R2=~ zjnPW$W;ZL(w?Ri`cR7GBknH*M=Ru-jx0S$KiS(k`$oUiGJu;`01%MX$$bg~{AZaid zT;+1prJQ!)6%zoSdtj}DmfSwWl`2nE` z0AAQY%N>q@)FeNY7V+I97Ewl^O#s-sb!*1D9LUt1@A>llF5!P%CtX*-I0F+o3^tr= z%E!7ZGeKv*y`t8)nVnb@!5#g>G~m;6Uqvaha{}P$lOJVj?c2ng0}%vFOiX$&%5;3x zVF%i9s}5+VC3+7Er!%-jjrxxI2qzmKI+c0Lf-PW7#>7O7r97r43Bm=4#w!6izOpPE z{(WNp_0{vw3;k>MxxqU4hsc)8ZXam)uL_7_^{*?J4(PvO_x~4AfZX`fYCxn7{sQ`v S!~<3zptWCLElb7b)PDiWULgno diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala index e86226ac3..ceaa656ee 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpAreaBase.scala @@ -5,8 +5,12 @@ */ package mrtjp.projectred.fabrication.operations +import codechicken.lib.render.uv.{UVScale, UVTranslation} +import codechicken.lib.vec.Translation import cpw.mods.fml.relauncher.{Side, SideOnly} import mrtjp.core.vec.{Point, Vec2} +import mrtjp.projectred.core.libmc.PRResources +import mrtjp.projectred.fabrication.ICComponentStore.{dynamicIdx, faceModels, finishRender, orthoGridT, prepairRender} import mrtjp.projectred.fabrication.IntegratedCircuit import mrtjp.projectred.fabrication.circuitparts.CircuitPart import mrtjp.projectred.fabrication.operations.OpAreaBase.clipboard @@ -75,6 +79,26 @@ abstract class OpAreaBase extends CircuitOp { CircuitOp.renderHolo(topLeft, bottomRight, scale, 0x44ffffff) } + protected def renderImage( + x: Double, + y: Double, + width: Double, + height: Double, + texTranslation: UVTranslation + ): Unit = { + val t = orthoGridT(width, height) `with` new Translation(x, y, 0) + + prepairRender() + PRResources.guiPrototyper.bind() + faceModels(dynamicIdx(0, true)).render( + t, + new UVScale(32) `with` texTranslation `with` new UVScale( + 1 / 512d + ) + ) + finishRender() + } + def rotateClipboard(): Unit = { if (clipboard.size > 1) { val p2 = clipboard diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala index edeae92c9..41223a0a0 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCopy.scala @@ -6,6 +6,7 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.uv.UVTranslation import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.IntegratedCircuit @@ -46,5 +47,7 @@ class OpCopy extends OpAreaBase { y: Double, width: Double, height: Double - ): Unit = {} + ): Unit = { + renderImage(x, y, width, height, new UVTranslation(330, 104)) + } } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala index e0e15830d..83099338c 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpCut.scala @@ -6,6 +6,7 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.MCDataOutput +import codechicken.lib.render.uv.UVTranslation import mrtjp.core.vec.Point import mrtjp.projectred.fabrication.IntegratedCircuit @@ -30,7 +31,9 @@ class OpCut extends OpErase { y: Double, width: Double, height: Double - ): Unit = {} + ): Unit = { + renderImage(x, y, width, height, new UVTranslation(330, 202)) + } override def getOpName: String = "gui.projectred.fabrication.cut" } diff --git a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala index bcdd57695..76769930a 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/operations/OpPaste.scala @@ -6,6 +6,7 @@ package mrtjp.projectred.fabrication.operations import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.render.uv.UVTranslation import mrtjp.core.vec.{Point, Vec2} import mrtjp.projectred.fabrication.IntegratedCircuit @@ -68,6 +69,6 @@ class OpPaste extends OpAreaBase { width: Double, height: Double ): Unit = { - // TODO render paste icon + renderImage(x, y, width, height, new UVTranslation(330, 138)) } } From 427ba49cb8a96f6d2f03d3a4708fb1b905933865 Mon Sep 17 00:00:00 2001 From: CPFe1 <214245144+CPFe1@users.noreply.github.com> Date: Sun, 1 Feb 2026 18:24:32 +0100 Subject: [PATCH 21/21] Fixed rebasing mistakes --- .../fabrication/IntegratedCircuit.scala | 13 +- .../fabrication/guiicworkbench.scala | 841 ------------------ .../mrtjp/projectred/fabrication/ic.scala | 512 ----------- 3 files changed, 7 insertions(+), 1359 deletions(-) delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala delete mode 100644 src/main/scala/mrtjp/projectred/fabrication/ic.scala diff --git a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala index 168fb4f27..604f8f310 100644 --- a/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala +++ b/src/main/scala/mrtjp/projectred/fabrication/IntegratedCircuit.scala @@ -8,12 +8,8 @@ package mrtjp.projectred.fabrication import codechicken.lib.data.{MCDataInput, MCDataOutput} import mrtjp.core.vec.{Point, Rect, Size} import mrtjp.projectred.ProjectRedCore.log -import mrtjp.projectred.fabrication.circuitparts.io.TIOCircuitPart -import mrtjp.projectred.fabrication.circuitparts.{ - CircuitPart, - TClientNetCircuitPart, - TErrorCircuitPart -} +import mrtjp.projectred.fabrication.circuitparts.io.{IOGateICPart, TIOCircuitPart} +import mrtjp.projectred.fabrication.circuitparts.{CircuitPart, TClientNetCircuitPart, TErrorCircuitPart} import mrtjp.projectred.fabrication.operations.CircuitOp import net.minecraft.nbt.{NBTTagCompound, NBTTagList} @@ -44,6 +40,11 @@ class IntegratedCircuit { iostate(r) = iostate(r) & 0xffff | (state & 0xffff) << 16 } + def firstSetup(): Unit = { + val ioparts = parts.values.collect { case io: IOGateICPart => io } + ioparts.foreach(_.onOutputChange(0xf)) + } + def onInputChanged(mask: Int) { val ioparts = parts.values.collect { case io: TIOCircuitPart => io } for (r <- 0 until 4) if ((mask & 1 << r) != 0) { diff --git a/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala b/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala deleted file mode 100644 index 94ed1a33b..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/guiicworkbench.scala +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import java.math.MathContext -import net.minecraft.client.resources.I18n -import codechicken.lib.data.MCDataInput -import codechicken.lib.gui.GuiDraw -import codechicken.lib.render.ColourMultiplier -import codechicken.lib.render.uv.{UVScale, UVTranslation} -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.color.Colors -import mrtjp.core.gui._ -import mrtjp.core.vec.{Point, Rect, Size} -import mrtjp.core.world.WorldLib -import mrtjp.projectred.core.libmc.PRResources -import mrtjp.projectred.fabrication.ICComponentStore._ -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.Gui -import net.minecraft.entity.player.EntityPlayer -import net.minecraft.util.EnumChatFormatting -import org.lwjgl.input.{Keyboard, Mouse} -import org.lwjgl.opengl.GL11 - -import scala.collection.JavaConversions._ -import scala.collection.convert.WrapAsJava -import scala.collection.immutable.ListMap - -class PrefboardNode(circuit: IntegratedCircuit) extends TNode { - var currentOp: CircuitOp = null - var currentOpRotation: Int = 0 - var currentOpConfiguration: Int = 0 - - /** 0 - off 1 - name only 2 - minor details 3 - all details - */ - var detailLevel = 1 - var scale = 1.0 - var sizeMult = 8 - def size = circuit.size * sizeMult - override def frame = Rect( - position, - Size((size.width * scale).toInt, (size.height * scale).toInt) - ) - - var opPickDelegate = { _: CircuitOp => () } - - private var leftMouseDown = false - private var rightMouseDown = false - private var mouseStart = Point(0, 0) - - private def isCircuitValid = circuit.nonEmpty - - private def toGridPoint(p: Point) = { - val f = frame - val rpos = p - position - Point( - (rpos.x * circuit.size.width * 1.0 / f.width).toInt - .min(circuit.size.width - 1) - .max(0), - (rpos.y * circuit.size.height * 1.0 / f.height).toInt - .min(circuit.size.height - 1) - .max(0) - ) - } - - private def toCenteredGuiPoint(gridP: Point) = { - val dp = frame.size.vectorize / circuit.size.vectorize - Point(gridP.vectorize * dp + dp / 2) - } - - override def update_Impl() { - if (mcInst.theWorld.getTotalWorldTime % 20 == 0) - circuit.refreshErrors() - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - if (isCircuitValid) { - val f = frame - RenderCircuit.renderOrtho( - circuit, - f.x, - f.y, - size.width * scale, - size.height * scale, - rframe - ) - - if (currentOp != null) { - if (frame.contains(mouse) && rayTest(mouse) && !leftMouseDown) { - currentOp.renderHover( - circuit, - toGridPoint(mouse), - currentOpRotation, - currentOpConfiguration, - f.x, - f.y, - size.width * scale, - size.height * scale - ) - } else if (leftMouseDown) - currentOp.renderDrag( - circuit, - mouseStart, - toGridPoint(mouse), - f.x, - f.y, - size.width * scale, - size.height * scale - ) - } - - if ( - mcInst.theWorld.getTotalWorldTime % 100 > 5 && circuit.errors.nonEmpty - ) { - prepairRender() - PRResources.guiPrototyper.bind() - for ((Point(x, y), (_, c)) <- circuit.errors) { - val t = orthoPartT( - f.x, - f.y, - size.width * scale, - size.height * scale, - circuit.size, - x, - y - ) - faceModels(dynamicIdx(0, true)).render( - t, - new UVScale(64) `with` new UVTranslation( - 330, - 37 - ) `with` new UVScale(1 / 512d), - ColourMultiplier.instance(Colors(c).rgba) - ) - } - finishRender() - } - } - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - if ( - isCircuitValid && !leftMouseDown && frame.contains(mouse) && rayTest( - mouse - ) - ) { - val point = toGridPoint(mouse) - val part = circuit.getPart(point) - if (part != null) { - val data = part.getRolloverData(detailLevel) - if (data.nonEmpty) { - ClipNode.tempDisableScissoring() - translateToScreen() - val Point(mx, my) = parent.convertPointToScreen(mouse) - GuiDraw.drawMultilineTip( - mx + 12, - my - 12, - WrapAsJava.seqAsJavaList(data) - ) - if (circuit.errors.contains(point)) - GuiDraw.drawMultilineTip( - mx + 12, - my - 32, - Seq(EnumChatFormatting.RED.toString + circuit.errors(point)._1) - ) - translateFromScreen() - ClipNode.tempEnableScissoring() - } - } - } - } - - override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { - if (isCircuitValid && !consumed && rayTest(p)) button match { - case 0 => - leftMouseDown = true - mouseStart = toGridPoint(p) - return true - case 1 => - rightMouseDown = true - val gridP = toGridPoint(p) - circuit.getPart(gridP) match { - case gp: IGuiCircuitPart => - val currentlyOpen = children.collect { case cg: CircuitGui => cg } - if (!currentlyOpen.exists(_.part == gp)) { - val gui = gp.createGui - gui.position = - convertPointFrom(Point(4, 4) * (currentlyOpen.size + 1), parent) - gui.linePointerCalc = () => toCenteredGuiPoint(gridP) - addChild(gui) - gui.pushZTo(currentlyOpen.size * 0.1) - } - case _ => - } - return true - case _ if button == mcInst.gameSettings.keyBindPickBlock.getKeyCode => - doPickOp() - return true - case _ => - } - false - } - - override def mouseReleased_Impl(p: Point, button: Int, consumed: Boolean) = { - if (leftMouseDown) { - leftMouseDown = false - val mouseEnd = toGridPoint(p) - val opUsed = - currentOp != null && circuit.sendOpUse(currentOp, currentOpRotation, currentOpConfiguration, mouseStart, mouseEnd) - if (!opUsed && mouseEnd == mouseStart) { - val part = circuit.getPart(mouseEnd) - if (part != null) part.onClicked() - } - } - if (rightMouseDown) { - rightMouseDown = false - val mouseEnd = toGridPoint(p) - if (mouseEnd == mouseStart) { - val part = circuit.getPart(mouseEnd) - if (part != null) part.onActivated() - } - } - false - } - - override def mouseScrolled_Impl(p: Point, dir: Int, consumed: Boolean) = { - if (!consumed && rayTest(p)) { - if (dir > 0) rescaleAt(p, math.min(scale + 0.1, 3.0)) - else if (dir < 0) rescaleAt(p, math.max(scale - 0.1, 0.5)) - true - } else false - } - - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { - import Keyboard._ - if (!consumed) keycode match { - case KEY_ESCAPE if leftMouseDown => - leftMouseDown = false - true - case KEY_ESCAPE if currentOp != null => - opPickDelegate(null) - true - case KEY_Q => - doPickOp() - true - case KEY_R if currentOp != null => - currentOpRotation += 1 - if (currentOpRotation == 4) currentOpRotation = 0 - true - case KEY_C if currentOp != null => - currentOpConfiguration += 1 - true - case _ if keycode == mcInst.gameSettings.keyBindInventory.getKeyCode => - opPickDelegate(CircuitOpDefs.Erase.getOp) - true - case _ => false - } - else false - } - - def doPickOp() { - val root = getRoot - val i = Mouse.getX * root.width / root.mc.displayWidth - val j = root.height - Mouse.getY * root.height / root.mc.displayHeight - 1 - val absPos = Point(i, j) - - val pos = parent.convertPointFromScreen(absPos) - if (rayTest(pos)) { - val part = circuit.getPart(toGridPoint(pos)) - opPickDelegate(if (part != null) part.getPickOp else null) - } - } - - def incDetail() { detailLevel = math.min(detailLevel + 1, 3) } - def decDetail() { detailLevel = math.max(detailLevel - 1, 0) } - - def incScale() { rescaleAt(frame.midPoint, math.min(scale + 0.2, 3.0)) } - def decScale() { rescaleAt(frame.midPoint, math.max(scale - 0.2, 0.5)) } - - def rescaleAt(point: Point, newScale: Double) { - val p = parent.convertPointTo(point, this).vectorize - val newP = (p / scale) * newScale - val dp = newP - p - scale = newScale - position -= Point(dp) - } -} - -class ICToolsetNode extends TNode { - var opSet = Seq.empty[CircuitOp] - var title = "" - var buttonSize = Size(16, 16) - var buttonGap = 1 - - var opSelectDelegate = { _: CircuitOp => () } - - private var focused = false - private var buttonOpMap = ListMap.empty[ButtonNode, CircuitOp] - - private var leadingButton: ButtonNode = null - private var groupButton: ButtonNode = null - - def setup() { - for (op <- opSet) { - val b = createButtonFor(op) - b.size = buttonSize - b.hidden = true - addChild(b) - buttonOpMap += b -> op - } - - val delta = opSet.size * (buttonSize.width + buttonGap) - val firstPoint = - Point(-delta / 2 + buttonSize.width / 2, -buttonSize.height - buttonGap) - for ((b, i) <- buttonOpMap.keys.zipWithIndex) - b.position = firstPoint.add(i * (buttonSize.width + buttonGap), 0) - - leadingButton = buttonOpMap.head._1 - - groupButton = new IconButtonNode { - override def drawButton(mouseover: Boolean) = { - val op = buttonOpMap(leadingButton) - op.renderImage( - position.x + 2, - position.y + 2, - size.width - 4, - size.height - 4 - ) - } - } - groupButton.size = buttonSize - groupButton.tooltipBuilder = { _ += buttonOpMap(leadingButton).getOpName } - groupButton.clickDelegate = { () => leadingButton.clickDelegate() } - addChild(groupButton) - } - - private def buttonClicked(op: CircuitOp, button: ButtonNode) { - setFocused() - opSelectDelegate(op) - parent.children - .collect { - case t: ICToolsetNode if t != this => t - } - .foreach(_.setUnfocused()) - leadingButton.mouseoverLock = false - leadingButton = button - leadingButton.mouseoverLock = true - } - - def setUnfocused() { - if (focused) hideSubTools() - focused = false - groupButton.mouseoverLock = false - } - - def setFocused() { - if (!focused) unhideSubTools() - focused = true - groupButton.mouseoverLock = true - } - - private def unhideSubTools() { - if (buttonOpMap.size > 1) - for (b <- buttonOpMap.keys) - b.hidden = false - } - - private def hideSubTools() { - if (buttonOpMap.size > 1) - for (b <- buttonOpMap.keys) - b.hidden = true - } - - private def createButtonFor(op: CircuitOp) = { - val b = new IconButtonNode { - override def drawButton(mouseover: Boolean) { - op.renderImage( - position.x + 2, - position.y + 2, - size.width - 4, - size.height - 4 - ) - } - } - b.tooltipBuilder = { _ += op.getOpName } - b.clickDelegate = { () => buttonClicked(op, b) } - b - } - - def pickOp(op: CircuitOp) { - setUnfocused() - buttonOpMap.find(_._2 == op) match { - case Some((b, _)) => b.clickDelegate() - case _ => - } - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - if ( - title.nonEmpty && groupButton.rayTest(parent.convertPointTo(mouse, this)) - ) { - import net.minecraft.util.EnumChatFormatting._ - translateToScreen() - val Point(mx, my) = parent.convertPointToScreen(mouse) - GuiDraw.drawMultilineTip( - mx + 12, - my - 32, - Seq(AQUA.toString + ITALIC.toString + title) - ) - translateFromScreen() - } - } -} - -class NewICNode extends TNode { - val size = Size(100, 120) - override def frame = Rect(position, size) - - var sizerRenderSize = Size(50, 50) - var sizerRenderOffset = Point(0, -16) - var sizerRenderGap = 2 - - var maxBoardSize = Size(4, 4) - var selectedBoardSize = Size(1, 1) - - var completionDelegate = { () => () } - - var outsideColour = Colors.LIGHT_GREY.argb - var insideColour = Colors.CYAN.rgb | 0x88000000 - var hoverColour = Colors.BLUE.argb - - def getName = { - val t = textbox.text - if (t.isEmpty) "untitled" else t - } - - private var textbox: SimpleTextboxNode = null - private var sizerMap: Map[(Int, Int), Rect] = null - - private def sizerPos = - position + Point(size / 2 - sizerRenderSize / 2) + sizerRenderOffset - - private def calcSizerRects = { - val p = sizerPos - val d = sizerRenderSize / maxBoardSize - - val rcol = GuiLib.createGrid( - p.x, - p.y, - maxBoardSize.width, - maxBoardSize.height, - d.width, - d.height - ) - val icol = - GuiLib.createGrid(0, 0, maxBoardSize.width, maxBoardSize.height, 1, 1) - val zcol = rcol.zip(icol) - - var rects = Map[(Int, Int), Rect]() - for (((px, py), (x, y)) <- zcol) { - val rect = - Rect(Point(px, py) + sizerRenderGap / 2, d - sizerRenderGap / 2) - rects += (x, y) -> rect - } - rects - } - - private def getMouseoverPos(mouse: Point) = - sizerMap.find(_._2 contains mouse) match { - case Some(((x, y), r)) => Point(x, y) - case None => null - } - - override def traceHit(absPoint: Point) = true - - override def onAddedToParent_Impl() { - sizerMap = calcSizerRects - - val close = new MCButtonNode - close.size = Size(8, 8) - close.position = Point(4, 4) - close.clickDelegate = { () => removeFromParent() } - addChild(close) - - val fin = new MCButtonNode - fin.size = Size(40, 15) - fin.position = Point( - size.width / 2 - fin.size.width / 2, - size.height - fin.size.height - 4 - ) - fin.clickDelegate = { () => - removeFromParent() - completionDelegate() - } - fin.text = "start" - addChild(fin) - - textbox = new SimpleTextboxNode - textbox.size = Size(80, 14) - textbox.position = Point(size / 2 - textbox.size / 2) + Point(0, 24) - textbox.phantom = "untitled" - addChild(textbox) - } - - override def frameUpdate_Impl(mouse: Point, rframe: Float) { - if (!parent.asInstanceOf[GuiICWorkbench].tile.hasBP) - removeFromParent() - } - - override def drawBack_Impl(mouse: Point, rframe: Float) { - GuiDraw.drawGradientRect( - 0, - 0, - parent.frame.width, - parent.frame.height, - -1072689136, - -804253680 - ) - GuiLib.drawGuiBox(position.x, position.y, size.width, size.height, 0) - - val mousePos = getMouseoverPos(mouse) - for (((x, y), rect) <- sizerMap) { - GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, outsideColour) - - if (x <= selectedBoardSize.width - 1 && y <= selectedBoardSize.height - 1) - GuiDraw.drawRect(rect.x, rect.y, rect.width, rect.height, insideColour) - - if (mousePos != null && x == mousePos.x && y == mousePos.y) - GuiDraw.drawRect(rect.midX - 2, rect.midY - 2, 4, 4, hoverColour) - } - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - if (rayTest(mouse)) { - val mousePos = getMouseoverPos(mouse) - if (mousePos != null) { - translateToScreen() - val Point(mx, my) = parent.convertPointToScreen(mouse) - import scala.collection.JavaConversions._ - GuiDraw.drawMultilineTip( - mx + 12, - my - 12, - Seq((mousePos.x + 1) * 16 + " x " + (mousePos.y + 1) * 16) - ) - translateFromScreen() - } - } - } - - override def mouseClicked_Impl( - p: Point, - button: Int, - consumed: Boolean - ): Boolean = { - if (!consumed) { - val mousePos = getMouseoverPos(p) - if (mousePos != null) { - selectedBoardSize = Size(mousePos + 1) - return true - } - } - false - } - - override def keyPressed_Impl(c: Char, keycode: Int, consumed: Boolean) = { - if (!consumed) keycode match { - case Keyboard.KEY_ESCAPE => - removeFromParent() - true - case Keyboard.KEY_RETURN => - removeFromParent() - completionDelegate() - true - case _ => false - } - else false - } -} - -class InfoNode extends TNode { - val size = Size(18, 18) - override def frame = Rect(position, size) - - private def getTile = parent.asInstanceOf[GuiICWorkbench].tile - - override def drawBack_Impl(mouse: Point, rframe: Float) { - PRResources.guiPrototyper.bind() - if (!getTile.hasBP || getTile.getIC.isEmpty) - Gui.func_146110_a( - position.x, - position.y, - 330, - 0, - size.width, - size.height, - 512, - 512 - ) - } - - override def drawFront_Impl(mouse: Point, rframe: Float) { - val text = - if (!getTile.hasBP) - "Lay down a blueprint on the workbench." - else if (getTile.getIC.isEmpty) - "Blueprint is empty. Redraw it." - else "" - if (text.nonEmpty && rayTest(mouse)) { - translateToScreen() - val Point(mx, my) = parent.convertPointToScreen(mouse) - import scala.collection.JavaConversions._ - GuiDraw.drawMultilineTip(mx + 12, my - 12, Seq(text)) - translateFromScreen() - } - } -} - -class GuiICWorkbench(val tile: TileICWorkbench) extends NodeGui(330, 256) { - var pref: PrefboardNode = null - var toolSets = Seq[ICToolsetNode]() - - override def onAddedToParent_Impl() { - val clip = new ClipNode - clip.position = Point(7, 18) - clip.size = Size(252, 197) - addChild(clip) - - val pan = new PanNode - pan.size = Size(252, 197) - pan.clampSlack = 35 - pan.dragTestFunction = { () => Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) } - clip.addChild(pan) - - pref = new PrefboardNode(tile.circuit) - pref.position = Point(pan.size / 2 - pref.size / 2) - pref.zPosition = -0.01 // Must be below pan/clip nodes - pref.opPickDelegate = { op => - if (op == null) pref.currentOp = null - toolSets.foreach(_.pickOp(op)) - } - pan.addChild(pref) - - val toolbar = new TNode {} - - { - import CircuitOpDefs._ - def addToolsetRange(name: String, from: OpDef, to: OpDef) { - addToolset(name, (from.getID to to.getID).map(CircuitOpDefs(_))) - } - def addToolset(name: String, opset: Seq[OpDef]) { - val toolset = new ICToolsetNode - toolset.position = Point(17, 0) * toolbar.children.size - toolset.title = name - toolset.opSet = opset.map(_.getOp) - toolset.setup() - toolset.opSelectDelegate = { op => - pref.currentOp = op - pref.currentOpConfiguration = 0 - } - toolbar.addChild(toolset) - toolSets :+= toolset - } - - addToolset("", Seq(Erase)) - addToolset("Debug", Seq(Torch, Lever, Button)) - addToolset("", Seq(AlloyWire)) - addToolsetRange("Insulated wires", WhiteInsulatedWire, BlackInsulatedWire) - addToolsetRange("Bundled cables", NeutralBundledCable, BlackBundledCable) - addToolset("IOs", Seq(SimpleIO, BundledIO, AnalogIO)) - addToolset( - "Primatives", - Seq( - ORGate, - NORGate, - NOTGate, - ANDGate, - NANDGate, - XORGate, - XNORGate, - BufferGate, - MultiplexerGate - ) - ) - addToolset( - "Timing and Clocks", - Seq( - PulseFormerGate, - RepeaterGate, - TimerGate, - SequencerGate, - StateCellGate - ) - ) - addToolset( - "Latches", - Seq(SRLatchGate, ToggleLatchGate, TransparentLatchGate) - ) - addToolset("Cells", Seq(NullCellGate, InvertCellGate, BufferCellGate)) - addToolset( - "Misc", - Seq(RandomizerGate, CounterGate, SynchronizerGate, DecRandomizerGate) - ) - } - - addChild(toolbar) - toolbar.position = - Point(size.width / 2 - toolbar.calculateAccumulatedFrame.width / 2, 235) - - val dminus = new MCButtonNode - dminus.position = Point(269, 175) - dminus.size = Size(10, 10) - dminus.text = "-" - dminus.clickDelegate = { () => pref.decDetail() } - addChild(dminus) - - val dplus = new MCButtonNode - dplus.position = Point(309, 175) - dplus.size = Size(10, 10) - dplus.text = "+" - dplus.clickDelegate = { () => pref.incDetail() } - addChild(dplus) - - val sminus = new MCButtonNode - sminus.position = Point(269, 207) - sminus.size = Size(10, 10) - sminus.text = "-" - sminus.clickDelegate = { () => pref.decScale() } - addChild(sminus) - - val splus = new MCButtonNode - splus.position = Point(309, 207) - splus.size = Size(10, 10) - splus.text = "+" - splus.clickDelegate = { () => pref.incScale() } - addChild(splus) - - val reqNew = new MCButtonNode - reqNew.position = Point(272, 133) - reqNew.size = Size(44, 12) - reqNew.text = I18n.format("gui.projectred.integration.icblock|0.redraw") - reqNew.clickDelegate = { () => - if (tile.hasBP) { - val nic = new NewICNode - nic.position = Point(size / 2) - Point(nic.size / 2) - nic.completionDelegate = { () => - val ic = new IntegratedCircuit - ic.name = nic.getName - ic.size = nic.selectedBoardSize * 16 - tile.sendNewICToServer(ic) - } - addChild(nic) - nic.pushZTo(5) - } - } - addChild(reqNew) - - val info = new InfoNode - info.position = Point(241, 18) - info.zPosition = 1 - addChild(info) - } - - override def drawBack_Impl(mouse: Point, frame: Float) { - GL11.glColor4f(1, 1, 1, 1) - PRResources.guiPrototyper.bind() - Gui.func_146110_a(0, 0, 0, 0, size.width, size.height, 512, 512) - - GuiDraw.drawString( - I18n.format("gui.projectred.integration.icblock|0.title"), - 8, - 6, - Colors.GREY.argb, - false - ) - - GuiDraw.drawStringC( - I18n.format("gui.projectred.integration.icblock|0.detail"), - 273, - 162, - 42, - 14, - Colors.GREY.argb, - false - ) - GuiDraw.drawStringC( - pref.detailLevel + "", // TODO: GuiText Integration - 279, - 175, - 30, - 10, - Colors.GREY.argb, - false - ) - - GuiDraw.drawStringC( - I18n.format("gui.projectred.integration.icblock|0.scale"), - 273, - 193, - 42, - 14, - Colors.GREY.argb, - false - ) - GuiDraw.drawStringC( - BigDecimal( - pref.scale, - new MathContext(2) - ) + "", // TODO: GuiText Integration - 279, - 207, - 30, - 10, - Colors.GREY.argb, - false - ) - } -} - -object GuiICWorkbench extends TGuiBuilder { - override def getID = FabricationProxy.icWorkbenchGui - - @SideOnly(Side.CLIENT) - override def buildGui(player: EntityPlayer, data: MCDataInput) = { - WorldLib.getTileEntity( - Minecraft.getMinecraft.theWorld, - data.readCoord() - ) match { - case t: TileICWorkbench => - t.circuit.readDesc(data) - new GuiICWorkbench(t) - case _ => null - } - } -} diff --git a/src/main/scala/mrtjp/projectred/fabrication/ic.scala b/src/main/scala/mrtjp/projectred/fabrication/ic.scala deleted file mode 100644 index 8cc011101..000000000 --- a/src/main/scala/mrtjp/projectred/fabrication/ic.scala +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. - */ -package mrtjp.projectred.fabrication - -import codechicken.lib.data.{MCDataInput, MCDataOutput} -import codechicken.lib.packet.PacketCustom -import codechicken.lib.vec.{BlockCoord, Transformation} -import cpw.mods.fml.relauncher.{Side, SideOnly} -import mrtjp.core.util.Enum -import mrtjp.core.vec.{Point, Size} -import mrtjp.projectred.ProjectRedCore.log -import net.minecraft.item.ItemStack -import net.minecraft.nbt.{NBTTagCompound, NBTTagList} -import net.minecraft.world.World -import net.minecraftforge.fluids.FluidStack - -import scala.collection.mutable.{Map => MMap, Seq => MSeq} - -trait WorldCircuit { - def getIC: IntegratedCircuit - def getWorld: World - - def getICStreamOf(key: Int): MCDataOutput - def getPartStream(x: Int, y: Int): MCDataOutput - - def isRemote: Boolean - def markSave() -} - -object DummyMCIO extends MCDataOutput { - override def writeVarInt(i: Int) = this - override def writeCoord(x: Int, y: Int, z: Int) = this - override def writeCoord(coord: BlockCoord) = this - override def writeString(s: String) = this - override def writeFloat(f: Float) = this - override def writeDouble(d: Double) = this - override def writeShort(s: Int) = this - override def writeVarShort(s: Int) = this - override def writeInt(i: Int) = this - override def writeFluidStack(liquid: FluidStack) = this - override def writeByteArray(array: Array[Byte]) = this - override def writeBoolean(b: Boolean) = this - override def writeItemStack(stack: ItemStack) = this - override def writeNBTTagCompound(tag: NBTTagCompound) = this - override def writeChar(c: Char) = this - override def writeLong(l: Long) = this - override def writeByte(b: Int) = this -} - -trait SimulatedWorldCircuit extends WorldCircuit { - override def getICStreamOf(key: Int) = DummyMCIO - override def getPartStream(x: Int, y: Int) = DummyMCIO - override def isRemote = false -} - -trait NetWorldCircuit extends WorldCircuit { - private var icStream: PacketCustom = null - private var partStream: PacketCustom = null - - def createPartStream(): PacketCustom - def sendPartStream(out: PacketCustom) - override def getPartStream(x: Int, y: Int): MCDataOutput = { - if (partStream == null) partStream = createPartStream() - - val part = getIC.getPart(x, y) - partStream.writeByte(part.id) - partStream.writeByte(x).writeByte(y) - - partStream - } - def flushPartStream() { - if (partStream != null) { - partStream.writeByte(255) // terminator - sendPartStream(partStream.compress()) - partStream = null - } - } - def readPartStream(in: MCDataInput) { - try { - var id = in.readUByte() - while (id != 255) { - val (x, y) = (in.readUByte(), in.readUByte()) - var part = getIC.getPart(x, y) - if (part == null || part.id != id) { - log.error("client part stream couldnt find part " + Point(x, y)) - part = CircuitPart.createPart(id) - } - part.read(in) - id = in.readUByte() - } - } catch { - case ex: IndexOutOfBoundsException => - log.error("Circuit part stream failed to be read.") - ex.printStackTrace() - } - } - - def createICStream(): PacketCustom - def sendICStream(out: PacketCustom) - override def getICStreamOf(key: Int): MCDataOutput = { - if (icStream == null) icStream = createICStream() - icStream.writeByte(key) - icStream - } - def flushICStream() { - if (icStream != null) { - icStream.writeByte(255) // terminator - sendICStream(icStream.compress()) - icStream = null - } - } - def readICStream(in: MCDataInput) { - try { - var id = in.readUByte() - while (id != 255) { - getIC.read(in, id) - id = in.readUByte() - } - } catch { - case ex: IndexOutOfBoundsException => - log.error("Circuit IC stream failed to be read") - } - } -} - -class IntegratedCircuit { - var network: WorldCircuit = null - - var name = "untitled" - var size = Size.zeroSize - - var parts = MMap[(Int, Int), CircuitPart]() - var errors = Map.empty[Point, (String, Int)] - - private var scheduledTicks = MMap[(Int, Int), Long]() - - /** Mapped inputs and outputs of this IC. Outputs go to the world, inputs come - * in from the world. OOOO OOOO OOOO OOOO IIII IIII IIII IIII - */ - val iostate = Array(0, 0, 0, 0) - - var outputChangedDelegate = { () => () } - - def setInput(r: Int, state: Int) { - iostate(r) = iostate(r) & 0xffff0000 | state & 0xffff - } - - def setOutput(r: Int, state: Int) { - iostate(r) = iostate(r) & 0xffff | (state & 0xffff) << 16 - } - - def firstSetup(): Unit = { - val ioparts = parts.values.collect { case io: IOGateICPart => io } - ioparts.foreach(_.onOutputChange(0xf)) - } - - def onInputChanged(mask: Int) { - val ioparts = parts.values.collect { case io: IIOCircuitPart => io } - for (r <- 0 until 4) if ((mask & 1 << r) != 0) { - ioparts.foreach(_.onExtInputChanged(r)) - sendInputUpdate(r) - } - } - - def onOutputChanged(mask: Int) { - val ioparts = parts.values.collect { case io: IIOCircuitPart => io } - for (r <- 0 until 4) if ((mask & 1 << r) != 0) { - ioparts.foreach(_.onExtOutputChanged(r)) - outputChangedDelegate() - sendOutputUpdate(r) - } - } - - def save(tag: NBTTagCompound) { - tag.setString("name", name) - tag.setByte("sw", size.width.toByte) - tag.setByte("sh", size.height.toByte) - tag.setIntArray("iost", iostate) - - val tagList = new NBTTagList - for (part <- parts.values) { - val partTag = new NBTTagCompound - partTag.setByte("id", part.id.toByte) - partTag.setByte("xpos", part.x.toByte) - partTag.setByte("ypos", part.y.toByte) - part.save(partTag) - tagList.appendTag(partTag) - } - tag.setTag("parts", tagList) - - // etc - } - - def load(tag: NBTTagCompound) { - clear() - name = tag.getString("name") - size = Size(tag.getByte("sw") & 0xff, tag.getByte("sh") & 0xff) - val ta = tag.getIntArray("iost") - for (i <- 0 until 4) iostate(i) = ta(i) - - val partList = tag.getTagList("parts", 10) - for (i <- 0 until partList.tagCount) { - val partTag = partList.getCompoundTagAt(i) - val part = CircuitPart.createPart(partTag.getByte("id") & 0xff) - setPart_do( - partTag.getByte("xpos") & 0xff, - partTag.getByte("ypos") & 0xff, - part - ) - part.load(partTag) - } - - // etc - } - - def writeDesc(out: MCDataOutput) { - out.writeString(name) - out.writeByte(size.width).writeByte(size.height) - for (i <- 0 until 4) out.writeInt(iostate(i)) - - for (((x, y), part) <- parts) { - out.writeByte(part.id) - out.writeByte(x).writeByte(y) - part.writeDesc(out) - } - out.writeByte(255) - - // etc - } - - def readDesc(in: MCDataInput) { - clear() - name = in.readString() - size = Size(in.readUByte(), in.readUByte()) - for (i <- 0 until 4) iostate(i) = in.readInt() - - var id = in.readUByte() - while (id != 255) { - val part = CircuitPart.createPart(id) - setPart_do(in.readUByte(), in.readUByte(), part) - part.readDesc(in) - id = in.readUByte() - } - // etc - } - - def read(in: MCDataInput, key: Int) = key match { - case 0 => readDesc(in) - case 1 => - val part = CircuitPart.createPart(in.readUByte()) - setPart_do(in.readUByte(), in.readUByte(), part) - part.readDesc(in) - case 2 => removePart(in.readUByte(), in.readUByte()) - case 3 => CircuitOp.getOperation(in.readUByte()).readOp(this, in) - case 4 => - getPart(in.readUByte(), in.readUByte()) match { - case g: TClientNetCircuitPart => g.readClientPacket(in) - case _ => log.error("Server IC stream received invalid client packet") - } - case 5 => iostate(in.readUByte()) = in.readInt() - case 6 => setInput(in.readUByte(), in.readShort()) - case 7 => setOutput(in.readUByte(), in.readShort()) - case _ => - } - - def sendPartAdded(part: CircuitPart) { - val out = network.getICStreamOf(1) - out.writeByte(part.id) - out.writeByte(part.x).writeByte(part.y) - part.writeDesc(out) - } - - def sendRemovePart(x: Int, y: Int) { - network.getICStreamOf(2).writeByte(x).writeByte(y) - } - - def sendOpUse(op: CircuitOp, rotation: Int, configuration: Int, start: Point, end: Point) = { - if (op.checkOp(this, start, end)) { - op.writeOp(this, start, end, rotation, configuration, network.getICStreamOf(3).writeByte(op.id)) - true - } else false - } - - def sendClientPacket( - part: TClientNetCircuitPart, - writer: MCDataOutput => Unit - ) { - val s = network.getICStreamOf(4).writeByte(part.x).writeByte(part.y) - writer(s) - } - - def sendIOUpdate(r: Int) { - network.getICStreamOf(5).writeByte(r).writeInt(iostate(r)) - } - - def sendInputUpdate(r: Int) { - network.getICStreamOf(6).writeByte(r).writeShort(iostate(r) & 0xffff) - } - - def sendOutputUpdate(r: Int) { - network.getICStreamOf(7).writeByte(r).writeShort(iostate(r) >> 16) - } - - def clear() { - parts.values.foreach { _.unbind() } // remove references - parts = MMap() - scheduledTicks = MMap() - name = "untitled" - size = Size.zeroSize - for (i <- 0 until 4) iostate(i) = 0 - } - - def isEmpty = size == Size.zeroSize - def nonEmpty = !isEmpty - - private def assertCoords(x: Int, y: Int) { - if (!(0 until size.width contains x) || !(0 until size.height contains y)) - throw new IndexOutOfBoundsException( - "Circuit does not contain " + Point(x, y) - ) - } - - def tick() { - val t = network.getWorld.getTotalWorldTime - var rem = Seq[(Int, Int)]() - for ((k, v) <- scheduledTicks) if (v >= t) { - getPart(k._1, k._2).scheduledTick() - rem :+= k - } - rem.foreach(scheduledTicks.remove) - - for (part <- parts.values) part.update() - } - - def refreshErrors() { - val eparts = parts.values.collect { case p: IErrorCircuitPart => p } - val elist = Map.newBuilder[Point, (String, Int)] - - for (part <- eparts) { - val error = part.postErrors - if (error != null) - elist += Point(part.x, part.y) -> error - } - - errors = elist.result() - } - - def setPart(x: Int, y: Int, part: CircuitPart) { - setPart_do(x, y, part) - part.onAdded() - if (!network.isRemote) sendPartAdded(part) - } - private def setPart_do(x: Int, y: Int, part: CircuitPart) { - assertCoords(x, y) - part.bind(this, x, y) - parts += (x, y) -> part - } - - def getPart(x: Int, y: Int): CircuitPart = parts.getOrElse((x, y), null) - - def removePart(x: Int, y: Int) { - assertCoords(x, y) - val part = getPart(x, y) - if (part != null) { - if (!network.isRemote) sendRemovePart(x, y) - parts.remove((x, y)) - part.onRemoved() - part.unbind() - } - } - - def notifyNeighbor(x: Int, y: Int) { - val part = getPart(x, y) - if (part != null) part.onNeighborChanged() - } - - def notifyNeighbors(x: Int, y: Int, mask: Int) { - for (r <- 0 until 4) if ((mask & 1 << r) != 0) { - val point = Point(x, y).offset(r) - val part = getPart(point.x, point.y) - if (part != null) part.onNeighborChanged() - } - } - - def scheduleTick(x: Int, y: Int, ticks: Int) { - scheduledTicks += (x, y) -> (network.getWorld.getTotalWorldTime + ticks) - } - - // Convinience functions - def setPart(p: Point, part: CircuitPart) { setPart(p.x, p.y, part) } - def getPart(p: Point): CircuitPart = getPart(p.x, p.y) - def removePart(p: Point) { removePart(p.x, p.y) } - def notifyNeighbor(p: Point) { notifyNeighbor(p.x, p.y) } - def notifyNeighbors(p: Point, mask: Int) { notifyNeighbors(p.x, p.y, mask) } - def scheduleTick(p: Point, ticks: Int) { scheduleTick(p.x, p.y, ticks) } -} - -object CircuitPartDefs extends Enum { - type EnumVal = CircuitPartDef - - val Torch = CircuitPartDef(() => new TorchICPart) - val Lever = CircuitPartDef(() => new LeverICPart) - val Button = CircuitPartDef(() => new ButtonICPart) - - val AlloyWire = CircuitPartDef(() => new AlloyWireICPart) - val InsulatedWire = CircuitPartDef(() => new InsulatedWireICPart) - val BundledCable = CircuitPartDef(() => new BundledCableICPart) - - val IOGate = CircuitPartDef(() => new IOGateICPart) - val SimpleGate = CircuitPartDef(() => new ComboGateICPart) - val ComplexGate = CircuitPartDef(() => new SequentialGateICPart) - val ArrayGate = CircuitPartDef(() => new ArrayGateICPart) - - case class CircuitPartDef(factory: () => CircuitPart) extends Value { - def id = ordinal - override def name = s"$id" - - def createPart = factory.apply() - } -} - -object CircuitPart { - def createPart(id: Int) = CircuitPartDefs(id).createPart -} - -abstract class CircuitPart { - var world: IntegratedCircuit = null - var loc: (Byte, Byte) = null - - def bind(ic: IntegratedCircuit, x: Int, y: Int) { - world = ic - loc = (x.toByte, y.toByte) - } - - def unbind() { - world = null - loc = null - } - - def x = loc._1 & 0xff - def y = loc._2 & 0xff - def id = getPartType.id - - def getPartType: CircuitPartDefs.CircuitPartDef - - def save(tag: NBTTagCompound) {} - def load(tag: NBTTagCompound) {} - - def writeDesc(out: MCDataOutput) {} - def readDesc(in: MCDataInput) {} - - def writeStreamOf(key: Int): MCDataOutput = - world.network.getPartStream(x, y).writeByte(key) - def read(in: MCDataInput) { read(in, in.readUByte()) } - def read(in: MCDataInput, key: Int) = key match { - case 0 => readDesc(in) - case _ => - } - - def sendDescUpdate() { writeDesc(writeStreamOf(0)) } - - def update() {} - def scheduledTick() {} - def scheduleTick(ticks: Int) { world.scheduleTick(x, y, ticks) } - - def onAdded() {} - def onRemoved() {} - - def onNeighborChanged() {} - - @SideOnly(Side.CLIENT) - def onClicked() {} - @SideOnly(Side.CLIENT) - def onActivated() {} - - @SideOnly(Side.CLIENT) - def getPartName: String - @SideOnly(Side.CLIENT) - def getPickOp: CircuitOp = null - @SideOnly(Side.CLIENT) - def getRolloverData(detailLevel: Int): Seq[String] = - if (detailLevel > 0) Seq(getPartName) else Seq.empty - - @SideOnly(Side.CLIENT) - def renderDynamic(t: Transformation, ortho: Boolean, frame: Float) {} -} - -trait TClientNetCircuitPart extends CircuitPart { - def readClientPacket(in: MCDataInput) - - @SideOnly(Side.CLIENT) - def sendClientPacket(writer: MCDataOutput => Unit = { _ => }) { - world.sendClientPacket(this, writer) - } -} - -trait IErrorCircuitPart extends CircuitPart { - def postErrors: (String, Int) // (message, colour) -} - -trait IGuiCircuitPart extends TClientNetCircuitPart { - @SideOnly(Side.CLIENT) - def createGui: CircuitGui -} - -trait IPoweredCircuitPart { - def rsOutputLevel(r: Int): Int - def canConnectRS(r: Int): Boolean -}