Added microcontrollers, closes #711.

Solar generator is now tier two to allow better balance of microcontroller.
This commit is contained in:
Florian Nücke 2014-12-08 22:17:52 +01:00
parent 981d2ffb6f
commit 451ab1b4d4
49 changed files with 694 additions and 92 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,25 @@
package li.cil.oc.api.internal;
import li.cil.oc.api.driver.EnvironmentHost;
import li.cil.oc.api.machine.Machine;
import li.cil.oc.api.network.Environment;
/**
* This interface is implemented as a marker by microcontrollers.
* <p/>
* This is implemented by microcontroller tile entities. That means you can
* use this to check for microcontrollers by using:
* <pre>
* if (tileEntity instanceof Microcontroller) {
* </pre>
* <p/>
* The only purpose is to allow identifying tile entities as microcontrollers
* via the API, i.e. without having to link against internal classes. This
* also means that <em>you should not implement this</em>.
*/
public interface Microcontroller extends Environment, EnvironmentHost, Rotatable {
/**
* The machine currently hosted by this computer case.
*/
Machine machine();
}

View File

@ -667,6 +667,20 @@ opencomputers {
# The amount of energy pushing blocks with the piston upgrade costs. # The amount of energy pushing blocks with the piston upgrade costs.
pistonPush: 20 pistonPush: 20
# Energy it costs to re-program an EEPROM. This is deliberately
# expensive, to discourage frequent re-writing of EEPROMs.
eepromWrite: 50
# Amount of energy a microcontroller consumes per tick while running.
microcontroller: 0.1
# The base energy cost for assembling a microcontroller.
microcontrollerAssemblyBase: 10000
# The additional amount of energy required to assemble a
# microcontroller for each point of complexity.
microcontrollerAssemblyComplexity: 10000
} }
# The rate at which different blocks accept external power. All of these # The rate at which different blocks accept external power. All of these

View File

@ -19,6 +19,7 @@ tile.oc.geolyzer.name=Geolyzer
tile.oc.keyboard.name=Keyboard tile.oc.keyboard.name=Keyboard
tile.oc.hologram1.name=Hologram Projector (Tier 1) tile.oc.hologram1.name=Hologram Projector (Tier 1)
tile.oc.hologram2.name=Hologram Projector (Tier 2) tile.oc.hologram2.name=Hologram Projector (Tier 2)
tile.oc.microcontroller.name=Microcontroller
tile.oc.motionSensor.name=Motion Sensor tile.oc.motionSensor.name=Motion Sensor
tile.oc.powerConverter.name=Power Converter tile.oc.powerConverter.name=Power Converter
tile.oc.powerDistributor.name=Power Distributor tile.oc.powerDistributor.name=Power Distributor
@ -74,6 +75,7 @@ item.oc.Memory5.name=Memory (Tier 3.5)
item.oc.Microchip0.name=Microchip (Tier 1) item.oc.Microchip0.name=Microchip (Tier 1)
item.oc.Microchip1.name=Microchip (Tier 2) item.oc.Microchip1.name=Microchip (Tier 2)
item.oc.Microchip2.name=Microchip (Tier 3) item.oc.Microchip2.name=Microchip (Tier 3)
item.oc.MicrocontrollerCase.name=Microcontroller Case
item.oc.NetworkCard.name=Network Card item.oc.NetworkCard.name=Network Card
item.oc.NumPad.name=Numeric Keypad item.oc.NumPad.name=Numeric Keypad
item.oc.PrintedCircuitBoard.name=Printed Circuit Board (PCB) item.oc.PrintedCircuitBoard.name=Printed Circuit Board (PCB)
@ -230,6 +232,8 @@ oc:tooltip.MaterialCosts=Hold [§f%s§7] for material costs.
oc:tooltip.Materials=Materials: oc:tooltip.Materials=Materials:
oc:tooltip.Memory=Required to get computers to run. The more you have, the more complex the programs you can run. oc:tooltip.Memory=Required to get computers to run. The more you have, the more complex the programs you can run.
oc:tooltip.Microchip=The chip formerly known as Integrated Circuit. I have no idea why this works with redstone, but it does. oc:tooltip.Microchip=The chip formerly known as Integrated Circuit. I have no idea why this works with redstone, but it does.
oc:tooltip.Microcontroller=Microcontrollers are computers boiled down to the essentials. They are intended to take care of very specific tasks, running only a single program that is provided on the EEPROM built into them.
oc:tooltip.MicrocontrollerCase=Base component for building microcontrollers. Place it into an assembler to add further components and assemble a microcontroller.
oc:tooltip.MotionSensor=Can detect movement of nearby living beings. Requires clear line-of-sight. oc:tooltip.MotionSensor=Can detect movement of nearby living beings. Requires clear line-of-sight.
oc:tooltip.NetworkCard=Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other. oc:tooltip.NetworkCard=Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other.
oc:tooltip.PowerAcceptor=Energy conversion speed: §f%s/t§7 oc:tooltip.PowerAcceptor=Energy conversion speed: §f%s/t§7
@ -299,6 +303,7 @@ item.oc.HardDiskDrive.usage=The §oHard Disk Drives§r are the higher tier stora
item.oc.InternetCard.usage=The §oInternet Card§r grants computers access to the internet. It provides ways to perform simple HTTP requests, as well as to open plain TCP client sockets that can be read and written to.[nl][nl]Installing an internet card in a computer will also attach a custom file system that contains a few internet related applications, such as one for downloading and uploading snippets from and to pastebin as well as a wannabe wget clone that allows downloading data from arbitrary HTTP URLs. item.oc.InternetCard.usage=The §oInternet Card§r grants computers access to the internet. It provides ways to perform simple HTTP requests, as well as to open plain TCP client sockets that can be read and written to.[nl][nl]Installing an internet card in a computer will also attach a custom file system that contains a few internet related applications, such as one for downloading and uploading snippets from and to pastebin as well as a wannabe wget clone that allows downloading data from arbitrary HTTP URLs.
item.oc.LinkedCard.usage=The §oLinked Card§r is a specialized but advanced version of a network card. It can only operate in pairs, providing a point-to-point communication between the paired cards. In return the distance the cards can communicate over is unlimited. They can even communicate when in different dimensions. item.oc.LinkedCard.usage=The §oLinked Card§r is a specialized but advanced version of a network card. It can only operate in pairs, providing a point-to-point communication between the paired cards. In return the distance the cards can communicate over is unlimited. They can even communicate when in different dimensions.
item.oc.Memory.usage=§oMemory§r is, like a §oCPU§r, an essential part in all computers. Depending on the CPU's architecture, the memory has a very essential effect on what a computer can and cannot do. For the standard Lua architecture, for example, it controls the actual amount of memory Lua scripts can use. This means that to run larger and more memory-intensive programs, you'll need more RAM. item.oc.Memory.usage=§oMemory§r is, like a §oCPU§r, an essential part in all computers. Depending on the CPU's architecture, the memory has a very essential effect on what a computer can and cannot do. For the standard Lua architecture, for example, it controls the actual amount of memory Lua scripts can use. This means that to run larger and more memory-intensive programs, you'll need more RAM.
item.oc.MicrocontrollerCase.usage=The §oMicrocontroller Case§r is the base part when building microcontrollers in the §oAssembler§r. Microcontrollers are very primitive computers. They may only contain a very limited number of components, and are intended to be used in very specific use-cases, such as transforming or reacting to redstone signals, or processing network messages.[nl][nl]They do not have an actual file system. All programming must be done using the EEPROM chip built into them. This chip can be swapped for another one by crafting a microcontroller with the chip to insert. The old EEPROM will be returned to your inventory.[nl][nl]While they also require power to run, they consume very little energy.
item.oc.NetworkCard.usage=The §oNetwork Card§r allows computers to send and receive network messages. Such messages (or packets) can be either sent as a broadcast, in which case they will be sent to all nodes in the same subnetwork, or sent to specific target, in which case they will only be received by the node with the specified target address. §oSwitches§r and §oAccess Points§r can be used to bridge multiple subnetworks by relaying messages between the subnetworks they are connected to. It is also possible to send a targeted message if the receiver is in another subnetwork, if the networks are connected via one or more switches. item.oc.NetworkCard.usage=The §oNetwork Card§r allows computers to send and receive network messages. Such messages (or packets) can be either sent as a broadcast, in which case they will be sent to all nodes in the same subnetwork, or sent to specific target, in which case they will only be received by the node with the specified target address. §oSwitches§r and §oAccess Points§r can be used to bridge multiple subnetworks by relaying messages between the subnetworks they are connected to. It is also possible to send a targeted message if the receiver is in another subnetwork, if the networks are connected via one or more switches.
item.oc.RedstoneCard.usage=The §oRedstone Card§r allows computers to read and emit analog redstone signal in adjacent blocks. When an ingoing signal strength changes, a signal is injected into the computer.[nl][nl]If there are any supported mods present that provide bundled redstone facilities, such as RedLogic, Project Red or MineFactory Reloaded, or mods that provide wireless redstone facilities such as WR-CBE and Slimevoid's Wireless mod, a second tier card is available that allows interacting with these systems.[nl][nl]The side provided to the several methods are relative to the orientation of the computer case / robot / server rack. That means when looking at the front of the computer, right is at your left and vice versa. item.oc.RedstoneCard.usage=The §oRedstone Card§r allows computers to read and emit analog redstone signal in adjacent blocks. When an ingoing signal strength changes, a signal is injected into the computer.[nl][nl]If there are any supported mods present that provide bundled redstone facilities, such as RedLogic, Project Red or MineFactory Reloaded, or mods that provide wireless redstone facilities such as WR-CBE and Slimevoid's Wireless mod, a second tier card is available that allows interacting with these systems.[nl][nl]The side provided to the several methods are relative to the orientation of the computer case / robot / server rack. That means when looking at the front of the computer, right is at your left and vice versa.
item.oc.Server.usage=§oServers§r are a form of higher tier computer. They can be configured by holding them in the hand and rightclicking - like opening a backpack or ender pouch, for example. After inserting CPU, memory and cards, the server has to be placed inside a §oServer Rack§r. For more information see the server rack entry. item.oc.Server.usage=§oServers§r are a form of higher tier computer. They can be configured by holding them in the hand and rightclicking - like opening a backpack or ender pouch, for example. After inserting CPU, memory and cards, the server has to be placed inside a §oServer Rack§r. For more information see the server rack entry.

