diff --git a/src/main/java/li/cil/oc/api/API.java b/src/main/java/li/cil/oc/api/API.java
index 5e277005b..3497915e9 100644
--- a/src/main/java/li/cil/oc/api/API.java
+++ b/src/main/java/li/cil/oc/api/API.java
@@ -12,7 +12,7 @@ import li.cil.oc.api.detail.*;
*/
public class API {
public static final String ID_OWNER = "OpenComputers|Core";
- public static final String VERSION = "5.4.0";
+ public static final String VERSION = "5.5.0";
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;
diff --git a/src/main/java/li/cil/oc/api/Items.java b/src/main/java/li/cil/oc/api/Items.java
index a10182d6c..7a0d5657e 100644
--- a/src/main/java/li/cil/oc/api/Items.java
+++ b/src/main/java/li/cil/oc/api/Items.java
@@ -3,6 +3,8 @@ package li.cil.oc.api;
import li.cil.oc.api.detail.ItemInfo;
import net.minecraft.item.ItemStack;
+import java.util.concurrent.Callable;
+
/**
* Access to item definitions for all blocks and items provided by
* OpenComputers.
@@ -44,6 +46,54 @@ public final class Items {
return null;
}
+ /**
+ * Register a single loot floppy disk.
+ *
+ * The disk will be listed in the creative tab of OpenComputers.
+ *
+ * The specified factory callable will be used to generate a new file
+ * system when the loot disk is used as a component. The specified name
+ * will be used as the label for the loot disk, as well as the identifier
+ * to select the corresponding factory method, so choose wisely.
+ *
+ * To use some directory in your mod JAR as the directory provided by the
+ * loot disk, use {@link FileSystem#fromClass} in your callable.
+ *
+ * @param name the label and identifier to use for the loot disk.
+ * @param color the color of the disk, as a Minecraft color (so 0-15,
+ * with 0 being black, 1 red and so on).
+ * @param factory the callable to call for creating file system instances.
+ * @return an item stack representing the registered loot disk, to allow
+ * adding a recipe for your loot disk, for example.
+ */
+ public static ItemStack registerFloppy(String name, int color, Callable factory) {
+ if (API.items != null)
+ return API.items.registerFloppy(name, color, factory);
+ return null;
+ }
+
+ /**
+ * Register a single custom EEPROM.
+ *
+ * The EEPROM will be listed in the creative tab of OpenComputers.
+ *
+ * The EEPROM will be initialized with the specified code and data byte
+ * arrays. For script code (e.g. a Lua script) use String.getBytes("UTF-8").
+ * You can omit any of the arguments by passing null.
+ *
+ * @param name the label of the EEPROM.
+ * @param code the code section of the EEPROM.
+ * @param data the data section of the EEPROM.
+ * @param readonly whether the code section is read-only.
+ * @return an item stack representing the registered EEPROM, to allow
+ * adding a recipe for your custom BIOS, for example.
+ */
+ public static ItemStack registerEEPROM(String name, byte[] code, byte[] data, boolean readonly) {
+ if (API.items != null)
+ return API.items.registerEEPROM(name, code, data, readonly);
+ return null;
+ }
+
// ----------------------------------------------------------------------- //
private Items() {
diff --git a/src/main/java/li/cil/oc/api/detail/ItemAPI.java b/src/main/java/li/cil/oc/api/detail/ItemAPI.java
index 8ae9f334d..0de2b2f3d 100644
--- a/src/main/java/li/cil/oc/api/detail/ItemAPI.java
+++ b/src/main/java/li/cil/oc/api/detail/ItemAPI.java
@@ -1,7 +1,10 @@
package li.cil.oc.api.detail;
+import li.cil.oc.api.FileSystem;
import net.minecraft.item.ItemStack;
+import java.util.concurrent.Callable;
+
public interface ItemAPI {
/**
* Get a descriptor object for the block or item with the specified name.
@@ -26,4 +29,48 @@ public interface ItemAPI {
* if the stack is not a valid OpenComputers item or block.
*/
ItemInfo get(ItemStack stack);
+
+ /**
+ * Register a single loot floppy disk.
+ *
+ * The disk will be listed in the creative tab of OpenComputers.
+ *
+ * The specified factory callable will be used to generate a new file
+ * system when the loot disk is used as a component. The specified name
+ * will be used as the label for the loot disk, as well as the identifier
+ * to select the corresponding factory method, so choose wisely.
+ *
+ * To use some directory in your mod JAR as the directory provided by the
+ * loot disk, use {@link FileSystem#fromClass} in your callable.
+ *
+ * Call this in the init phase or later, not in pre-init.
+ *
+ * @param name the label and identifier to use for the loot disk.
+ * @param color the color of the disk, as a Minecraft color (so 0-15,
+ * with 0 being black, 1 red and so on).
+ * @param factory the callable to call for creating file system instances.
+ * @return an item stack representing the registered loot disk, to allow
+ * adding a recipe for your loot disk, for example.
+ */
+ ItemStack registerFloppy(String name, int color, Callable factory);
+
+ /**
+ * Register a single custom EEPROM.
+ *
+ * The EEPROM will be listed in the creative tab of OpenComputers.
+ *
+ * The EEPROM will be initialized with the specified code and data byte
+ * arrays. For script code (e.g. a Lua script) use String.getBytes("UTF-8").
+ * You can omit any of the arguments by passing null.
+ *
+ * Call this in the init phase or later, not in pre-init.
+ *
+ * @param name the label of the EEPROM.
+ * @param code the code section of the EEPROM.
+ * @param data the data section of the EEPROM.
+ * @param readonly whether the code section is read-only.
+ * @return an item stack representing the registered EEPROM, to allow
+ * adding a recipe for your custom BIOS, for example.
+ */
+ ItemStack registerEEPROM(String name, byte[] code, byte[] data, boolean readonly);
}
diff --git a/src/main/resources/assets/opencomputers/loot/loot.properties b/src/main/resources/assets/opencomputers/loot/loot.properties
index 95e955686..b7f6a3b68 100644
--- a/src/main/resources/assets/opencomputers/loot/loot.properties
+++ b/src/main/resources/assets/opencomputers/loot/loot.properties
@@ -10,7 +10,7 @@ MazeGen=maze:1:dyeOrange
Network=network:1:dyeLime
OpenIRC=irc:1:dyeLightBlue
OpenLoader=openloader:1:dyeMagenta
-OpenOS=openos:0:dyeGreen
+OpenOS=openOS:0:dyeGreen
OPPM=oppm:0:dyeCyan
# Higher chance to find the dig program, because it has the most immediate
# use - OpenOS is craftable and IRC can be downloaded once an internet card
diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes
index b5399f3e0..9166abbe5 100644
--- a/src/main/resources/assets/opencomputers/recipes/default.recipes
+++ b/src/main/resources/assets/opencomputers/recipes/default.recipes
@@ -364,7 +364,6 @@ chameliumBlock {
["oc:chamelium", "oc:chamelium", "oc:chamelium"],
["oc:chamelium", "oc:chamelium", "oc:chamelium"]]
}
-
endstone {
input: [[enderPearl, "oc:chameliumBlock", enderPearl]
["oc:chameliumBlock", enderPearl, "oc:chameliumBlock"]
diff --git a/src/main/scala/li/cil/oc/Constants.scala b/src/main/scala/li/cil/oc/Constants.scala
index cb00dea32..0eaa9d9ff 100644
--- a/src/main/scala/li/cil/oc/Constants.scala
+++ b/src/main/scala/li/cil/oc/Constants.scala
@@ -113,6 +113,7 @@ object Constants {
final val NavigationUpgrade = "navigationUpgrade"
final val NetworkCard = "lanCard"
final val NumPad = "numPad"
+ final val OpenOS = "openOS"
final val PistonUpgrade = "pistonUpgrade"
final val Present = "present"
final val PrintedCircuitBoard = "printedCircuitBoard"
diff --git a/src/main/scala/li/cil/oc/common/Achievement.scala b/src/main/scala/li/cil/oc/common/Achievement.scala
index 1fd7c6a93..d4fe9c3c7 100644
--- a/src/main/scala/li/cil/oc/common/Achievement.scala
+++ b/src/main/scala/li/cil/oc/common/Achievement.scala
@@ -163,7 +163,7 @@ object Achievement {
val OpenOS = newAchievement("openOS").
at(10, 9).
withParent(Floppy).
- whenCrafting(Items.createOpenOS()).
+ whenCrafting(Constants.ItemName.OpenOS).
add()
val Raid = newAchievement("raid").
at(8, 10).
diff --git a/src/main/scala/li/cil/oc/common/Loot.scala b/src/main/scala/li/cil/oc/common/Loot.scala
index 641769c5d..0a3c3a049 100644
--- a/src/main/scala/li/cil/oc/common/Loot.scala
+++ b/src/main/scala/li/cil/oc/common/Loot.scala
@@ -2,11 +2,15 @@ package li.cil.oc.common
import java.io
import java.util.Random
+import java.util.concurrent.Callable
+import cpw.mods.fml.common.Loader
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.api.fs.FileSystem
import li.cil.oc.common.init.Items
import li.cil.oc.util.Color
import net.minecraft.inventory.IInventory
@@ -28,11 +32,38 @@ object Loot extends WeightedRandomChestContent(new ItemStack(null: Item), 1, 1,
ChestGenHooks.PYRAMID_JUNGLE_CHEST,
ChestGenHooks.STRONGHOLD_LIBRARY)
- val builtInDisks = mutable.Map.empty[String, (ItemStack, Int)]
+ val factories = mutable.Map.empty[String, Callable[FileSystem]]
+
+ val globalDisks = mutable.Map.empty[String, (ItemStack, Int)]
val worldDisks = mutable.Map.empty[String, (ItemStack, Int)]
- val disks = mutable.ArrayBuffer.empty[ItemStack]
+ val disksForSampling = mutable.ArrayBuffer.empty[ItemStack]
+
+ def registerLootDisk(name: String, color: Int, factory: Callable[FileSystem]): ItemStack = {
+ val mod = Loader.instance.activeModContainer.getModId
+
+ OpenComputers.log.info(s"Registering loot disk '$name' from mod $mod.")
+
+ val modSpecificName = mod + ":" + name
+
+ val data = new NBTTagCompound()
+ data.setString(Settings.namespace + "fs.label", name)
+
+ val nbt = new NBTTagCompound()
+ nbt.setTag(Settings.namespace + "data", data)
+
+ // Store this top level, so it won't get wiped on save.
+ nbt.setString(Settings.namespace + "lootFactory", modSpecificName)
+ nbt.setInteger(Settings.namespace + "color", color max 0 min 15)
+
+ val stack = Items.get(Constants.ItemName.Floppy).createItemStack(1)
+ stack.setTagCompound(nbt)
+
+ Loot.factories += modSpecificName -> factory
+
+ stack.copy()
+ }
def init() {
for (container <- containers) {
@@ -43,13 +74,13 @@ object Loot extends WeightedRandomChestContent(new ItemStack(null: Item), 1, 1,
val listStream = getClass.getResourceAsStream("/assets/" + Settings.resourceDomain + "/loot/loot.properties")
list.load(listStream)
listStream.close()
- parseLootDisks(list, builtInDisks)
+ parseLootDisks(list, globalDisks, external = false)
}
@SubscribeEvent
- def initForWorld(e: WorldEvent.Load) {
+ def initForWorld(e: WorldEvent.Load): Unit = {
worldDisks.clear()
- disks.clear()
+ disksForSampling.clear()
val path = new io.File(DimensionManager.getCurrentSaveRootDirectory, Settings.savePath + "loot/")
if (path.exists && path.isDirectory) {
val listFile = new io.File(path, "loot.properties")
@@ -59,33 +90,33 @@ object Loot extends WeightedRandomChestContent(new ItemStack(null: Item), 1, 1,
val list = new java.util.Properties()
list.load(listStream)
listStream.close()
- parseLootDisks(list, worldDisks)
+ parseLootDisks(list, worldDisks, external = true)
}
catch {
case t: Throwable => OpenComputers.log.warn("Failed opening loot descriptor file in saves folder.")
}
}
}
- for ((name, entry) <- builtInDisks if !worldDisks.contains(name)) {
+ for ((name, entry) <- globalDisks if !worldDisks.contains(name)) {
worldDisks += name -> entry
}
for ((_, (stack, count)) <- worldDisks) {
for (i <- 0 until count) {
- disks += stack
+ disksForSampling += stack
}
}
}
- private def parseLootDisks(list: java.util.Properties, acc: mutable.Map[String, (ItemStack, Int)]) {
+ private def parseLootDisks(list: java.util.Properties, acc: mutable.Map[String, (ItemStack, Int)], external: Boolean) {
for (key <- list.stringPropertyNames) {
val value = list.getProperty(key)
try value.split(":") match {
case Array(name, count, color) =>
- acc += key -> ((createLootDisk(name, key, Some(color)), count.toInt))
+ acc += key -> ((createLootDisk(name, key, external, Some(Color.dyes.indexOf(color))), count.toInt))
case Array(name, count) =>
- acc += key -> ((createLootDisk(name, key), count.toInt))
+ acc += key -> ((createLootDisk(name, key, external), count.toInt))
case _ =>
- acc += key -> ((createLootDisk(value, key), 1))
+ acc += key -> ((createLootDisk(value, key, external), 1))
}
catch {
case t: Throwable => OpenComputers.log.warn("Bad loot descriptor: " + value, t)
@@ -93,29 +124,22 @@ object Loot extends WeightedRandomChestContent(new ItemStack(null: Item), 1, 1,
}
}
- def createLootDisk(name: String, path: String, color: Option[String] = None) = {
- val data = new NBTTagCompound()
- data.setString(Settings.namespace + "fs.label", name)
-
- val tag = new NBTTagCompound()
- tag.setTag(Settings.namespace + "data", data)
- // Store this top level, so it won't get wiped on save.
- tag.setString(Settings.namespace + "lootPath", path)
- color match {
- case Some(oreDictName) =>
- tag.setInteger(Settings.namespace + "color", Color.dyes.indexOf(oreDictName))
- case _ =>
+ def createLootDisk(name: String, path: String, external: Boolean, color: Option[Int] = None) = {
+ val callable = if (external) new Callable[FileSystem] {
+ override def call(): FileSystem = api.FileSystem.fromSaveDirectory("loot/" + path, 0, false)
+ } else new Callable[FileSystem] {
+ override def call(): FileSystem = api.FileSystem.fromClass(OpenComputers.getClass, Settings.resourceDomain, "loot/" + path)
}
-
- val disk = Items.get(Constants.ItemName.LootDisk).createItemStack(1)
- disk.setTagCompound(tag)
-
- disk
+ val stack = registerLootDisk(name, color.getOrElse(8), callable)
+ if (!external) {
+ Items.registerStack(stack, name)
+ }
+ stack
}
override def generateChestContent(random: Random, newInventory: IInventory) =
- if (disks.length > 0)
- ChestGenHooks.generateStacks(random, disks(random.nextInt(disks.length)),
+ if (disksForSampling.length > 0)
+ ChestGenHooks.generateStacks(random, disksForSampling(random.nextInt(disksForSampling.length)),
theMinimumChanceToGenerateItem, theMaximumChanceToGenerateItem)
else Array.empty[ItemStack]
}
diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala
index 4b30ae26d..9f346874d 100644
--- a/src/main/scala/li/cil/oc/common/init/Items.scala
+++ b/src/main/scala/li/cil/oc/common/init/Items.scala
@@ -1,11 +1,14 @@
package li.cil.oc.common.init
+import java.util.concurrent.Callable
+
import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.detail.ItemAPI
import li.cil.oc.api.detail.ItemInfo
+import li.cil.oc.api.fs.FileSystem
import li.cil.oc.common
import li.cil.oc.common.Loot
import li.cil.oc.common.Tier
@@ -103,6 +106,24 @@ object Items extends ItemAPI {
instance
}
+ def registerStack(stack: ItemStack, id: String) = {
+ val immutableStack = stack.copy()
+ descriptors += id -> new ItemInfo {
+ override def name = id
+
+ override def block = null
+
+ override def createItemStack(size: Int): ItemStack = {
+ val copy = immutableStack.copy()
+ copy.stackSize = size
+ copy
+ }
+
+ override def item = immutableStack.getItem
+ }
+ stack
+ }
+
private def getBlockOrItem(stack: ItemStack): Any =
if (stack == null) null
else Delegator.subItem(stack).getOrElse(stack.getItem match {
@@ -112,24 +133,60 @@ object Items extends ItemAPI {
// ----------------------------------------------------------------------- //
- def createOpenOS(amount: Int = 1) = {
- Loot.builtInDisks.get("OpenOS").map(_._1.copy()).orNull
+ val registeredItems = mutable.ArrayBuffer.empty[ItemStack]
+
+ override def registerFloppy(name: String, color: Int, factory: Callable[FileSystem]): ItemStack = {
+ val stack = Loot.registerLootDisk(name, color, factory)
+
+ registeredItems += stack
+
+ stack.copy()
}
- def createLuaBios(amount: Int = 1) = {
- val data = new NBTTagCompound()
- val code = new Array[Byte](4 * 1024)
- val count = OpenComputers.getClass.getResourceAsStream(Settings.scriptPath + "bios.lua").read(code)
- data.setByteArray(Settings.namespace + "eeprom", code.take(count))
- data.setString(Settings.namespace + "label", "EEPROM (Lua BIOS)")
-
+ override def registerEEPROM(name: String, code: Array[Byte], data: Array[Byte], readonly: Boolean): ItemStack = {
val nbt = new NBTTagCompound()
- nbt.setTag(Settings.namespace + "data", data)
+ if (name != null) {
+ nbt.setString(Settings.namespace + "label", name.trim.take(16))
+ }
+ if (code != null) {
+ nbt.setByteArray(Settings.namespace + "eeprom", code.take(Settings.get.eepromSize))
+ }
+ if (data != null) {
+ nbt.setByteArray(Settings.namespace + "userdata", data.take(Settings.get.eepromDataSize))
+ }
+ nbt.setBoolean(Settings.namespace + "readonly", readonly)
- val stack = get(Constants.ItemName.EEPROM).createItemStack(amount)
- stack.setTagCompound(nbt)
+ val stackNbt = new NBTTagCompound()
+ stackNbt.setTag(Settings.namespace + "data", nbt)
- stack
+ val stack = get(Constants.ItemName.EEPROM).createItemStack(1)
+ stack.setTagCompound(stackNbt)
+
+ registeredItems += stack
+
+ stack.copy()
+ }
+
+ // ----------------------------------------------------------------------- //
+
+ // Nobody should use this anyway, since it's internal, but IIRC some people do, so let's be nice...
+ // TODO remove in OC 1.6
+ /**
+ * @deprecated use api.Items.get("openOS").createItemStack(amount) instead.
+ */
+ @Deprecated
+ def createOpenOS(amount: Int = 1) = {
+ get(Constants.ItemName.OpenOS).createItemStack(amount)
+ }
+
+ // Nobody should use this anyway, since it's internal, but IIRC some people do, so let's be nice...
+ // TODO remove in OC 1.6
+ /**
+ * @deprecated use api.Items.get("luaBios").createItemStack(amount) instead.
+ */
+ @Deprecated
+ def createLuaBios(amount: Int = 1) = {
+ get(Constants.ItemName.LuaBios).createItemStack(amount)
}
def createConfiguredDrone() = {
@@ -204,8 +261,8 @@ object Items extends ItemAPI {
get(Constants.ItemName.RAMTier6).createItemStack(1),
get(Constants.ItemName.RAMTier6).createItemStack(1),
- createLuaBios(),
- createOpenOS(),
+ get(Constants.ItemName.LuaBios).createItemStack(1),
+ get(Constants.ItemName.OpenOS).createItemStack(1),
get(Constants.ItemName.HDDTier3).createItemStack(1)
)
data.containers = Array(
@@ -238,10 +295,10 @@ object Items extends ItemAPI {
Option(get(Constants.ItemName.RAMTier6).createItemStack(1)),
Option(get(Constants.ItemName.RAMTier6).createItemStack(1)),
- Option(createLuaBios()),
+ Option(get(Constants.ItemName.LuaBios).createItemStack(1)),
Option(get(Constants.ItemName.HDDTier3).createItemStack(1))
).padTo(32, None)
- data.items(31) = Option(createOpenOS())
+ data.items(31) = Option(get(Constants.ItemName.OpenOS).createItemStack(1))
data.container = Option(get(Constants.BlockName.DiskDrive).createItemStack(1))
val stack = get(Constants.ItemName.Tablet).createItemStack(1)
@@ -255,20 +312,19 @@ object Items extends ItemAPI {
def init() {
val multi = new item.Delegator() {
- def configuredItems = Array(
- createLuaBios(),
+ def additionalItems = Array(
createConfiguredDrone(),
createConfiguredMicrocontroller(),
createConfiguredRobot(),
createConfiguredTablet()
- )
+ ) ++ registeredItems
override def getSubItems(item: Item, tab: CreativeTabs, list: java.util.List[_]) {
// Workaround for MC's untyped lists...
def add[T](list: java.util.List[T], value: Any) = list.add(value.asInstanceOf[T])
super.getSubItems(item, tab, list)
Loot.worldDisks.values.foreach(entry => add(list, entry._1))
- configuredItems.foreach(add(list, _))
+ additionalItems.foreach(add(list, _))
}
}
@@ -369,7 +425,7 @@ object Items extends ItemAPI {
new item.FloppyDisk(multi) {
showInItemList = false
- override def createItemStack(amount: Int) = createOpenOS(amount)
+ override def createItemStack(amount: Int) = get(Constants.ItemName.OpenOS).createItemStack(1)
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
if (player.isSneaking) get(Constants.ItemName.Floppy).createItemStack(1)
@@ -414,7 +470,13 @@ object Items extends ItemAPI {
// 1.4.2
val eeprom = new item.EEPROM()
Recipes.addItem(eeprom, Constants.ItemName.EEPROM, "oc:eeprom")
- Recipes.addRecipe(createLuaBios(), Constants.ItemName.LuaBios)
+ val luaBios = {
+ val code = new Array[Byte](4 * 1024)
+ val count = OpenComputers.getClass.getResourceAsStream(Settings.scriptPath + "bios.lua").read(code)
+ registerEEPROM("EEPROM (Lua BIOS)", code.take(count), null, readonly = false)
+ }
+ Recipes.addStack(luaBios, Constants.ItemName.LuaBios)
+
Recipes.addSubItem(new item.MicrocontrollerCase(multi, Tier.One), Constants.ItemName.MicrocontrollerCaseTier1, "oc:microcontrollerCase1")
// 1.4.3
@@ -452,6 +514,5 @@ object Items extends ItemAPI {
// 1.5.8
Recipes.addSubItem(new item.UpgradeHover(multi, Tier.One), Constants.ItemName.HoverUpgradeTier1, "oc:hoverUpgrade1")
Recipes.addSubItem(new item.UpgradeHover(multi, Tier.Two), Constants.ItemName.HoverUpgradeTier2, "oc:hoverUpgrade2")
-
}
}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
index c2fc0266f..a459acd10 100644
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
@@ -6,7 +6,6 @@ import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo
-import li.cil.oc.common.init.Items
import li.cil.oc.common.item.data.DroneData
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.PrintData
@@ -28,7 +27,7 @@ import scala.util.control.Breaks._
object ExtendedRecipe {
private lazy val drone = api.Items.get(Constants.ItemName.Drone)
private lazy val eeprom = api.Items.get(Constants.ItemName.EEPROM)
- private lazy val luaBios = Items.createLuaBios()
+ private lazy val luaBios = api.Items.get(Constants.ItemName.LuaBios)
private lazy val mcu = api.Items.get(Constants.BlockName.Microcontroller)
private lazy val navigationUpgrade = api.Items.get(Constants.ItemName.NavigationUpgrade)
private lazy val linkedCard = api.Items.get(Constants.ItemName.LinkedCard)
@@ -159,7 +158,7 @@ object ExtendedRecipe {
// EEPROM copying.
if (api.Items.get(craftedStack) == eeprom &&
- !ItemStack.areItemStackTagsEqual(craftedStack, luaBios) &&
+ api.Items.get(craftedStack) != luaBios &&
recipe.isInstanceOf[ExtendedShapelessOreRecipe] &&
recipe.asInstanceOf[ExtendedShapelessOreRecipe].getInput != null &&
recipe.asInstanceOf[ExtendedShapelessOreRecipe].getInput.size == 2) breakable {
diff --git a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala b/src/main/scala/li/cil/oc/common/recipe/Recipes.scala
index 3f5c764f2..a52c321c5 100644
--- a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/Recipes.scala
@@ -68,6 +68,13 @@ object Recipes {
instance
}
+ def addStack(stack: ItemStack, name: String, oreDict: String*) = {
+ Items.registerStack(stack, name)
+ addRecipe(stack, name)
+ register(stack, oreDict: _*)
+ stack
+ }
+
def addRecipe(stack: ItemStack, name: String) {
list += stack -> name
}
@@ -149,7 +156,7 @@ object Recipes {
val lootRecipes = recipes.getConfigList("lootDisks")
for (recipe <- lootRecipes) {
val name = recipe.getString("name")
- Loot.builtInDisks.get(name) match {
+ Loot.globalDisks.get(name) match {
case Some((stack, _)) => addRecipe(stack, recipe, s"loot disk '$name'")
case _ =>
OpenComputers.log.warn(s"Failed adding recipe for loot disk '$name': No such global loot disk.")
diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverFileSystem.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverFileSystem.scala
index 824d04533..9d8b9b966 100644
--- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverFileSystem.scala
+++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverFileSystem.scala
@@ -5,6 +5,7 @@ import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
+import li.cil.oc.common.Loot
import li.cil.oc.common.Slot
import li.cil.oc.common.item.Delegator
import li.cil.oc.common.item.FloppyDisk
@@ -41,17 +42,31 @@ object DriverFileSystem extends Item {
}
private def createEnvironment(stack: ItemStack, capacity: Int, host: EnvironmentHost, speed: Int) = {
- // We have a bit of a chicken-egg problem here, because we want to use the
- // node's address as the folder name... so we generate the address here,
- // if necessary. No one will know, right? Right!?
- val address = addressFromTag(dataTag(stack))
- val isFloppy = api.Items.get(stack) == api.Items.get(Constants.ItemName.Floppy)
- val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
- val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ReadWriteItemLabel(stack), host, Settings.resourceDomain + ":" + (if (isFloppy) "floppy_access" else "hdd_access"), speed)
- if (environment != null && environment.node != null) {
- environment.node.asInstanceOf[oc.server.network.Node].address = address
+ if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "lootFactory")) {
+ // Loot disk, create file system using factory callback.
+ Loot.factories.get(stack.getTagCompound.getString(Settings.namespace + "lootFactory")) match {
+ case Some(factory) =>
+ val label =
+ if (dataTag(stack).hasKey(Settings.namespace + "fs.label"))
+ dataTag(stack).getString(Settings.namespace + "fs.label")
+ else null
+ api.FileSystem.asManagedEnvironment(factory.call(), label, host, Settings.resourceDomain + ":floppy_access")
+ case _ => null // Invalid loot disk.
+ }
+ }
+ else {
+ // We have a bit of a chicken-egg problem here, because we want to use the
+ // node's address as the folder name... so we generate the address here,
+ // if necessary. No one will know, right? Right!?
+ val address = addressFromTag(dataTag(stack))
+ val isFloppy = api.Items.get(stack) == api.Items.get(Constants.ItemName.Floppy)
+ val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
+ val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ReadWriteItemLabel(stack), host, Settings.resourceDomain + ":" + (if (isFloppy) "floppy_access" else "hdd_access"), speed)
+ if (environment != null && environment.node != null) {
+ environment.node.asInstanceOf[oc.server.network.Node].address = address
+ }
+ environment
}
- environment
}
private def addressFromTag(tag: NBTTagCompound) =
diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverLootDisk.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverLootDisk.scala
index ef00c1138..fe1cf718a 100644
--- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverLootDisk.scala
+++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverLootDisk.scala
@@ -11,6 +11,9 @@ import li.cil.oc.common.Slot
import net.minecraft.item.ItemStack
import net.minecraftforge.common.DimensionManager
+// This is deprecated and kept for compatibility with old saves.
+// As of OC 1.5.10, loot disks are generated using normal floppies, and using
+// a factory system that allows third-party mods to register loot disks.
object DriverLootDisk extends Item {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get(Constants.ItemName.LootDisk))