Skip to content

File tree

11 files changed

+366
-0
lines changed

11 files changed

+366
-0
lines changed
 

Diff for: ‎src/main/resources/application.conf

+7
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,10 @@ opencomputers {
807807

808808
# Energy consumed when reconfiguring nanomachines.
809809
nanomachinesReconfigure: 5000
810+
811+
# Energy consumed by a MFU per tick while connected.
812+
# Similar to `wirelessCostPerRange`, this is multiplied with the distance to the bound block.
813+
mfuRelay: 1
810814
}
811815

812816
# The rate at which different blocks accept external power. All of these
@@ -1342,6 +1346,9 @@ opencomputers {
13421346
# The maximum range between the drone/robot and a villager for a trade to
13431347
# be performed by the trading upgrade
13441348
tradingRange: 8.0
1349+
1350+
# Radius the MFU is able to operate in
1351+
mfuRange: 3
13451352
}
13461353

13471354
# Settings for mod integration (the mod previously known as OpenComponents).

Diff for: ‎src/main/resources/assets/opencomputers/lang/en_US.lang

+4
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ item.oc.UpgradeHover1.name=Hover Upgrade (Tier 2)
144144
item.oc.UpgradeInventory.name=Inventory Upgrade
145145
item.oc.UpgradeInventoryController.name=Inventory Controller Upgrade
146146
item.oc.UpgradeLeash.name=Leash Upgrade
147+
item.oc.UpgradeMF.name=MFU
147148
item.oc.UpgradeNavigation.name=Navigation Upgrade
148149
item.oc.UpgradePiston.name=Piston Upgrade
149150
item.oc.UpgradeSign.name=Sign I/O Upgrade
@@ -370,6 +371,9 @@ oc:tooltip.UpgradeGenerator=Can be used to generate energy from fuel on the go.
370371
oc:tooltip.UpgradeHover=This upgrade allows robots to fly higher above the ground without having to climb walls.[nl] Maximum height: §f%s§7
371372
oc:tooltip.UpgradeInventory=This upgrade provides inventory space to a robot or drone. Without one of these, they will not be able to store items internally.
372373
oc:tooltip.UpgradeInventoryController=This upgrade allows robots and drones more control in how it interacts with external inventories, and allows robots to swap their equipped tool with an item in their inventory.
374+
oc:tooltip.UpgradeMF=TODO really, do this
375+
oc:tooltip.UpgradeMF.Linked=§fConnection established§7
376+
oc:tooltip.UpgradeMF.Unlinked=§fNo connection§7
373377
oc:tooltip.UpgradeLeash=Allows some devices, such as drones, to bind Isaa- excuse me... *chatter* My apologies. I'm just being told this is actually used to put animals on a leash. Multiple animals, even. Odd.
374378
oc:tooltip.UpgradeNavigation=Can be used to determine the position and orientation of a device. The position is relative to the center of the map that was used to craft this upgrade.
375379
oc:tooltip.UpgradePiston=This upgrade is very pushy. It allows moving blocks, similar to when using a piston. It does §lnot§7 move entities, however.

Diff for: ‎src/main/resources/assets/opencomputers/recipes/default.recipes