View File

@ -6,6 +6,11 @@ analyzer {
["oc:materialTransistor", nuggetGold, ""] ["oc:materialTransistor", nuggetGold, ""]
["oc:materialCircuitBoardPrinted", nuggetGold, ""]] ["oc:materialCircuitBoardPrinted", nuggetGold, ""]]
} }
microcontrollerCase {
input: [[nuggetIron, "oc:circuitChip1", nuggetIron]
[redstone, chest, redstone]
[nuggetIron, "oc:materialCircuitBoardPrinted", nuggetIron]]
}
terminal { terminal {
input: [[nuggetIron, "oc:solarGeneratorUpgrade", nuggetIron] input: [[nuggetIron, "oc:solarGeneratorUpgrade", nuggetIron]
["oc:circuitChip3", "oc:screen2", "oc:wlanCard"] ["oc:circuitChip3", "oc:screen2", "oc:wlanCard"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

View File

@ -178,6 +178,10 @@ class Settings(val config: Config) {
val disassemblerItemCost = config.getDouble("power.cost.disassemblerPerItem") max 0 val disassemblerItemCost = config.getDouble("power.cost.disassemblerPerItem") max 0
val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0 val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0
val pistonCost = config.getDouble("power.cost.pistonPush") max 0 val pistonCost = config.getDouble("power.cost.pistonPush") max 0
val microcontrollerCost = config.getDouble("power.cost.microcontroller") max 0
val eepromWriteCost = config.getDouble("power.cost.eepromWrite") max 0
val microcontrollerBaseCost = config.getDouble("power.cost.microcontrollerAssemblyBase") max 0
val microcontrollerComplexityCost = config.getDouble("power.cost.microcontrollerAssemblyComplexity") max 0
// power.rate // power.rate
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0 val accessPointRate = config.getDouble("power.rate.accessPoint") max 0

View File

@ -55,6 +55,7 @@ private[oc] class Proxy extends CommonProxy {
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.DiskDrive], DiskDriveRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.DiskDrive], DiskDriveRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Geolyzer], GeolyzerRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Geolyzer], GeolyzerRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer)

View File

@ -37,6 +37,8 @@ object Textures {
val blockCaseFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontActivity.png") val blockCaseFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontActivity.png")
val blockDiskDriveFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/DiskDriveFrontActivity.png") val blockDiskDriveFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/DiskDriveFrontActivity.png")
val blockHologram = new ResourceLocation(Settings.resourceDomain, "textures/blocks/HologramEffect.png") val blockHologram = new ResourceLocation(Settings.resourceDomain, "textures/blocks/HologramEffect.png")
val blockMicrocontrollerFrontLight = new ResourceLocation(Settings.resourceDomain, "textures/blocks/MicrocontrollerFrontLight.png")
val blockMicrocontrollerFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/MicrocontrollerFrontOn.png")
val blockRackFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontOn.png") val blockRackFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontOn.png")
val blockRackFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontActivity.png") val blockRackFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontActivity.png")
val blockRaidFrontError = new ResourceLocation(Settings.resourceDomain, "textures/blocks/RaidFrontError.png") val blockRaidFrontError = new ResourceLocation(Settings.resourceDomain, "textures/blocks/RaidFrontError.png")
@ -105,7 +107,10 @@ object Textures {
tm.bindTexture(guiSlot) tm.bindTexture(guiSlot)
tm.bindTexture(blockCaseFrontOn) tm.bindTexture(blockCaseFrontOn)
tm.bindTexture(blockCaseFrontActivity)
tm.bindTexture(blockHologram) tm.bindTexture(blockHologram)
tm.bindTexture(blockMicrocontrollerFrontLight)
tm.bindTexture(blockMicrocontrollerFrontOn)
tm.bindTexture(blockRackFrontOn) tm.bindTexture(blockRackFrontOn)
tm.bindTexture(blockRobot) tm.bindTexture(blockRobot)
tm.bindTexture(blockScreenUpIndicator) tm.bindTexture(blockScreenUpIndicator)

View File

@ -0,0 +1,62 @@
package li.cil.oc.client.renderer.tileentity
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity.Microcontroller
import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
object MicrocontrollerRenderer extends TileEntitySpecialRenderer {
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val mcu = tileEntity.asInstanceOf[Microcontroller]
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(1)
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
mcu.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslated(-0.5, 0.5, 0.505)
GL11.glScalef(1, -1, 1)
bindTexture(Textures.blockMicrocontrollerFrontLight)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(0, 1, 0, 0, 1)
t.addVertexWithUV(1, 1, 0, 1, 1)
t.addVertexWithUV(1, 0, 0, 1, 0)
t.addVertexWithUV(0, 0, 0, 0, 0)
t.draw()
if (mcu.isRunning) {
bindTexture(Textures.blockMicrocontrollerFrontOn)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(0, 1, 0, 0, 1)
t.addVertexWithUV(1, 1, 0, 1, 1)
t.addVertexWithUV(1, 0, 0, 1, 0)
t.addVertexWithUV(0, 0, 0, 0, 0)
t.draw()
}
GL11.glPopMatrix()
GL11.glPopAttrib()
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
}
}

