|
| 1 | +package li.cil.oc.server.component |
| 2 | + |
| 3 | +import li.cil.oc.api.network._ |
| 4 | +import li.cil.oc.api.{Network, prefab} |
| 5 | +import li.cil.oc.common.event.BlockChangeHandler |
| 6 | +import li.cil.oc.common.event.BlockChangeHandler.ChangeListener |
| 7 | +import li.cil.oc.util.BlockPosition |
| 8 | +import li.cil.oc.util.ExtendedWorld._ |
| 9 | +import li.cil.oc.{Settings, api} |
| 10 | +import net.minecraft.nbt.NBTTagCompound |
| 11 | +import net.minecraft.util.Vec3 |
| 12 | +import net.minecraftforge.common.util.ForgeDirection |
| 13 | + |
| 14 | +/** |
| 15 | + * Mostly stolen from li.cil.oc.common.tileentity.Adapter |
| 16 | + * |
| 17 | + * @author Sangar, Vexatos |
| 18 | + */ |
| 19 | +class UpgradeMF(val host: EnvironmentHost, val coord: BlockPosition, val dir: ForgeDirection) extends prefab.ManagedEnvironment with ChangeListener { |
| 20 | + override val node = Network.newNode(this, Visibility.None). |
| 21 | + withConnector(). |
| 22 | + create() |
| 23 | + |
| 24 | + private var otherEnv: Option[api.network.Environment] = None |
| 25 | + private var otherDrv: Option[(ManagedEnvironment, api.driver.SidedBlock)] = None |
| 26 | + private var blockData: Option[BlockData] = None |
| 27 | + |
| 28 | + override val canUpdate = true |
| 29 | + |
| 30 | + // Not checking for range yet because host may be a moving adapter, who knows? |
| 31 | + BlockChangeHandler.addListener(this, coord) |
| 32 | + |
| 33 | + private def updateBoundState() { |
| 34 | + if (node != null && node.network != null && coord.world.exists(_.provider.dimensionId == host.world.provider.dimensionId) |
| 35 | + && coord.toVec3.distanceTo(Vec3.createVectorHelper(host.xPosition, host.yPosition, host.zPosition)) <= Settings.get.mfuRange) { |
| 36 | + host.world.getTileEntity(coord) match { |
| 37 | + case env: api.network.Environment => |
| 38 | + otherEnv = Some(env) |
| 39 | + // Remove any driver that might be there. |
| 40 | + otherDrv match { |
| 41 | + case Some((environment, driver)) => |
| 42 | + node.disconnect(environment.node) |
| 43 | + environment.save(blockData.get.data) |
| 44 | + Option(environment.node).foreach(_.remove()) |
| 45 | + otherDrv = None |
| 46 | + case _ => // Nothing to do here. |
| 47 | + } |
| 48 | + node.connect(env.node) |
| 49 | + case _ => |
| 50 | + // Remove any environment that might have been there. |
| 51 | + otherEnv match { |
| 52 | + case Some(environment) => |
| 53 | + node.disconnect(environment.node) |
| 54 | + otherEnv = None |
| 55 | + case _ => // Nothing to do here. |
| 56 | + } |
| 57 | + val (world, x, y, z) = (coord.world.get, coord.x, coord.y, coord.z) |
| 58 | + Option(api.Driver.driverFor(world, coord.x, coord.y, coord.z, dir)) match { |
| 59 | + case Some(newDriver) => |
| 60 | + otherDrv match { |
| 61 | + case Some((oldEnvironment, driver)) => |
| 62 | + if (newDriver != driver) { |
| 63 | + // This is... odd. Maybe moved by some other mod? First, clean up. |
| 64 | + otherDrv = None |
| 65 | + blockData = None |
| 66 | + node.disconnect(oldEnvironment.node) |
| 67 | + |
| 68 | + // Then rebuild - if we have something. |
| 69 | + val environment = newDriver.createEnvironment(world, x, y, z, dir) |
| 70 | + if (environment != null) { |
| 71 | + otherDrv = Some((environment, newDriver)) |
| 72 | + blockData = Some(new BlockData(environment.getClass.getName, new NBTTagCompound())) |
| 73 | + node.connect(environment.node) |
| 74 | + } |
| 75 | + } // else: the more things change, the more they stay the same. |
| 76 | + case _ => |
| 77 | + // A challenger appears. Maybe. |
| 78 | + val environment = newDriver.createEnvironment(world, x, y, z, dir) |
| 79 | + if (environment != null) { |
| 80 | + otherDrv = Some((environment, newDriver)) |
| 81 | + blockData match { |
| 82 | + case Some(data) if data.name == environment.getClass.getName => |
| 83 | + environment.load(data.data) |
| 84 | + case _ => |
| 85 | + } |
| 86 | + blockData = Some(new BlockData(environment.getClass.getName, new NBTTagCompound())) |
| 87 | + node.connect(environment.node) |
| 88 | + } |
| 89 | + } |
| 90 | + case _ => otherDrv match { |
| 91 | + case Some((environment, driver)) => |
| 92 | + // We had something there, but it's gone now... |
| 93 | + node.disconnect(environment.node) |
| 94 | + environment.save(blockData.get.data) |
| 95 | + Option(environment.node).foreach(_.remove()) |
| 96 | + otherDrv = None |
| 97 | + case _ => // Nothing before, nothing now. |
| 98 | + } |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + private def disconnect() { |
| 105 | + otherEnv match { |
| 106 | + case Some(environment) => |
| 107 | + node.disconnect(environment.node) |
| 108 | + otherEnv = None |
| 109 | + case _ => // Nothing to do here. |
| 110 | + } |
| 111 | + otherDrv match { |
| 112 | + case Some((environment, driver)) => |
| 113 | + node.disconnect(environment.node) |
| 114 | + environment.save(blockData.get.data) |
| 115 | + Option(environment.node).foreach(_.remove()) |
| 116 | + otherDrv = None |
| 117 | + case _ => // Nothing to do here. |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + override def onBlockChanged() = updateBoundState() |
| 122 | + |
| 123 | + override def update() { |
| 124 | + super.update() |
| 125 | + otherDrv match { |
| 126 | + case Some((env, drv)) if env.canUpdate => env.update() |
| 127 | + case _ => // No driver |
| 128 | + } |
| 129 | + if (host.world.getTotalWorldTime % Settings.get.tickFrequency == 0) { |
| 130 | + if (!node.tryChangeBuffer(-Settings.get.mfuCost * Settings.get.tickFrequency |
| 131 | + * coord.toVec3.distanceTo(Vec3.createVectorHelper(host.xPosition, host.yPosition, host.zPosition)))) { |
| 132 | + disconnect() |
| 133 | + } |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + override def onConnect(node: Node) { |
| 138 | + super.onConnect(node) |
| 139 | + if (node == this.node) { |
| 140 | + updateBoundState() |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + override def onDisconnect(node: Node) { |
| 145 | + super.onDisconnect(node) |
| 146 | + otherEnv match { |
| 147 | + case Some(env) if node == env.node => otherEnv = None |
| 148 | + case _ => // No environment |
| 149 | + } |
| 150 | + otherDrv match { |
| 151 | + case Some((env, drv)) if node == env.node => otherDrv = None |
| 152 | + case _ => // No driver |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + override def load(nbt: NBTTagCompound) { |
| 157 | + super.load(nbt) |
| 158 | + Option(nbt.getCompoundTag(Settings.namespace + "adapter.block")) match { |
| 159 | + case Some(blockNbt: NBTTagCompound) => |
| 160 | + if (blockNbt.hasKey("name") && blockNbt.hasKey("data")) { |
| 161 | + blockData = Some(new BlockData(blockNbt.getString("name"), blockNbt.getCompoundTag("data"))) |
| 162 | + } |
| 163 | + case _ => // Invalid tag |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + override def save(nbt: NBTTagCompound) { |
| 168 | + super.save(nbt) |
| 169 | + val blockNbt = new NBTTagCompound() |
| 170 | + blockData.foreach({ data => |
| 171 | + otherDrv.foreach(_._1.save(data.data)) |
| 172 | + blockNbt.setString("name", data.name) |
| 173 | + blockNbt.setTag("data", data.data) |
| 174 | + }) |
| 175 | + nbt.setTag(Settings.namespace + "adapter.block", blockNbt) |
| 176 | + } |
| 177 | + |
| 178 | + // ----------------------------------------------------------------------- // |
| 179 | + |
| 180 | + private class BlockData(val name: String, val data: NBTTagCompound) |
| 181 | + |
| 182 | +} |
0 commit comments