+5
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ inventoryControllerUpgrade {
295295
[dropper, "oc:circuitChip2", craftingPiston]
296296
[ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
297297
}
298+
mfu {
299+
input: [["oc:chamelium", gemLapis, "oc:chamelium"]
300+
["oc:linkedCard", "oc:adapter", "oc:linkedCard"]
301+
["oc:chamelium", gemLapis, "oc:chamelium"]]
302+
}
298303
leashUpgrade {
299304
input: [[ingotIron, lead, ingotIron]
300305
[lead, "oc:materialCU", lead]

Diff for: ‎src/main/scala/li/cil/oc/Constants.scala

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ object Constants {
118118
final val LinkedCard = "linkedCard"
119119
final val LootDisk = "lootDisk"
120120
final val LuaBios = "luaBios"
121+
final val MFU = "mfu"
121122
final val Manual = "manual"
122123
final val MicrocontrollerCaseCreative = "microcontrollerCaseCreative"
123124
final val MicrocontrollerCaseTier1 = "microcontrollerCase1"

Diff for: ‎src/main/scala/li/cil/oc/Settings.scala

+2
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ class Settings(val config: Config) {
214214
val transposerCost = config.getDouble("power.cost.transposer") max 0
215215
val nanomachineCost = config.getDouble("power.cost.nanomachineInput") max 0
216216
val nanomachineReconfigureCost = config.getDouble("power.cost.nanomachinesReconfigure") max 0
217+
val mfuCost = config.getDouble("power.cost.mfuRelay") max 0
217218

218219
// power.rate
219220
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
@@ -348,6 +349,7 @@ class Settings(val config: Config) {
348349
val serverRackSwitchTier = (config.getInt("misc.serverRackSwitchTier") - 1) max Tier.None min Tier.Three
349350
val redstoneDelay = config.getDouble("misc.redstoneDelay") max 0
350351
val tradingRange = config.getDouble("misc.tradingRange") max 0
352+
val mfuRange = config.getInt("misc.mfuRange") max 0 min 128
351353

352354
// ----------------------------------------------------------------------- //
353355
// nanomachines
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package li.cil.oc.common.event
2+
3+
import cpw.mods.fml.common.eventhandler.SubscribeEvent
4+
import li.cil.oc.util.BlockPosition
5+
import net.minecraft.entity.Entity
6+
import net.minecraft.entity.player.EntityPlayer
7+
import net.minecraft.world.{IWorldAccess, World}
8+
import net.minecraftforge.event.world.WorldEvent
9+
10+
import scala.collection.mutable
11+
12+
/**
13+
*
14+
* @author Vexatos
15+
*/
16+
object BlockChangeHandler {
17+
18+
def addListener(listener: ChangeListener, coord: BlockPosition) = {
19+
changeListeners.synchronized {
20+
changeListeners.put(listener, coord)
21+
}
22+
}
23+
24+
private val changeListeners = mutable.WeakHashMap.empty[ChangeListener, BlockPosition]
25+
26+
@SubscribeEvent
27+
def onWorldLoad(e: WorldEvent.Load) {
28+
e.world.addWorldAccess(new Listener(e.world))
29+
}
30+
31+
trait ChangeListener {
32+
def onBlockChanged()
33+
}
34+
35+
private class Listener(world: World) extends IWorldAccess {
36+
37+
override def markBlockForUpdate(x: Int, y: Int, z: Int): Unit = {
38+
val current = BlockPosition(x, y, z, world)
39+
changeListeners.synchronized {
40+
for ((listener, coord) <- changeListeners) if (coord.equals(current)) {
41+
listener.onBlockChanged()
42+
}
43+
}
44+
}
45+
46+
override def playRecord(recordName: String, x: Int, y: Int, z: Int) {}
47+
48+
override def playAuxSFX(player: EntityPlayer, sfxType: Int, x: Int, y: Int, z: Int, data: Int) {}
49+
50+
override def onEntityDestroy(entity: Entity) {}
51+
52+
override def destroyBlockPartially(breakerId: Int, x: Int, y: Int, z: Int, progress: Int) {}
53+
54+
override def markBlockForRenderUpdate(x: Int, y: Int, z: Int) {}
55+
56+
override def spawnParticle(particleType: String, x: Double, y: Double, z: Double, velX: Double, velY: Double, velZ: Double) {}
57+
58+
override def playSound(soundName: String, x: Double, y: Double, z: Double, volume: Float, pitch: Float) {}
59+
60+
override def broadcastSound(soundID: Int, x: Int, y: Int, z: Int, data: Int) {}
61+
62+
override def playSoundToNearExcept(player: EntityPlayer, soundName: String, x: Double, y: Double, z: Double, volume: Float, pitch: Float) {}
63+
64+
override def markBlockRangeForRenderUpdate(x1: Int, y1: Int, z1: Int, x2: Int, y2: Int, z2: Int) {}
65+
66+
override def onEntityCreate(entity: Entity) {}
67+
68+
override def onStaticEntitiesChanged() {}
69+
}
70+
71+
}

Diff for: ‎src/main/scala/li/cil/oc/common/init/Items.scala

+1
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ object Items extends ItemAPI {
534534
Recipes.addSubItem(new item.DiskDriveMountable(multi), Constants.ItemName.DiskDriveMountable, "oc:diskDriveMountable")
535535
Recipes.addSubItem(new item.UpgradeTrading(multi), Constants.ItemName.TradingUpgrade, "oc:tradingUpgrade")
536536
registerItem(new item.DiamondChip(multi), Constants.ItemName.DiamondChip)
537+
Recipes.addSubItem(new item.UpgradeMF(multi), Constants.ItemName.MFU, "oc:mfu")
537538

538539
// Register aliases.
539540
for ((k, v) <- aliases) {

Diff for: ‎src/main/scala/li/cil/oc/common/item/UpgradeMF.scala

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package li.cil.oc.common.item
2+
3+
import java.util
4+
5+
import li.cil.oc.Settings
6+
import li.cil.oc.util.ExtendedWorld._
7+
import li.cil.oc.util.{BlockPosition, Tooltip}
8+
import net.minecraft.entity.player.EntityPlayer
9+
import net.minecraft.item.ItemStack
10+
import net.minecraft.nbt.NBTTagCompound
11+
import net.minecraft.tileentity.TileEntity
12+
13+
class UpgradeMF(val parent: Delegator) extends traits.Delegate with traits.ItemTier {
14+
15+
override def onItemUseFirst(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
16+
if (!player.worldObj.isRemote && player.isSneaking) {
17+
player.worldObj.getTileEntity(position) match {
18+
case tile: TileEntity =>
19+
if (!stack.hasTagCompound) {
20+
stack.setTagCompound(new NBTTagCompound())
21+
}
22+
val data = stack.getTagCompound
23+
data.setIntArray(Settings.namespace + "coord", Array(position.x, position.y, position.z, player.worldObj.provider.dimensionId, side))
24+
return true
25+
case _ =>
26+
}
27+
}
28+
super.onItemUseFirst(stack, player, position, side, hitX, hitY, hitZ)
29+
}
30+
31+
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
32+
stack.getTagCompound match {
33+
case data: NBTTagCompound =>
34+
tooltip.addAll(Tooltip.get(super.unlocalizedName + (if (data.hasKey("coord")) ".Linked" else ".Unlinked")))
35+
case _ =>
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package li.cil.oc.integration.opencomputers
2+
3+
import li.cil.oc.api.driver.EnvironmentProvider
4+
import li.cil.oc.api.driver.item.HostAware
5+
import li.cil.oc.api.network.{EnvironmentHost, ManagedEnvironment}
6+
import li.cil.oc.common.{Slot, Tier}
7+
import li.cil.oc.server.component
8+
import li.cil.oc.util.BlockPosition
9+
import li.cil.oc.{Constants, Settings, api}
10+
import net.minecraft.item.ItemStack
11+
import net.minecraftforge.common.DimensionManager
12+
import net.minecraftforge.common.util.ForgeDirection
13+
14+
/**
15+
*
16+
* @author Vexatos
17+
*/
18+
object DriverUpgradeMF extends Item with HostAware {
19+
override def worksWith(stack: ItemStack): Boolean = isOneOf(stack,
20+
api.Items.get(Constants.ItemName.MFU))
21+
22+
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]): Boolean =
23+
worksWith(stack) && isAdapter(host)
24+
25+
override def slot(stack: ItemStack): String = Slot.Upgrade
26+
27+
override def tier(stack: ItemStack) = Tier.Three
28+
29+
override def createEnvironment(stack: ItemStack, host: EnvironmentHost): ManagedEnvironment = {
30+
if (host.world != null && !host.world.isRemote) {
31+
if (stack.hasTagCompound) {
32+
stack.getTagCompound.getIntArray(Settings.namespace + "coord") match {
33+
case Array(x, y, z, dim, side) =>
34+
Option(DimensionManager.getWorld(dim)) match {
35+
case Some(world) => return new component.UpgradeMF(host, BlockPosition(x, y, z), ForgeDirection.getOrientation(side))
36+
case _ => // Invalid dimension ID
37+
}
38+
case _ => // Invalid tag
39+
}
40+
}
41+
}
42+
null
43+
}
44+
45+
object Provider extends EnvironmentProvider {
46+
override def getEnvironment(stack: ItemStack): Class[_] =
47+
if (worksWith(stack))
48+
classOf[component.UpgradeMF]
49+
else null
50+
}
51+
52+
}

Diff for: ‎src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ object ModOpenComputers extends ModProxy {
7979

8080
MinecraftForge.EVENT_BUS.register(Analyzer)
8181
MinecraftForge.EVENT_BUS.register(AngelUpgradeHandler)
82+
MinecraftForge.EVENT_BUS.register(BlockChangeHandler)
8283
MinecraftForge.EVENT_BUS.register(ChunkloaderUpgradeHandler)
8384
MinecraftForge.EVENT_BUS.register(EventHandler)
8485
MinecraftForge.EVENT_BUS.register(ExperienceUpgradeHandler)
@@ -147,6 +148,7 @@ object ModOpenComputers extends ModProxy {
147148
api.Driver.add(DriverUpgradeTankController)
148149
api.Driver.add(DriverUpgradeTractorBeam)
149150
api.Driver.add(DriverUpgradeTrading)
151+
api.Driver.add(DriverUpgradeMF)
150152

151153
api.Driver.add(DriverAPU.Provider)
152154
api.Driver.add(DriverDataCard.Provider)
@@ -174,6 +176,7 @@ object ModOpenComputers extends ModProxy {
174176
api.Driver.add(DriverUpgradeSign.Provider)
175177
api.Driver.add(DriverUpgradeTankController.Provider)
176178
api.Driver.add(DriverUpgradeTractorBeam.Provider)
179+
api.Driver.add(DriverUpgradeMF.Provider)
177180

178181
api.Driver.add(EnvironmentProviderBlocks)
179182

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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

Comments
 (0)
Please sign in to comment.