View File

@ -8,6 +8,7 @@ import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent import cpw.mods.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent
import li.cil.oc._ import li.cil.oc._
import li.cil.oc.api.Network import li.cil.oc.api.Network
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.client.renderer.PetRenderer import li.cil.oc.client.renderer.PetRenderer
import li.cil.oc.client.{PacketSender => ClientPacketSender} import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.tileentity.traits.power import li.cil.oc.common.tileentity.traits.power
@ -20,6 +21,7 @@ import li.cil.oc.util.SideTracker
import li.cil.oc.util.UpdateCheck import li.cil.oc.util.UpdateCheck
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.entity.player.EntityPlayerMP import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
@ -145,23 +147,36 @@ object EventHandler {
ClientPacketSender.sendPetVisibility() ClientPacketSender.sendPetVisibility()
} }
lazy val eeprom = api.Items.get("eeprom")
lazy val mcu = api.Items.get("microcontroller")
lazy val navigationUpgrade = api.Items.get("navigationUpgrade") lazy val navigationUpgrade = api.Items.get("navigationUpgrade")
@SubscribeEvent @SubscribeEvent
def onCrafting(e: ItemCraftedEvent) = { def onCrafting(e: ItemCraftedEvent) = {
if (api.Items.get(e.crafting) == navigationUpgrade) { recraft(e, navigationUpgrade, stack => {
Option(api.Driver.driverFor(e.crafting)).foreach(driver => // Restore the map currently used in the upgrade.
for (i <- 0 until e.craftMatrix.getSizeInventory) { Option(api.Driver.driverFor(e.crafting)) match {
val stack = e.craftMatrix.getStackInSlot(i) case Some(driver) => Option(ItemUtils.loadStack(driver.dataTag(stack).getCompoundTag(Settings.namespace + "map")))
if (stack != null && api.Items.get(stack) == navigationUpgrade) { case _ => None
// Restore the map currently used in the upgrade. }
val nbt = driver.dataTag(stack) })
val map = ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
if (map != null && !e.player.inventory.addItemStackToInventory(map)) { recraft(e, mcu, stack => {
e.player.dropPlayerItemWithRandomChoice(map, false) // Restore EEPROM currently used in microcontroller.
} new ItemUtils.MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
} })
}) }
private def recraft(e: ItemCraftedEvent, item: ItemInfo, callback: ItemStack => Option[ItemStack]): Unit = {
if (api.Items.get(e.crafting) == item) {
for (slot <- 0 until e.craftMatrix.getSizeInventory) {
val stack = e.craftMatrix.getStackInSlot(slot)
if (api.Items.get(stack) == item) {
callback(stack).foreach(extra => if (!e.player.inventory.addItemStackToInventory(extra)) {
e.player.dropPlayerItemWithRandomChoice(extra, false)
})
}
}
} }
} }

View File

@ -0,0 +1,99 @@
package li.cil.oc.common.block
import java.util
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.ItemUtils
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.util.MovingObjectPosition
import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection
class Microcontroller extends RedstoneAware with traits.PowerAcceptor {
override protected def customTextures = Array(
Some("MicrocontrollerTop"),
Some("MicrocontrollerTop"),
Some("MicrocontrollerSide"),
Some("MicrocontrollerFront"),
Some("MicrocontrollerSide"),
Some("MicrocontrollerSide")
)
// ----------------------------------------------------------------------- //
override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case mcu: tileentity.Microcontroller => mcu.info.copyItemStack()
case _ => null
}
// Custom drop logic for NBT tagged item stack.
override def getDrops(world: World, x: Int, y: Int, z: Int, metadata: Int, fortune: Int) = new java.util.ArrayList[ItemStack]()
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int) {}
// ----------------------------------------------------------------------- //
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.MicrocontrollerData(stack)
for (component <- info.components) {
tooltip.add("- " + component.getDisplayName)
}
}
}
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.caseRate(Tier.One)
override def createTileEntity(world: World, metadata: Int) = new tileentity.Microcontroller()
// ----------------------------------------------------------------------- //
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking && !Wrench.holdsApplicableWrench(player, x, y, z)) {
if (!world.isRemote) {
world.getTileEntity(x, y, z) match {
case mcu: tileentity.Microcontroller =>
if (mcu.machine.isRunning) mcu.machine.stop()
else mcu.machine.start()
case _ =>
}
}
true
}
else false
}
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, entity: EntityLivingBase, stack: ItemStack) {
super.onBlockPlacedBy(world, x, y, z, entity, stack)
if (!world.isRemote) world.getTileEntity(x, y, z) match {
case mcu: tileentity.Microcontroller =>
mcu.info.load(stack)
case _ =>
}
}
override def removedByPlayer(world: World, player: EntityPlayer, x: Int, y: Int, z: Int, willHarvest: Boolean): Boolean = {
if (!world.isRemote) {
world.getTileEntity(x, y, z) match {
case mcu: tileentity.Microcontroller =>
mcu.saveComponents()
dropBlockAsItem(world, x, y, z, mcu.info.createItemStack())
case _ =>
}
}
super.removedByPlayer(world, player, x, y, z, willHarvest)
}
}

View File

@ -21,6 +21,7 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Keyboard], Settings.namespace + "keyboard") GameRegistry.registerTileEntity(classOf[tileentity.Keyboard], Settings.namespace + "keyboard")
GameRegistry.registerTileEntity(classOf[tileentity.Hologram], Settings.namespace + "hologram") GameRegistry.registerTileEntity(classOf[tileentity.Hologram], Settings.namespace + "hologram")
GameRegistry.registerTileEntity(classOf[tileentity.Geolyzer], Settings.namespace + "geolyzer") GameRegistry.registerTileEntity(classOf[tileentity.Geolyzer], Settings.namespace + "geolyzer")
GameRegistry.registerTileEntity(classOf[tileentity.Microcontroller], Settings.namespace + "microcontroller")
GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motion_sensor") GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motion_sensor")
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter") GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter")
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor") GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor")
@ -33,6 +34,7 @@ object Blocks {
// These are purely for converting existing blocks in delegator format to the new, // These are purely for converting existing blocks in delegator format to the new,
// one block type per block format. // one block type per block format.
// TODO Remove in 1.5
GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "simple") GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "simple")
GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "simple_redstone") GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "simple_redstone")
GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "special") GameRegistry.registerBlock(new DelegatorConverter(), classOf[DelegatorConverter.Item], "special")
@ -86,5 +88,6 @@ object Blocks {
// v1.4.2 // v1.4.2
Recipes.addBlock(new Raid(), "raid", "oc:raid") Recipes.addBlock(new Raid(), "raid", "oc:raid")
Items.registerBlock(new Microcontroller(), "microcontroller")
} }
} }

View File

@ -307,9 +307,9 @@ object Items extends ItemAPI {
if (Mods.AppliedEnergistics2.isAvailable) { if (Mods.AppliedEnergistics2.isAvailable) {
Recipes.addItem(new item.AppliedEnergisticsP2PTunnel(), "appengTunnel") Recipes.addItem(new item.AppliedEnergisticsP2PTunnel(), "appengTunnel")
} }
val eeprom = new item.EEPROM() val eeprom = new item.EEPROM()
Recipes.addItem(eeprom, "eeprom", "oc:eeprom") Recipes.addItem(eeprom, "eeprom", "oc:eeprom")
Recipes.addRecipe(createLuaBios(), "luaBios") Recipes.addRecipe(createLuaBios(), "luaBios")
Recipes.addMultiItem(new item.MicrocontrollerCase(multi), "microcontrollerCase", "oc:microcontrollerCase")
} }
} }

View File

@ -0,0 +1,3 @@
package li.cil.oc.common.item
class MicrocontrollerCase(val parent: Delegator) extends Delegate

View File

@ -7,6 +7,7 @@ import li.cil.oc.api
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.util.Color import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.SideTracker import li.cil.oc.util.SideTracker
import net.minecraft.init.Blocks import net.minecraft.init.Blocks
import net.minecraft.inventory.InventoryCrafting import net.minecraft.inventory.InventoryCrafting
@ -16,6 +17,8 @@ import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._ import scala.collection.convert.WrapAsScala._
object ExtendedRecipe { object ExtendedRecipe {
private lazy val eeprom = api.Items.get("eeprom")
private lazy val mcu = api.Items.get("microcontroller")
private lazy val navigationUpgrade = api.Items.get("navigationUpgrade") private lazy val navigationUpgrade = api.Items.get("navigationUpgrade")
private lazy val linkedCard = api.Items.get("linkedCard") private lazy val linkedCard = api.Items.get("linkedCard")
private lazy val floppy = api.Items.get("floppy") private lazy val floppy = api.Items.get("floppy")
@ -30,8 +33,8 @@ object ExtendedRecipe {
def addNBTToResult(craftedStack: ItemStack, inventory: InventoryCrafting): ItemStack = { def addNBTToResult(craftedStack: ItemStack, inventory: InventoryCrafting): ItemStack = {
if (api.Items.get(craftedStack) == navigationUpgrade) { if (api.Items.get(craftedStack) == navigationUpgrade) {
Option(api.Driver.driverFor(craftedStack)).foreach(driver => Option(api.Driver.driverFor(craftedStack)).foreach(driver =>
for (i <- 0 until inventory.getSizeInventory) { for (slot <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(i) val stack = inventory.getStackInSlot(slot)
if (stack != null && stack.getItem == net.minecraft.init.Items.filled_map) { if (stack != null && stack.getItem == net.minecraft.init.Items.filled_map) {
// Store information of the map used for crafting in the result. // Store information of the map used for crafting in the result.
val nbt = driver.dataTag(craftedStack) val nbt = driver.dataTag(craftedStack)
@ -55,8 +58,8 @@ object ExtendedRecipe {
craftedStack.setTagCompound(new NBTTagCompound()) craftedStack.setTagCompound(new NBTTagCompound())
} }
val nbt = craftedStack.getTagCompound val nbt = craftedStack.getTagCompound
for (i <- 0 until inventory.getSizeInventory) { for (slot <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(i) val stack = inventory.getStackInSlot(slot)
if (stack != null) { if (stack != null) {
if (api.Items.get(stack) == floppy && stack.hasTagCompound) { if (api.Items.get(stack) == floppy && stack.hasTagCompound) {
val oldData = stack.getTagCompound val oldData = stack.getTagCompound
@ -68,6 +71,29 @@ object ExtendedRecipe {
} }
} }
if (api.Items.get(craftedStack) == mcu) {
// Find old Microcontroller.
(0 until inventory.getSizeInventory).map(inventory.getStackInSlot).find(api.Items.get(_) == mcu) match {
case Some(oldMcu) =>
val data = new ItemUtils.MicrocontrollerData(oldMcu)
// Remove old EEPROM.
val oldRom = data.components.filter(api.Items.get(_) == eeprom)
data.components = data.components.diff(oldRom)
// Insert new EEPROM.
for (slot <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(slot)
if (api.Items.get(stack) == eeprom) {
data.components :+= stack
}
}
data.save(craftedStack)
case _ =>
}
}
craftedStack craftedStack
} }

View File

@ -132,6 +132,10 @@ object Recipes {
result.setTagCompound(tag) result.setTagCompound(tag)
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(result, floppy, dye)) GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(result, floppy, dye))
} }
// Microcontroller recrafting.
val mcu = api.Items.get("microcontroller").createItemStack(1)
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(mcu, mcu, api.Items.get("eeprom").createItemStack(1)))
} }
catch { catch {
case e: Throwable => OpenComputers.log.error("Error parsing recipes, you may not be able to craft any items from this mod!", e) case e: Throwable => OpenComputers.log.error("Error parsing recipes, you may not be able to craft any items from this mod!", e)

View File

@ -0,0 +1,67 @@
package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.template.TabletTemplate.hasComponent
import li.cil.oc.common.template.TabletTemplate.hasFileSystem
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagList
object MicrocontrollerTemplate extends Template {
override protected val suggestedComponents = Array(
"BIOS" -> hasComponent("eeprom") _)
override protected def hostClass = classOf[internal.Microcontroller]
def select(stack: ItemStack) = api.Items.get(stack) == api.Items.get("microcontrollerCase")
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.MicrocontrollerData()
data.components = items.drop(1).filter(_ != null).toArray
val stack = api.Items.get("microcontroller").createItemStack(1)
data.save(stack)
val energy = Settings.get.microcontrollerBaseCost + complexity(inventory) * Settings.get.microcontrollerComplexityCost
Array(stack, double2Double(energy))
}
def register() {
val nbt = new NBTTagCompound()
nbt.setString("name", "Microcontroller")
nbt.setString("select", "li.cil.oc.common.template.MicrocontrollerTemplate.select")
nbt.setString("validate", "li.cil.oc.common.template.MicrocontrollerTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.MicrocontrollerTemplate.assemble")
nbt.setString("hostClass", "li.cil.oc.api.internal.Microcontroller")
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Any))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.One))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.One))
componentSlots.appendTag(new NBTTagCompound())
componentSlots.appendTag(Map("type" -> Slot.CPU, "tier" -> Tier.One))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.One))
componentSlots.appendTag(new NBTTagCompound())
componentSlots.appendTag(Map("type" -> Slot.EEPROM, "tier" -> Tier.Any))
nbt.setTag("componentSlots", componentSlots)
FMLInterModComms.sendMessage("OpenComputers", "registerAssemblerTemplate", nbt)
}
override protected def maxComplexity(inventory: IInventory) = 4
override protected def caseTier(inventory: IInventory) = if (select(inventory.getStackInSlot(0))) Tier.One else Tier.None
}

View File

@ -93,7 +93,7 @@ abstract class Template {
acc += (Option(api.Driver.driverFor(stack, hostClass)) match { acc += (Option(api.Driver.driverFor(stack, hostClass)) match {
case Some(driver: Processor) => 0 // CPUs are exempt, since they control the limit. case Some(driver: Processor) => 0 // CPUs are exempt, since they control the limit.
case Some(driver: Container) => (1 + driver.tier(stack)) * 2 case Some(driver: Container) => (1 + driver.tier(stack)) * 2
case Some(driver) => 1 + driver.tier(stack) case Some(driver) if driver.slot(stack) != Slot.EEPROM => 1 + driver.tier(stack)
case _ => 0 case _ => 0
}) })
} }

View File

@ -95,9 +95,8 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
else if (api.Items.get(stack) == api.Items.get("server2")) enqueueServer(stack, 1) else if (api.Items.get(stack) == api.Items.get("server2")) enqueueServer(stack, 1)
else if (api.Items.get(stack) == api.Items.get("server3")) enqueueServer(stack, 2) else if (api.Items.get(stack) == api.Items.get("server3")) enqueueServer(stack, 2)
else if (api.Items.get(stack) == api.Items.get("tablet")) enqueueTablet(stack) else if (api.Items.get(stack) == api.Items.get("tablet")) enqueueTablet(stack)
else if (api.Items.get(stack) == api.Items.get("navigationUpgrade")) { else if (api.Items.get(stack) == api.Items.get("microcontroller")) enqueueMicrocontroller(stack)
enqueueNavigationUpgrade(stack) else if (api.Items.get(stack) == api.Items.get("navigationUpgrade")) enqueueNavigationUpgrade(stack)
}
else queue ++= getIngredients(stack) else queue ++= getIngredients(stack)
totalRequiredEnergy = queue.size * Settings.get.disassemblerItemCost totalRequiredEnergy = queue.size * Settings.get.disassemblerItemCost
} }
@ -136,6 +135,12 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
node.changeBuffer(info.energy) node.changeBuffer(info.energy)
} }
private def enqueueMicrocontroller(mcu: ItemStack) {
val info = new ItemUtils.MicrocontrollerData(mcu)
queue += api.Items.get("microcontrollerCase").createItemStack(1)
queue ++= info.components
}
private def enqueueNavigationUpgrade(stack: ItemStack) { private def enqueueNavigationUpgrade(stack: ItemStack) {
val info = new ItemUtils.NavigationUpgradeData(stack) val info = new ItemUtils.NavigationUpgradeData(stack)
val parts = getIngredients(stack) val parts = getIngredients(stack)
@ -243,7 +248,8 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override def getInventoryStackLimit = 64 override def getInventoryStackLimit = 64
override def isItemValidForSlot(i: Int, stack: ItemStack) = override def isItemValidForSlot(i: Int, stack: ItemStack) =
api.Items.get(stack) == api.Items.get("robot") || ((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && getIngredients(stack).nonEmpty) ||
api.Items.get(stack) == api.Items.get("robot") ||
api.Items.get(stack) == api.Items.get("tablet") || api.Items.get(stack) == api.Items.get("tablet") ||
((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && getIngredients(stack).nonEmpty) api.Items.get(stack) == api.Items.get("microcontroller")
} }

View File

@ -0,0 +1,176 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Driver
import li.cil.oc.api.driver.item.Memory
import li.cil.oc.api.driver.item.Processor
import li.cil.oc.api.internal
import li.cil.oc.api.machine.Architecture
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
class Microcontroller extends traits.PowerAcceptor with traits.Computer with internal.Microcontroller {
val info = new ItemUtils.MicrocontrollerData()
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("microcontroller").
withConnector().
create()
private val snooperNode = api.Network.newNode(this, Visibility.Network).create()
override protected def runSound = None // Microcontrollers are silent.
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
override protected def hasConnector(side: ForgeDirection) = side != facing
override protected def connector(side: ForgeDirection) = Option(if (side != facing && machine != null) machine.node.asInstanceOf[Connector] else null)
override protected def energyThroughput = Settings.get.caseRate(Tier.One)
override def getWorld = world
// ----------------------------------------------------------------------- //
override def cpuArchitecture: Class[_ <: Architecture] = info.components.map(stack => (stack, Driver.driverFor(stack, getClass))).collectFirst {
case (stack, driver: Processor) if driver.slot(stack) == Slot.CPU => driver.architecture(stack)
}.orNull
override def callBudget = info.components.foldLeft(0.0)((sum, item) => sum + (Option(item) match {
case Some(stack) => Option(Driver.driverFor(stack, getClass)) match {
case Some(driver: Processor) if driver.slot(stack) == Slot.CPU => Settings.get.callBudgets(driver.tier(stack))
case _ => 0
}
case _ => 0
}))
override def installedMemory = info.components.foldLeft(0)((sum, item) => sum + (Option(item) match {
case Some(stack) => Option(Driver.driverFor(stack, getClass)) match {
case Some(driver: Memory) => driver.amount(stack)
case _ => 0
}
case _ => 0
}))
override def componentSlot(address: String) = components.indexWhere(_.exists(env => env.node != null && env.node.address == address))
def maxComponents = 32
// ----------------------------------------------------------------------- //
@Callback(doc = """function():boolean -- Starts the microcontroller. Returns true if the state changed.""")
def start(context: Context, args: Arguments): Array[AnyRef] =
result(!machine.isPaused && machine.start())
@Callback(doc = """function():boolean -- Stops the microcontroller. Returns true if the state changed.""")
def stop(context: Context, args: Arguments): Array[AnyRef] =
result(machine.stop())
@Callback(direct = true, doc = """function():boolean -- Returns whether the microcontroller is running.""")
def isRunning(context: Context, args: Arguments): Array[AnyRef] =
result(machine.isRunning)
@Callback(direct = true, doc = """function():string -- Returns the reason the microcontroller crashed, if applicable.""")
def lastError(context: Context, args: Arguments): Array[AnyRef] =
result(machine.lastError)
// ----------------------------------------------------------------------- //
override def canUpdate = isServer
override def updateEntity() {
super.updateEntity()
// Pump energy into the internal network.
if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
machine.node match {
case connector: Connector =>
val demand = connector.globalBufferSize - connector.globalBuffer
val available = demand + node.changeBuffer(-demand)
connector.changeBuffer(available)
case _ =>
}
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
if (node == this.node) {
api.Network.joinNewNetwork(machine.node)
machine.node.connect(snooperNode)
machine.setCostPerTick(Settings.get.microcontrollerCost)
}
super.onConnect(node)
}
override def onMessage(message: Message) {
super.onMessage(message)
if (message.name == "network.message") {
if (message.source.network == snooperNode.network)
node.sendToReachable(message.name, message.data: _*)
else
snooperNode.sendToReachable(message.name, message.data: _*)
}
}
override protected def connectItemNode(node: Node) {
if (machine.node != null && node != null) {
machine.node.connect(node)
}
}
override def readFromNBT(nbt: NBTTagCompound) {
// Load info before inventory and such, to avoid initializing components
// to empty inventory.
info.load(nbt.getCompoundTag(Settings.namespace + "info"))
super.readFromNBT(nbt)
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
nbt.setNewCompoundTag(Settings.namespace + "info", info.save)
}
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT) override
def readFromNBTForClient(nbt: NBTTagCompound) {
info.load(nbt.getCompoundTag("info"))
super.readFromNBTForClient(nbt)
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
super.writeToNBTForClient(nbt)
nbt.setNewCompoundTag("info", info.save)
}
override lazy val items = info.components.map(Option(_))
override def getSizeInventory = info.components.length
override def isItemValidForSlot(slot: Int, stack: ItemStack) = false
// Nope.
override def setInventorySlotContents(slot: Int, stack: ItemStack) {}
// Nope.
override def decrStackSize(slot: Int, amount: Int) = null
}

View File

@ -41,6 +41,8 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
private val _users = mutable.Set.empty[String] private val _users = mutable.Set.empty[String]
protected def runSound = Option("computer_running")
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def canInteract(player: String) = def canInteract(player: String) =
@ -53,8 +55,10 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
def setRunning(value: Boolean): Unit = if (value != _isRunning) { def setRunning(value: Boolean): Unit = if (value != _isRunning) {
_isRunning = value _isRunning = value
world.markBlockForUpdate(x, y, z) world.markBlockForUpdate(x, y, z)
if (_isRunning) Sound.startLoop(this, "computer_running", 0.5f, 50 + world.rand.nextInt(50)) runSound.foreach(sound =>
else Sound.stopLoop(this) if (_isRunning) Sound.startLoop(this, sound, 0.5f, 50 + world.rand.nextInt(50))
else Sound.stopLoop(this)
)
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ -158,7 +162,7 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
_isRunning = nbt.getBoolean("isRunning") _isRunning = nbt.getBoolean("isRunning")
_users.clear() _users.clear()
_users ++= nbt.getTagList("users", NBT.TAG_STRING).map((tag: NBTTagString) => tag.func_150285_a_()) _users ++= nbt.getTagList("users", NBT.TAG_STRING).map((tag: NBTTagString) => tag.func_150285_a_())
if (_isRunning) Sound.startLoop(this, "computer_running", 0.5f, 1000 + world.rand.nextInt(2000)) if (_isRunning) runSound.foreach(sound => Sound.startLoop(this, sound, 0.5f, 1000 + world.rand.nextInt(2000)))
} }
override def writeToNBTForClient(nbt: NBTTagCompound) { override def writeToNBTForClient(nbt: NBTTagCompound) {

View File

@ -1,11 +1,15 @@
package li.cil.oc.integration.opencomputers package li.cil.oc.integration.opencomputers
import li.cil.oc.{OpenComputers, Settings, api} import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.Processor import li.cil.oc.api.driver.item.Processor
import li.cil.oc.api.machine.Architecture import li.cil.oc.api.machine.Architecture
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import scala.collection.convert.WrapAsScala._ import scala.collection.convert.WrapAsScala._

View File

@ -1,10 +1,13 @@
package li.cil.oc.integration.opencomputers package li.cil.oc.integration.opencomputers
import li.cil.oc.{Settings, api} import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.Processor import li.cil.oc.api.driver.item.Processor
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverComponentBus extends Item with Processor { object DriverComponentBus extends Item with Processor {

View File

@ -3,8 +3,10 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.Container import li.cil.oc.api.driver.item.Container
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverContainerCard extends Item with Container { object DriverContainerCard extends Item with Container {

View File

@ -3,8 +3,10 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.Container import li.cil.oc.api.driver.item.Container
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverContainerUpgrade extends Item with Container { object DriverContainerUpgrade extends Item with Container {

View File

@ -14,7 +14,7 @@ object DriverEEPROM extends Item with HostAware with EnvironmentAware {
isOneOf(stack, api.Items.get("eeprom")) isOneOf(stack, api.Items.get("eeprom"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host) || isTablet(host)) worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host) || isTablet(host) || isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.EEPROM() override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.EEPROM()

View File

@ -1,16 +1,23 @@
package li.cil.oc.integration.opencomputers package li.cil.oc.integration.opencomputers
import li.cil.oc.api.driver.{EnvironmentAware, EnvironmentHost} import li.cil.oc.api
import li.cil.oc.{api, common} import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier}
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverGraphicsCard extends Item with EnvironmentAware { object DriverGraphicsCard extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) = override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("graphicsCard1"), api.Items.get("graphicsCard2"), api.Items.get("graphicsCard3")) isOneOf(stack, api.Items.get("graphicsCard1"), api.Items.get("graphicsCard2"), api.Items.get("graphicsCard3"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
tier(stack) match { tier(stack) match {
case Tier.One => new component.GraphicsCard.Tier1() case Tier.One => new component.GraphicsCard.Tier1()

View File

@ -12,7 +12,7 @@ object DriverKeyboard extends Item with HostAware {
isOneOf(stack, api.Items.get("keyboard")) isOneOf(stack, api.Items.get("keyboard"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isAdapter(host) worksWith(stack) && !isAdapter(host) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.Keyboard(host) override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.Keyboard(host)

View File

@ -20,7 +20,7 @@ object DriverRedstoneCard extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("redstoneCard1"), api.Items.get("redstoneCard2")) override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("redstoneCard1"), api.Items.get("redstoneCard2"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host)) worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host) || isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match { host match {

View File

@ -14,7 +14,7 @@ object DriverScreen extends Item with HostAware with EnvironmentAware {
isOneOf(stack, api.Items.get("screen1")) isOneOf(stack, api.Items.get("screen1"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isTablet(host) && !isAdapter(host) worksWith(stack) && !isTablet(host) && !isAdapter(host) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match { override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case screen: tileentity.Screen if screen.tier > 0 => new component.Screen(screen) case screen: tileentity.Screen if screen.tier > 0 => new component.Screen(screen)

View File

@ -3,8 +3,10 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack

View File

@ -3,17 +3,24 @@ package li.cil.oc.integration.opencomputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.driver import li.cil.oc.api.driver
import li.cil.oc.api.driver.EnvironmentAware import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.inventory.DatabaseInventory import li.cil.oc.common.inventory.DatabaseInventory
import li.cil.oc.common.{Slot, Tier, item} import li.cil.oc.common.item
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverUpgradeDatabase extends Item with EnvironmentAware { object DriverUpgradeDatabase extends Item with HostAware with EnvironmentAware {
override def worksWith(stack: ItemStack) = override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("databaseUpgrade1"), api.Items.get("databaseUpgrade2"), api.Items.get("databaseUpgrade3")) isOneOf(stack, api.Items.get("databaseUpgrade1"), api.Items.get("databaseUpgrade2"), api.Items.get("databaseUpgrade3"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && !isMicrocontroller(host)
override def createEnvironment(stack: ItemStack, host: driver.EnvironmentHost) = override def createEnvironment(stack: ItemStack, host: driver.EnvironmentHost) =
new component.UpgradeDatabase(new DatabaseInventory { new component.UpgradeDatabase(new DatabaseInventory {
override def tier = DriverUpgradeDatabase.tier(stack) override def tier = DriverUpgradeDatabase.tier(stack)

View File

@ -15,7 +15,7 @@ object DriverUpgradeNavigation extends Item with HostAware with EnvironmentAware
isOneOf(stack, api.Items.get("navigationUpgrade")) isOneOf(stack, api.Items.get("navigationUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRotatable(host) worksWith(stack) && (isRotatable(host) && !isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match { host match {

View File

@ -1,12 +1,15 @@
package li.cil.oc.integration.opencomputers package li.cil.oc.integration.opencomputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.driver.{EnvironmentAware, EnvironmentHost} import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.api.internal.{Adapter, Rotatable} import li.cil.oc.api.internal.Adapter
import li.cil.oc.api.internal.Rotatable
import li.cil.oc.common.Slot import li.cil.oc.common.Slot
import li.cil.oc.server.component import li.cil.oc.server.component
import li.cil.oc.server.component.{UpgradeSignInAdapter, UpgradeSignInRotatable} import li.cil.oc.server.component.UpgradeSignInAdapter
import li.cil.oc.server.component.UpgradeSignInRotatable
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object DriverUpgradeSign extends Item with HostAware with EnvironmentAware { object DriverUpgradeSign extends Item with HostAware with EnvironmentAware {
@ -14,7 +17,7 @@ object DriverUpgradeSign extends Item with HostAware with EnvironmentAware {
isOneOf(stack, api.Items.get("signUpgrade")) isOneOf(stack, api.Items.get("signUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isRotatable(host) || isAdapter(host)) worksWith(stack) && (isAdapter(host) || isRotatable(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = override def createEnvironment(stack: ItemStack, host: EnvironmentHost) =
host match { host match {

View File

@ -19,5 +19,5 @@ object DriverUpgradeSolarGenerator extends Item with HostAware {
override def slot(stack: ItemStack) = Slot.Upgrade override def slot(stack: ItemStack) = Slot.Upgrade
override def tier(stack: ItemStack) = Tier.Three override def tier(stack: ItemStack) = Tier.Two
} }

View File

@ -27,6 +27,8 @@ trait Item extends driver.Item {
protected def isServer(host: Class[_ <: EnvironmentHost]) = classOf[internal.Server].isAssignableFrom(host) protected def isServer(host: Class[_ <: EnvironmentHost]) = classOf[internal.Server].isAssignableFrom(host)
protected def isTablet(host: Class[_ <: EnvironmentHost]) = classOf[internal.Tablet].isAssignableFrom(host) protected def isTablet(host: Class[_ <: EnvironmentHost]) = classOf[internal.Tablet].isAssignableFrom(host)
protected def isMicrocontroller(host: Class[_ <: EnvironmentHost]) = classOf[internal.Microcontroller].isAssignableFrom(host)
} }
object Item { object Item {

View File

@ -10,6 +10,7 @@ import li.cil.oc.common.asm.SimpleComponentTickHandler
import li.cil.oc.common.event._ import li.cil.oc.common.event._
import li.cil.oc.common.item.Tablet import li.cil.oc.common.item.Tablet
import li.cil.oc.common.recipe.Recipes import li.cil.oc.common.recipe.Recipes
import li.cil.oc.common.template.MicrocontrollerTemplate
import li.cil.oc.common.template.RobotTemplate import li.cil.oc.common.template.RobotTemplate
import li.cil.oc.common.template.TabletTemplate import li.cil.oc.common.template.TabletTemplate
import li.cil.oc.integration.ModProxy import li.cil.oc.integration.ModProxy
@ -22,6 +23,7 @@ object ModOpenComputers extends ModProxy {
override def getMod = Mods.OpenComputers override def getMod = Mods.OpenComputers
override def initialize() { override def initialize() {
MicrocontrollerTemplate.register()
RobotTemplate.register() RobotTemplate.register()
TabletTemplate.register() TabletTemplate.register()

View File

@ -16,7 +16,7 @@ object DriverAbstractBusCard extends Item with HostAware with EnvironmentAware {
isOneOf(stack, api.Items.get("abstractBusCard")) isOneOf(stack, api.Items.get("abstractBusCard"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) = override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host)) worksWith(stack) && (isComputer(host) || isRobot(host) || isServer(host) || isMicrocontroller(host))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = if (Mods.StargateTech2.isAvailable) host match { override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = if (Mods.StargateTech2.isAvailable) host match {
case device: IBusDevice => new component.AbstractBusCard(device) case device: IBusDevice => new component.AbstractBusCard(device)

View File

@ -26,6 +26,9 @@ class EEPROM extends prefab.ManagedEnvironment {
@Callback(doc = """function(data:string) -- Overwrite the currently stored byte array.""") @Callback(doc = """function(data:string) -- Overwrite the currently stored byte array.""")
def set(context: Context, args: Arguments): Array[AnyRef] = { def set(context: Context, args: Arguments): Array[AnyRef] = {
if (!node.tryChangeBuffer(-Settings.get.eepromWriteCost)) {
return result(Unit, "not enough energy")
}
val newData = args.checkByteArray(0) val newData = args.checkByteArray(0)
if (newData.length > 4 * 1024) throw new IllegalArgumentException("not enough space") if (newData.length > 4 * 1024) throw new IllegalArgumentException("not enough space")
data = newData data = newData

View File

@ -13,6 +13,7 @@ import li.cil.oc.common.tileentity.traits.RedstoneAware
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util import li.cil.oc.integration.util
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
@Optional.InterfaceList(Array( @Optional.InterfaceList(Array(
new Optional.Interface(iface = "codechicken.wirelessredstone.core.WirelessReceivingDevice", modid = Mods.IDs.WirelessRedstoneCBE), new Optional.Interface(iface = "codechicken.wirelessredstone.core.WirelessReceivingDevice", modid = Mods.IDs.WirelessRedstoneCBE),
@ -74,7 +75,7 @@ trait RedstoneWireless extends Redstone[RedstoneAware] with WirelessReceivingDev
override def updateDevice(frequency: Int, on: Boolean) { override def updateDevice(frequency: Int, on: Boolean) {
if (frequency == wirelessFrequency && on != wirelessInput) { if (frequency == wirelessFrequency && on != wirelessInput) {
wirelessInput = on wirelessInput = on
// TODO signal to computer node.sendToReachable("computer.signal", "redstone_changed", "wireless")
} }
} }

View File

@ -24,7 +24,7 @@ class UpgradePiston(val host: Rotatable with EnvironmentHost) extends prefab.Man
private lazy val tryExtend = ReflectionHelper.findMethod(classOf[BlockPistonBase], null, Array("tryExtend", "func_150079_i", "i"), classOf[World], classOf[Int], classOf[Int], classOf[Int], classOf[Int]) private lazy val tryExtend = ReflectionHelper.findMethod(classOf[BlockPistonBase], null, Array("tryExtend", "func_150079_i", "i"), classOf[World], classOf[Int], classOf[Int], classOf[Int], classOf[Int])
@Callback(doc = """function(side:number):boolean -- Tries to push the block in front of the container of the upgrade.""") @Callback(doc = """function():boolean -- Tries to push the block in front of the container of the upgrade.""")
def push(context: Context, args: Arguments): Array[AnyRef] = { def push(context: Context, args: Arguments): Array[AnyRef] = {
val hostPos = BlockPosition(host) val hostPos = BlockPosition(host)
val blockPos = hostPos.offset(host.facing) val blockPos = hostPos.offset(host.facing)

View File

@ -10,7 +10,6 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.block.DelegatorConverter import li.cil.oc.common.block.DelegatorConverter
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.integration.opencomputers.DriverScreen import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.integration.opencomputers.DriverUpgradeExperience
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemMap import net.minecraft.item.ItemMap
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
@ -49,6 +48,85 @@ object ItemUtils {
} }
} }
class MicrocontrollerData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var components = Array.empty[ItemStack]
override def load(nbt: NBTTagCompound) {
components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(loadStack)
}
override def save(nbt: NBTTagCompound) {
nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
}
def createItemStack() = {
val stack = api.Items.get("microcontroller").createItemStack(1)
save(stack)
stack
}
def copyItemStack() = {
val stack = createItemStack()
// Forget all node addresses and so on. This is used when 'picking' a
// microcontroller in creative mode.
val newInfo = new MicrocontrollerData(stack)
newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
case Some(driver) if driver == DriverScreen =>
val nbt = driver.dataTag(cs)
for (tagName <- nbt.func_150296_c().toArray) {
nbt.removeTag(tagName.asInstanceOf[String])
}
case _ =>
})
newInfo.save(stack)
stack
}
}
class NavigationUpgradeData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var map = new ItemStack(net.minecraft.init.Items.filled_map)
def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
case _: Throwable => throw new Exception("invalid map")
}
override def load(stack: ItemStack) {
if (stack.hasTagCompound) {
load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data"))
}
}
override def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getCompoundTag(Settings.namespace + "data"))
}
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey(Settings.namespace + "map")) {
map = loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
}
}
override def save(nbt: NBTTagCompound) {
if (map != null) {
nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT)
}
}
}
class RobotData extends ItemData { class RobotData extends ItemData {
def this(stack: ItemStack) { def this(stack: ItemStack) {
this() this()
@ -151,44 +229,6 @@ object ItemUtils {
def randomName = if (names.length > 0) names((math.random * names.length).toInt) else "Robot" def randomName = if (names.length > 0) names((math.random * names.length).toInt) else "Robot"
} }
class NavigationUpgradeData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var map = new ItemStack(net.minecraft.init.Items.filled_map)
def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
case _: Throwable => throw new Exception("invalid map")
}
override def load(stack: ItemStack) {
if (stack.hasTagCompound) {
load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data"))
}
}
override def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getCompoundTag(Settings.namespace + "data"))
}
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey(Settings.namespace + "map")) {
map = loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
}
}
override def save(nbt: NBTTagCompound) {
if (map != null) {
nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT)
}
}
}
class TabletData extends ItemData { class TabletData extends ItemData {
def this(stack: ItemStack) { def this(stack: ItemStack) {
this() this()