updated documentation in api; made createEnvironment for item components pass a tile entity instead of an object (always is a tile entity)

This commit is contained in:
Florian Nücke 2013-11-29 03:01:59 +01:00
parent 9ddbc35f4f
commit 608383bf8a
24 changed files with 274 additions and 182 deletions

View File

@ -8,7 +8,10 @@ import li.cil.oc.api.driver.Item;
* This API allows registering new drivers with the mod. * This API allows registering new drivers with the mod.
* <p/> * <p/>
* Drivers are used to make items and third-party blocks available in the mod's * Drivers are used to make items and third-party blocks available in the mod's
* component network, and optionally to Lua programs. * component network, and optionally to Lua programs. If you implement a new
* block that should interact with the mod's component network it is enough to
* have it implement {@link li.cil.oc.api.network.Environment} - no driver is
* needed in that case.
* *
* @see Network * @see Network
* @see Block * @see Block

View File

@ -8,22 +8,27 @@ import li.cil.oc.api.network.ManagedEnvironment;
/** /**
* This class provides factory methods for creating file systems that are * This class provides factory methods for creating file systems that are
* compatible with the built-in filesystem driver. * compatible with the built-in file system driver.
* <p/> * <p/>
* File systems created this way and wrapped in a managed environment via * File systems created this way and wrapped in a managed environment via
* {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem)} will appear as * {@link #asManagedEnvironment} or its overloads will appear as
* <tt>filesystem</tt> components in the internal network. Note that the * <tt>filesystem</tt> components in the component network. Note that the
* component's visibility is set to <tt>Neighbors</tt> per default. If you wish * component's visibility is set to <tt>Neighbors</tt> per default. If you wish
* to change the file system's visibility (e.g. like the disk drive does) you * to change the file system's visibility (e.g. like the disk drive does) you
* must cast the environment's node to {@link li.cil.oc.api.network.Component} * must cast the environment's node to {@link li.cil.oc.api.network.Component}
* and set it accordingly. * and set the visibility to the desired value.
* <p/>
* Note that these methods should <em>not</em> be called in the pre-init phase,
* since the {@link #instance} may not have been initialized at that time. Only
* start calling these methods in the init phase or later.
*/ */
public final class FileSystem { public final class FileSystem {
/** /**
* Creates a new file system based on the location of a class. * Creates a new file system based on the location of a class.
* <p/> * <p/>
* This can be used to wrap a folder in the assets folder of your mod's JAR. * This can be used to wrap a folder in the assets folder of your mod's JAR.
* The actual path is built like this: `"/assets/" + domain + "/" + root`. * The actual path is built like this:
* <pre>"/assets/" + domain + "/" + root</pre>
* <p/> * <p/>
* If the class is located in a JAR file, this will create a read-only file * If the class is located in a JAR file, this will create a read-only file
* system based on that JAR file. If the class file is located in the native * system based on that JAR file. If the class file is located in the native
@ -32,10 +37,10 @@ public final class FileSystem {
* class path (i.e. it'll look for a path constructed as described above). * class path (i.e. it'll look for a path constructed as described above).
* <p/> * <p/>
* If the specified path cannot be located, the creation fails and this * If the specified path cannot be located, the creation fails and this
* returns `None`. * returns <tt>null</tt>.
* *
* @param clazz the class whose containing JAR to wrap. * @param clazz the class whose containing JAR to wrap.
* @param domain the mod domain, usually its name. * @param domain the domain, usually your mod's ID.
* @param root an optional subdirectory. * @param root an optional subdirectory.
* @return a file system wrapping the specified folder. * @return a file system wrapping the specified folder.
*/ */
@ -49,11 +54,11 @@ public final class FileSystem {
* <p/> * <p/>
* This will create a folder, if necessary, and create a writable virtual * This will create a folder, if necessary, and create a writable virtual
* file system based in that folder. The actual path is based in a sub- * file system based in that folder. The actual path is based in a sub-
* folder of the save folder. The actual path is e.g. built like this: * folder of the save folder. The actual path is built like this:
* <tt>"saves/" + WORLD_NAME + "/opencomputers/" + root</tt>. Where the first * <pre>"saves/" + WORLD_NAME + "/opencomputers/" + root</pre>
* part may differ, in particular for servers. But you get the idea. * The first part may differ, in particular for servers.
* <p/> * <p/>
* Usually the name will be the name of the node used to represent the * Usually the name will be the address of the node used to represent the
* file system. * file system.
* <p/> * <p/>
* Note that by default file systems are "buffered", meaning that any * Note that by default file systems are "buffered", meaning that any
@ -86,12 +91,12 @@ public final class FileSystem {
} }
/** /**
* Creates a new *writable* file system that resides in memory. * Creates a new <em>writable</em> file system that resides in memory.
* <p/> * <p/>
* Any contents created and written on this file system will be lost when * Any contents created and written on this file system will be lost when
* the node is removed from the network. * the node is removed from the network.
* <p/> * <p/>
* This is used for computers' `/tmp` mount, for example. * This is used for computers' <tt>/tmp</tt> mount, for example.
* *
* @param capacity the capacity of the file system. * @param capacity the capacity of the file system.
* @return a file system residing in memory. * @return a file system residing in memory.
@ -131,7 +136,7 @@ public final class FileSystem {
* your own driver. Which will probably be most of the time. If you need * your own driver. Which will probably be most of the time. If you need
* more control over the node, implement your own, and connect this one to * more control over the node, implement your own, and connect this one to
* it. In that case you will have to forward any disk driver messages to the * it. In that case you will have to forward any disk driver messages to the
* node, though, since it's visibility is neighbors only. * node, though.
* *
* @param fileSystem the file system to wrap. * @param fileSystem the file system to wrap.
* @param label the label of the file system. * @param label the label of the file system.
@ -143,8 +148,8 @@ public final class FileSystem {
} }
/** /**
* Does the same thing {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)} * Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)},
* does, but creates a read-only label initialized to the specified value. * but creates a read-only label initialized to the specified value.
* *
* @param fileSystem the file system to wrap. * @param fileSystem the file system to wrap.
* @param label the read-only label of the file system. * @param label the read-only label of the file system.
@ -156,9 +161,9 @@ public final class FileSystem {
} }
/** /**
* Does the same thing {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)} * Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)},
* does, but creates an unlabeled file system (i.e. the label can neither * but creates an unlabeled file system (i.e. the label can neither be read
* be read nor written). * nor written).
* *
* @param fileSystem the file system to wrap. * @param fileSystem the file system to wrap.
* @return the network node wrapping the file system. * @return the network node wrapping the file system.

View File

@ -8,18 +8,36 @@ import li.cil.oc.api.network.Visibility;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
/** /**
* This class provides factories networks and nodes. * This class provides factories for networks and nodes.
* <p/> * <p/>
* The two functions provided provided by this API are to allow existing * The first two functions provided provided by this API are to allow existing
* environments - implemented in a tile entity - to join an existing network or * environments - implemented in a tile entity for example - to join an existing
* create a new one, and to create nodes that may then be connected to an * network or create new ones. The third one is used to create nodes that may
* existing network. It is not possible to create networks that do not belong * then be connected to an existing network. It is not possible to create
* to at least one tile entity at this time. * networks that do not belong to at least one tile entity or node.
* <p/>
* It is important to understand that component networks only exist on the
* server side. It is impossible to create nodes, and therefore networks, on
* the client side. This is to enforce a clear distinction of where the actual
* logic lies - since Lua only runs on the server.
* <p/>
* Note that these methods should <em>not</em> be called in the pre-init phase,
* since the {@link #instance} may not have been initialized at that time. Only
* start calling these methods in the init phase or later.
*/ */
public final class Network { public final class Network {
/** /**
* Tries to add a tile entity network node at the specified coordinates to * Tries to add a tile entity's network node(s) at the specified coordinates
* adjacent networks. * to adjacent networks.
* <p/>
* If the tile entity implements {@link Environment} its one node will be
* connected to any existing adjacent tile entity nodes. If none exist a
* new network with the specified tile entity's node as its sole entry.
* <p/>
* If the tile entity is a {@link li.cil.oc.api.network.SidedEnvironment}
* the same rules as for simple environments apply, except that the
* respective for each side is used when connecting, and each side's node
* is added to its own new network, if necessary.
* *
* @param tileEntity the tile entity to initialize. * @param tileEntity the tile entity to initialize.
*/ */
@ -52,23 +70,34 @@ public final class Network {
* Example use: * Example use:
* <pre> * <pre>
* class YourThing extends TileEntity implements Environment { * class YourThing extends TileEntity implements Environment {
* private ComponentConnector node_ = api.Network.newNode(this, Visibility.Network). * private ComponentConnector node_ =
* withComponent("your_thing"). * api.Network.newNode(this, Visibility.Network).
* withConnector(32). * withComponent("your_thing").
* create(); * withConnector(32).
* create();
* *
* public Node node() { return node_; } * public Node node() { return node_; }
* *
* // ... * // ...
* } * }
* </pre> * </pre>
* <p/>
* Note that the <em>reachability</em> specified here is the general
* availability of the created node to other nodes in the network. Special
* rules apply to components, which have a <em>visibility</em> that is used
* to control how they can be reached from Lua. For example, network cards
* have a <em>reachability</em> of <tt>Visibility.Network</tt>, to allow
* them to communicate with each other, but a <em>visibility</em> of
* <tt>Visibility.Neighbors</tt> to avoid other computers in the network
* to see the card (i.e. only the Lua programs running on the computer the
* card installed in can see interact with it).
* *
* @param host the environment the node is created for. * @param host the environment the node is created for.
* @param visibility the visibility of the node. * @param reachability the reachability of the node.
* @return a new node builder. * @return a new node builder.
*/ */
public static Builder.NodeBuilder newNode(Environment host, Visibility visibility) { public static Builder.NodeBuilder newNode(Environment host, Visibility reachability) {
if (instance != null) return instance.newNode(host, visibility); if (instance != null) return instance.newNode(host, reachability);
return null; return null;
} }

View File

@ -17,7 +17,7 @@ public interface Persistable {
* Saves the current state of the object into the specified NBT tag. * Saves the current state of the object into the specified NBT tag.
* <p/> * <p/>
* This should write the state in such a way that it can be restored when * This should write the state in such a way that it can be restored when
* `load` is called with that tag. * {@link #load} is called with that tag.
* *
* @param nbt the tag to save the state to. * @param nbt the tag to save the state to.
*/ */

View File

@ -2,6 +2,11 @@ package li.cil.oc.api.detail;
import li.cil.oc.api.network.*; import li.cil.oc.api.network.*;
/**
* Used for building {@link Node}s via {@link li.cil.oc.api.Network#newNode}.
*
* @param <T> the type of the node created by this builder.
*/
public interface Builder<T extends Node> { public interface Builder<T extends Node> {
T create(); T create();

View File

@ -10,5 +10,5 @@ public interface NetworkAPI {
void joinNewNetwork(Node node); void joinNewNetwork(Node node);
Builder.NodeBuilder newNode(Environment host, Visibility visibility); Builder.NodeBuilder newNode(Environment host, Visibility reachability);
} }

View File

@ -8,10 +8,14 @@ import net.minecraft.world.World;
* <p/> * <p/>
* This driver type is used for components that are blocks, i.e. that can be * This driver type is used for components that are blocks, i.e. that can be
* placed in the world, but cannot be modified to or don't want to have their * placed in the world, but cannot be modified to or don't want to have their
* `TileEntities` implement `network.Node`. * {@link net.minecraft.tileentity.TileEntity} implement one of the interfaces
* for environments ({@link li.cil.oc.api.network.Environment} or
* {@link li.cil.oc.api.network.SidedEnvironment}).
* <p/> * <p/>
* A block driver is used by proxy blocks to check its neighbors and whether * A block driver is used by <tt>Adapter</tt> blocks to check its neighbors and
* those neighbors should be treated as components or not. * whether those neighbors should be treated as components or not. If a driver
* is present, it will be used to create a {@link ManagedEnvironment} that is
* managed by the adapter.
* <p/> * <p/>
* Note that it is possible to write one driver that supports as many different * Note that it is possible to write one driver that supports as many different
* blocks as you wish. I'd recommend writing one per device (type), though, to * blocks as you wish. I'd recommend writing one per device (type), though, to
@ -21,32 +25,38 @@ public interface Block {
/** /**
* Used to determine the block types this driver handles. * Used to determine the block types this driver handles.
* <p/> * <p/>
* This is used to determine which driver to use for a block placed next to a * This is used to determine which driver to use for a block placed next to
* computer. Note that the return value should not change over time; if it * an <tt>Adapter</tt> block. Note that the return value should not change
* does, though, an already installed component will not be ejected, since * over time; if it does, though, an already installed component will not
* this value is only checked when adding components. * be removed, since this value is only checked when scanning blocks. You
* can force this by sending a neighbor block change notification.
* *
* @param world the world in which the block to check lives. * @param world the world in which the block to check lives.
* @param x the X coordinate of the block to check. * @param x the X coordinate of the block to check.
* @param y the Y coordinate of the block to check. * @param y the Y coordinate of the block to check.
* @param z the Z coordinate of the block to check. * @param z the Z coordinate of the block to check.
* @return true if the block is supported; false otherwise. * @return <tt>true</tt> if the block is supported; <tt>false</tt> otherwise.
*/ */
boolean worksWith(World world, int x, int y, int z); boolean worksWith(World world, int x, int y, int z);
/** /**
* Get a reference to the network node wrapping the specified block. * Create a new managed environment interfacing the specified block.
* <p/> * <p/>
* This is used to connect the component to the component network when it is * This is used to connect the component to the component network when it
* detected next to a proxy. Components that are not part of the component * is detected next to an <tt>Adapter</tt>. Components that are not part of
* network probably don't make much sense (can't think of any uses at this * the component network probably don't make much sense (can't think of any
* time), but you may still opt to not implement this. * uses at this time), but you may still opt to not implement this - i.e.
* it is safe to return <tt>null</tt> here.
* <p/>
* This is expected to return a <em>new instance</em> each time it is
* called. The created instance's life cycle is managed by the
* <tt>Adapter</tt> block that caused its creation.
* *
* @param world the world in which the block to get the node for lives. * @param world the world containing the block to get the environment for.
* @param x the X coordinate of the block to get the node for. * @param x the X coordinate of the block to get the environment for.
* @param y the Y coordinate of the block to get the node for. * @param y the Y coordinate of the block to get the environment for.
* @param z the Z coordinate of the block to get the node for. * @param z the Z coordinate of the block to get the environment for.
* @return the network node for the block at that location. * @return the environment for the block at that location.
*/ */
ManagedEnvironment createEnvironment(World world, int x, int y, int z); ManagedEnvironment createEnvironment(World world, int x, int y, int z);
} }

View File

@ -3,20 +3,21 @@ package li.cil.oc.api.driver;
import li.cil.oc.api.network.ManagedEnvironment; import li.cil.oc.api.network.ManagedEnvironment;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
/** /**
* Interface for item component drivers. * Interface for item component drivers.
* <p/> * <p/>
* This driver type is used for components that are items, i.e. that can be * This driver type is used for components that are items, i.e. that can be
* inserted into computers. An example for this are internal drives, memory and * inserted into computers and robots. An example for this are internal drives,
* power supply units. * memory and graphic cards.
* <p/> * <p/>
* When trying to add an item to a computer the list of registered drivers is * When trying to add an item to a computer the list of registered drivers is
* queried using the drivers' `worksWith` functions. The first driver that * queried using the drivers' <tt>worksWith</tt> functions. The first driver
* replies positively and whose check against the slot type is successful, i.e. * that replies positively and whose check against the slot type is successful,
* for which the `slot` matches the slot it should be inserted into, will be * i.e. for which the <tt>slot</tt> matches the slot it should be inserted into,
* used as the component's driver and the component will be added. If no driver * will be used as the component's driver and the component will be added. If no
* is found the item will be rejected and cannot be installed. * driver is found the item will be rejected and cannot be installed.
* <p/> * <p/>
* Note that it is possible to write one driver that supports as many different * Note that it is possible to write one driver that supports as many different
* items as you wish. I'd recommend writing one per device (type), though, to * items as you wish. I'd recommend writing one per device (type), though, to
@ -26,57 +27,71 @@ public interface Item {
/** /**
* Used to determine the item types this driver handles. * Used to determine the item types this driver handles.
* <p/> * <p/>
* This is used to determine which driver to use for an item when installed in * This is used to determine which driver to use for an item when it should
* a computer. Note that the return value should not change over time; if it * be installed in a computer. Note that the return value should not change
* does, though, an already installed component will not be ejected, since * over time; if it does, though, an already installed component will not
* this value is only checked when adding components. * be ejected, since this value is only checked when adding components.
* *
* @param item the item to check. * @param item the item to check.
* @return true if the item is supported; false otherwise. * @return <tt>true</tt> if the item is supported; <tt>false</tt> otherwise.
*/ */
boolean worksWith(ItemStack item); boolean worksWith(ItemStack item);
/** /**
* Gets a reference to the network node interfacing the specified item. * Create a new managed environment interfacing the specified item.
* <p/> * <p/>
* This is used to connect the component to the component network when it is * This is used to connect the component to the component network when it is
* added to a computer, for example. Components that are not part of the * added to a computer, for example. The only kind of component that does
* component network probably don't make much sense (can't think of any uses * not need to be connected to the component network is probably memory, and
* at this time), but you may still opt to not implement this. * there's a built-in driver for that. You may still opt to not implement
* this - i.e. it is safe to return <tt>null</tt> here.
* <p/> * <p/>
* This is expected to return a *new instance* each time it is called. * Keep in mind that the tile entity's location may change if the owner is
* a robot. This is important if you cache the location somewhere. For
* example, the wireless network card checks in it's update whether its
* owner's position has changed to update the index structure used for
* receiver look-up.
* <p/>
* This is expected to return a <em>new instance</em> each time it is
* called. The created instance's life cycle is managed by the computer or
* other container that caused its creation.
* *
* @param item the item instance for which to get the node. * @param stack the item stack for which to get the environment.
* @param container the container the environment will be managed by. This * @param container the tile entity the environment will be managed by.
* will usually be a tile entity. * @return the environment for that item.
* @return the network node for that item.
*/ */
ManagedEnvironment createEnvironment(ItemStack item, Object container); ManagedEnvironment createEnvironment(ItemStack stack, TileEntity container);
/** /**
* The slot type of the specified item this driver supports. * The slot type of the specified item this driver supports.
* <p/> * <p/>
* This is used to determine into which slot of a computer the components this * This is used to determine into which slot of a computer the components
* driver supports may go. This will only be called if a previous call to * this driver supports may go. This will only be called if a previous call
* `worksWith` with the same item type returned true. * to {@link #worksWith} with the same stack returned true.
* *
* @param item the item to get the slot type for. * @param stack the item stack to get the slot type for.
* @return the component type of the specified item. * @return the slot type of the specified item.
*/ */
Slot slot(ItemStack item); Slot slot(ItemStack stack);
/** /**
* Get the tag compound based on the item stack to use for persisting the * Get the tag compound based on the item stack to use for persisting the
* environment and node associated with the specified item stack. * environment associated with the specified item stack.
* <p/> * <p/>
* This is only used if the item has an environment. This must always be a * This is only used if the item has an environment. This must always be a
* child tag of the items own tag compound, it will not be saved otherwise. * child tag of the item stack's own tag compound, it will not be saved
* Use this in the unlikely case that the default name collides with * otherwise. Use this in the unlikely case that the default name collides
* something. The built-in components use a child tag-compound with the name * with something. The built-in components use a child tag-compound with
* "oc:node". * the name <tt>oc:data</tt>, which will also be used if this returns
* <tt>null</tt>.
* <p/>
* This tag will be passed to the environment's <tt>save</tt> and
* <tt>load</tt> methods when appropriate (world save / load and when
* removed from their hosting inventory).
* *
* @param item the item to get the child tag from. * @param stack the item to get the child tag from.
* @return the tag to use for saving and loading. * @return the tag to use for saving and loading, or <tt>null</tt> to use
* the default tag <tt>oc:data</tt>.
*/ */
NBTTagCompound nbt(ItemStack item); NBTTagCompound dataTag(ItemStack stack);
} }

View File

@ -11,7 +11,7 @@ import net.minecraft.item.ItemStack;
*/ */
public interface Memory extends Item { public interface Memory extends Item {
/** /**
* The amount of RAM this component provides, in byte. * The amount of RAM this component provides, in bytes.
* *
* @param item the item to get the provided memory for. * @param item the item to get the provided memory for.
* @return the amount of memory the specified component provides. * @return the amount of memory the specified component provides.

View File

@ -4,26 +4,36 @@ package li.cil.oc.api.driver;
* List of possible item component types. * List of possible item component types.
* <p/> * <p/>
* This is used to determine which item components may go into which slots in * This is used to determine which item components may go into which slots in
* a computer's and robot's inventory. * a computer's or robot's inventory.
*/ */
public enum Slot { public enum Slot {
/** /**
* Invalid slot type. * Invalid slot type.
* <p/>
* Drivers should never return this, used internally.
*/ */
None, None,
/** /**
* Extension cards such as graphics cards or redstone cards. * Extension cards such as graphics cards or redstone cards.
* <p/>
* The primary means of adding new functionality to a computer or robot.
*/ */
Card, Card,
/** /**
* Floppy disks. These can be inserted into the Disk Drive block. * Floppy disks.
* <p/>
* These can be inserted into the disk drive block, robots and tier three
* computer cases. They provide persistent storage cheaper than hard disk
* drives, but with much more limited capacity.
*/ */
Disk, Disk,
/** /**
* Hard disk drives. These can be installed in computers. * Hard disk drives.
* <p/>
* These can be installed in computers to provide persistent storage.
*/ */
HardDiskDrive, HardDiskDrive,
@ -34,12 +44,17 @@ public enum Slot {
/** /**
* Tool slot in robots (equipment slot). * Tool slot in robots (equipment slot).
* <p/>
* Components should usually not implement this slot type, since this slot
* allows any kind of item. It is only used to define the background icon
* for the tool slot in robots.
*/ */
Tool, Tool,
/** /**
* Upgrade slot for robots. For special robot upgrades such as internal * Upgrade slot for robots.
* engines and the like. * <p/>
* Used for special robot upgrades such as internal engines and the like.
*/ */
Upgrade Upgrade
} }

View File

@ -1,27 +1,18 @@
package li.cil.oc.api.fs; package li.cil.oc.api.fs;
import li.cil.oc.api.Persistable; import li.cil.oc.api.Persistable;
import li.cil.oc.api.network.Network;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
/** /**
* Interface for file system driver compatible file systems. * Interface for file system driver compatible file systems.
* <p/> * <p/>
* To create a file system from a JAR file or folder (in read-only mode; for * See {@link li.cil.oc.api.FileSystem} for factory methods.
* example the one containing your mod) use `Filesystem.fromClass`, providing
* a class from your mod as the first parameter.
* <p/>
* To get a network node wrapping a file system and using the default file
* system driver, use `Filesystem.asNode`.
* <p/>
* Alternatively to using the factory methods for file systems in `Filesystem`
* you are free to implement this interface yourself.
* <p/> * <p/>
* Note that all paths passed here are assumed to be absolute in the underlying * Note that all paths passed here are assumed to be absolute in the underlying
* file system implementation, meaning they do not contain any "." or "..", and * file system implementation, meaning they do not contain any "." or "..", and
* are relative to the root of the file system. When wrapping a file system in * are relative to the root of the file system. When wrapping a file system in
* a node with the provided factory function this is automatically ensured. If * a node with the provided factory functions this is automatically ensured. If
* you call any of the functions of a file system directly it is your * you call any of the functions of a file system directly it is your
* responsibility to ensure the path has been cleaned up. * responsibility to ensure the path has been cleaned up.
*/ */
@ -35,9 +26,6 @@ public interface FileSystem extends Persistable {
* accordingly to enforce true read-only logic (i.e. {@link #open} should * accordingly to enforce true read-only logic (i.e. {@link #open} should
* not allow opening files in write or append mode, {@link #makeDirectory} * not allow opening files in write or append mode, {@link #makeDirectory}
* and such should do nothing/return false/throw an exception). * and such should do nothing/return false/throw an exception).
* <p/>
* For file systems made available to the component {@link Network} will
* also use this flag to determine whether their label may be changed.
*/ */
boolean isReadOnly(); boolean isReadOnly();
@ -53,8 +41,6 @@ public interface FileSystem extends Persistable {
/** /**
* The used storage capacity of the file system, in bytes. * The used storage capacity of the file system, in bytes.
* <p/>
* For read-only systems this should return zero.
* *
* @return the used storage space of this file system. * @return the used storage space of this file system.
*/ */
@ -68,7 +54,8 @@ public interface FileSystem extends Persistable {
* This function should never throw. * This function should never throw.
* *
* @param path the path to check at. * @param path the path to check at.
* @return true if the path points to a file or directory; false otherwise. * @return <tt>true</tt> if the path points to a file or directory;
* <tt>false</tt> otherwise.
*/ */
boolean exists(String path); boolean exists(String path);
@ -117,19 +104,19 @@ public interface FileSystem extends Persistable {
* Gets a list of all items in the specified folder. * Gets a list of all items in the specified folder.
* <p/> * <p/>
* This must return the actual object names in the specified parent folder, * This must return the actual object names in the specified parent folder,
* not their full path. For example, for a file at `/home/test`, when doing * not their full path. For example, for a file at <tt>/home/test</tt>, when
* `list("/home/")` this should return `["test"]`, *not* `["/home/test"]`. * doing <tt>list("/home/")</tt> this should return <tt>["test"]</tt>,
* <em>not</em> <tt>["/home/test"]</tt>.
* <p/> * <p/>
* Sub-folders should be returned with a trailing slash, to indicate that * Sub-folders should be returned with a trailing slash, to indicate that
* they are folders. This is primarily intended to avoid Lua programs having * they are folders.
* to check which of the entries are folders via calling `isDirectory`, which
* would be excruciatingly slow (since each call takes one game tick).
* <p/> * <p/>
* If the folder is empty this should return an empty array. * If the folder is empty this should return an empty array.
* *
* @param path the path to the folder to get the contents of. * @param path the path to the folder to get the contents of.
* @return an array with the names of all objects in that folder; `null` if * @return an array with the names of all objects in that folder;
* the specified object does not exist or is not a folder. * <tt>null</tt> if the specified object does not exist or is not a
* folder.
*/ */
String[] list(String path); String[] list(String path);
@ -139,26 +126,27 @@ public interface FileSystem extends Persistable {
* Deletes a file or folder. * Deletes a file or folder.
* <p/> * <p/>
* This only has to support deleting single files and empty folders. If a * This only has to support deleting single files and empty folders. If a
* directory is non-empty this may return false. If the target object does * directory is non-empty this may return <tt>false</tt>. If the target
* not exists it should return false. * object does not exists it should return <tt>false</tt>.
* <p/> * <p/>
* This is only available for writable file systems. For read-only systems * This is only available for writable file systems. For read-only systems
* it should just always return false. * it should always return <tt>false</tt>.
* *
* @param path the path to the object to delete. * @param path the path to the object to delete.
* @return true if the object was successfully deleted; false otherwise. * @return <tt>true</tt> if the object was successfully deleted;
* <tt>false</tt> otherwise.
*/ */
boolean delete(String path); boolean delete(String path);
/** /**
* Create the specified directory. * Create the specified directory.
* <p/> * <p/>
* This should always only create a single directory. If the parent directory * This should always only create a single directory. If the parent
* does not exists it should return false. If the target object already * directory does not exists it should return <tt>false</tt>. If the target
* exists it should also return false. * object already exists it should also return <tt>false</tt>.
* <p/> * <p/>
* This is only available for writable file systems. For read-only systems * This is only available for writable file systems. For read-only systems
* it should just always return false. * it should always return <tt>false</tt>.
* *
* @param path the path to the directory to create. * @param path the path to the directory to create.
* @return true if the directory was created; false otherwise. * @return true if the directory was created; false otherwise.
@ -169,11 +157,12 @@ public interface FileSystem extends Persistable {
* Moves / renames a file or folder. * Moves / renames a file or folder.
* <p/> * <p/>
* This is only available for writable file systems. For read-only systems * This is only available for writable file systems. For read-only systems
* it should just always return false. * it should always return false.
* *
* @param from the name of the file or folder to move. * @param from the name of the file or folder to move.
* @param to the location to move the file or folder to. * @param to the location to move the file or folder to.
* @return true if the object was renamed; false otherwise. * @return <tt>true</tt> if the object was renamed;
* <tt>false</tt> otherwise.
* @throws FileNotFoundException if the source is not a file or folder. * @throws FileNotFoundException if the source is not a file or folder.
*/ */
boolean rename(String from, String to) throws FileNotFoundException; boolean rename(String from, String to) throws FileNotFoundException;
@ -185,10 +174,13 @@ public interface FileSystem extends Persistable {
* intended to be used when initializing a file system to a set of known * intended to be used when initializing a file system to a set of known
* modification times (for example, this is used when creating a virtual * modification times (for example, this is used when creating a virtual
* file system from a set of real files). * file system from a set of real files).
* <p/>
* Read-only file systems may ignore this request.
* *
* @param path the path of the object for which to set the modification time. * @param path the path of the object for which to set the modification time.
* @param time the time the object was supposedly last modified. * @param time the time the object was supposedly last modified.
* @return whether the modification time was adjusted. * @return <tt>true</tt> if the modification time was adjusted;
* <tt>false</tt> otherwise.
*/ */
boolean setLastModified(String path, long time); boolean setLastModified(String path, long time);
@ -199,8 +191,8 @@ public interface FileSystem extends Persistable {
* <p/> * <p/>
* This should create some internal handle to the file, based on the mode * This should create some internal handle to the file, based on the mode
* specified. A unique ID corresponding to that handle should be returned. * specified. A unique ID corresponding to that handle should be returned.
* This ID can be used in `file` to get an abstract wrapper for the handle, * This ID can be used in {@link #getHandle} to get an abstract wrapper for
* and to allow interaction with the file. * the handle, and to allow interaction with the file.
* <p/> * <p/>
* It is the responsibility of the file system to restore all handles to * It is the responsibility of the file system to restore all handles to
* their previous state when it is reloaded (game loaded for example). * their previous state when it is reloaded (game loaded for example).
@ -215,20 +207,22 @@ public interface FileSystem extends Persistable {
int open(String path, Mode mode) throws FileNotFoundException; int open(String path, Mode mode) throws FileNotFoundException;
/** /**
* Gets a wrapper for a file previously opened using `open`. * Gets a wrapper for a file previously opened using {@link #open}.
* <p/> * <p/>
* The wrapper allows interaction with the underlying file (stream) based * The wrapper allows interaction with the underlying file (stream) based
* on the mode it was opened in. See the `File` interface for more details. * on the mode it was opened in. See {@link Handle} for more details.
* <p/> * <p/>
* If there is no such handle, this should return `None`, but never throw. * If there is no such handle, this should return <tt>null</tt>, but never
* throw.
* *
* @param handle the ID of the handle to get the wrapper for. * @param handle the ID of the handle to get the wrapper for.
* @return the wrapper for that handle ID; None if the ID is invalid. * @return the wrapper for that handle ID; <tt>null</tt> if there is no
* handle with the specified ID.
*/ */
Handle getHandle(int handle); Handle getHandle(int handle);
/** /**
* Called when the file system is close. * Called when the file system is destroyed.
* <p/> * <p/>
* This should close any open real file handles (e.g. all open I/O streams), * This should close any open real file handles (e.g. all open I/O streams),
* but keep any internal state that may have to be persisted, for example * but keep any internal state that may have to be persisted, for example
@ -236,11 +230,11 @@ public interface FileSystem extends Persistable {
* save any open handles). * save any open handles).
* <p/> * <p/>
* When the filesystem is made available as a network node created via * When the filesystem is made available as a network node created via
* `FileSystem.asNode` this will be called whenever the node is disconnected * one of the factory functions in {@link li.cil.oc.api.FileSystem} this
* from its network. If the node was used to represent an item (which will * will be called whenever the node is disconnected from its network. If
* be the usual use-case, I imagine) this means the item was removed from * the node was used to represent an item (which will be the usual use-case,
* its container (e.g. hard drive from a computer) or the container was * I imagine) this means the item was removed from its container (e.g. hard
* unloaded. * drive from a computer) or the container was unloaded.
*/ */
void close(); void close();
} }

View File

@ -20,8 +20,8 @@ public interface Handle {
* Closes the handle. * Closes the handle.
* <p/> * <p/>
* For example, if there is an underlying stream, this should close that * For example, if there is an underlying stream, this should close that
* stream. Any future calls to {@link #read} or {@link #write} should throw an * stream. Any future calls to {@link #read} or {@link #write} should throw
* <tt>IOException</tt> after this function was called. * an <tt>IOException</tt> after this function was called.
*/ */
void close(); void close();

View File

@ -19,8 +19,11 @@ public interface Label {
* Set the new value of this label. * Set the new value of this label.
* <p/> * <p/>
* May be set to <tt>null</tt> to clear the label. * May be set to <tt>null</tt> to clear the label.
* <p/>
* May throw an exception if the label is read-only.
* *
* @param value the new label. * @param value the new label.
* @throws IllegalArgumentException if the label is read-only.
*/ */
void setLabel(String value); void setLabel(String value);
} }

View File

@ -1,14 +1,18 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
import li.cil.oc.api.driver import li.cil.oc.api.driver
import li.cil.oc.api.driver.{Item => ItemDriver}
import li.cil.oc.api.network import li.cil.oc.api.network
import li.cil.oc.api.network.{ManagedEnvironment, Node} import li.cil.oc.api.network.{ManagedEnvironment, Node}
import li.cil.oc.server.driver.Registry import li.cil.oc.server.driver.Registry
import li.cil.oc.server.driver.item.Item
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
trait ComponentInventory extends Inventory with network.Environment { trait ComponentInventory extends Inventory with network.Environment {
self: MCTileEntity =>
protected lazy val components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None) protected lazy val components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None)
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -33,7 +37,7 @@ trait ComponentInventory extends Inventory with network.Environment {
case Some(driver) => case Some(driver) =>
Option(driver.createEnvironment(stack, this)) match { Option(driver.createEnvironment(stack, this)) match {
case Some(environment) => case Some(environment) =>
environment.load(driver.nbt(stack)) environment.load(dataTag(driver, stack))
Some(environment) Some(environment)
case _ => None case _ => None
} }
@ -64,7 +68,7 @@ trait ComponentInventory extends Inventory with network.Environment {
case (stack, slot) => components(slot) match { case (stack, slot) => components(slot) match {
case Some(environment) => case Some(environment) =>
// We're guaranteed to have a driver for entries. // We're guaranteed to have a driver for entries.
environment.save(Registry.driverFor(stack).get.nbt(stack)) environment.save(dataTag(Registry.driverFor(stack).get, stack))
case _ => // Nothing special to save. case _ => // Nothing special to save.
} }
} }
@ -80,9 +84,9 @@ trait ComponentInventory extends Inventory with network.Environment {
case Some(driver) => Option(driver.createEnvironment(stack, this)) match { case Some(driver) => Option(driver.createEnvironment(stack, this)) match {
case Some(component) => case Some(component) =>
components(slot) = Some(component) components(slot) = Some(component)
component.load(driver.nbt(stack)) component.load(dataTag(driver, stack))
connectItemNode(component.node) connectItemNode(component.node)
component.save(driver.nbt(stack)) component.save(dataTag(driver, stack))
ServerPacketSender.sendItemComponentAddress(this, slot, stack) ServerPacketSender.sendItemComponentAddress(this, slot, stack)
case _ => // No environment (e.g. RAM). case _ => // No environment (e.g. RAM).
} }
@ -101,7 +105,7 @@ trait ComponentInventory extends Inventory with network.Environment {
components(slot) = None components(slot) = None
component.node.remove() component.node.remove()
Registry.driverFor(stack).foreach(driver => Registry.driverFor(stack).foreach(driver =>
component.save(driver.nbt(stack))) component.save(dataTag(driver, stack)))
case _ => // Nothing to do. case _ => // Nothing to do.
} }
} }
@ -111,4 +115,7 @@ trait ComponentInventory extends Inventory with network.Environment {
protected def connectItemNode(node: Node) { protected def connectItemNode(node: Node) {
this.node.connect(node) this.node.connect(node)
} }
private def dataTag(driver: ItemDriver, stack: ItemStack) =
Option(driver.dataTag(stack)).getOrElse(Item.dataTag(stack))
} }

View File

@ -3,7 +3,6 @@ package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side} import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network._ import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.block.Delegator import li.cil.oc.common.block.Delegator
import li.cil.oc.server.component.GraphicsCard import li.cil.oc.server.component.GraphicsCard
import li.cil.oc.server.component.robot.Player import li.cil.oc.server.component.robot.Player

View File

@ -5,21 +5,22 @@ import li.cil.oc
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import li.cil.oc.api.fs.Label import li.cil.oc.api.fs.Label
import li.cil.oc.common.item.{Disk, HardDiskDrive} import li.cil.oc.common.item.{Disk, HardDiskDrive}
import li.cil.oc.common.tileentity.DiskDrive import li.cil.oc.common.tileentity.TileEntity
import li.cil.oc.util.mods.ComputerCraft import li.cil.oc.util.mods.ComputerCraft
import li.cil.oc.{Settings, Items} import li.cil.oc.{Settings, Items}
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object FileSystem extends Item { object FileSystem extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.hdd1, Items.hdd2, Items.hdd3, Items.disk) || ComputerCraft.isDisk(stack) override def worksWith(stack: ItemStack) = isOneOf(stack, Items.hdd1, Items.hdd2, Items.hdd3, Items.disk) || ComputerCraft.isDisk(stack)
override def createEnvironment(stack: ItemStack, container: AnyRef) = override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
if (ComputerCraft.isDisk(stack)) { if (ComputerCraft.isDisk(stack)) {
container match { container match {
case diskDrive: DiskDrive => case tileEntity: TileEntity =>
val address = addressFromTag(nbt(stack)) val address = addressFromTag(dataTag(stack))
val mount = ComputerCraft.createDiskMount(stack, diskDrive.world) val mount = ComputerCraft.createDiskMount(stack, tileEntity.world)
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack))) match { Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack))) match {
case Some(environment) => case Some(environment) =>
environment.node.asInstanceOf[oc.server.network.Node].address = address environment.node.asInstanceOf[oc.server.network.Node].address = address
@ -46,7 +47,7 @@ object FileSystem extends Item {
// We have a bit of a chicken-egg problem here, because we want to use the // 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, // node's address as the folder name... so we generate the address here,
// if necessary. No one will know, right? Right!? // if necessary. No one will know, right? Right!?
val address = addressFromTag(nbt(stack)) val address = addressFromTag(dataTag(stack))
Option(oc.api.FileSystem.asManagedEnvironment(oc.api.FileSystem. Option(oc.api.FileSystem.asManagedEnvironment(oc.api.FileSystem.
fromSaveDirectory(address, capacity, Settings.get.bufferChanges), new ItemLabel(stack))) match { fromSaveDirectory(address, capacity, Settings.get.bufferChanges), new ItemLabel(stack))) match {
case Some(environment) => case Some(environment) =>
@ -74,12 +75,12 @@ object FileSystem extends Item {
private class ItemLabel(val stack: ItemStack) extends Label { private class ItemLabel(val stack: ItemStack) extends Label {
def getLabel = def getLabel =
if (nbt(stack).hasKey(Settings.namespace + "fs.label")) if (dataTag(stack).hasKey(Settings.namespace + "fs.label"))
nbt(stack).getString(Settings.namespace + "fs.label") dataTag(stack).getString(Settings.namespace + "fs.label")
else null else null
def setLabel(value: String) { def setLabel(value: String) {
nbt(stack).setString(Settings.namespace + "fs.label", dataTag(stack).setString(Settings.namespace + "fs.label",
if (value.length > 16) value.substring(0, 16) else value) if (value.length > 16) value.substring(0, 16) else value)
} }
} }

View File

@ -4,11 +4,12 @@ import li.cil.oc.Items
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object Generator extends Item { object Generator extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.generator) override def worksWith(stack: ItemStack) = isOneOf(stack, Items.generator)
override def createEnvironment(stack: ItemStack, container: AnyRef) = new component.Generator() override def createEnvironment(stack: ItemStack, container: MCTileEntity) = new component.Generator()
override def slot(stack: ItemStack) = Slot.Upgrade override def slot(stack: ItemStack) = Slot.Upgrade
} }

View File

@ -5,11 +5,12 @@ import li.cil.oc.api.driver.Slot
import li.cil.oc.common import li.cil.oc.common
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object GraphicsCard extends Item { object GraphicsCard extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.gpu1, Items.gpu2, Items.gpu3) override def worksWith(stack: ItemStack) = isOneOf(stack, Items.gpu1, Items.gpu2, Items.gpu3)
override def createEnvironment(stack: ItemStack, container: AnyRef) = override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
Items.multi.subItem(stack) match { Items.multi.subItem(stack) match {
case Some(gpu: common.item.GraphicsCard) => gpu.tier match { case Some(gpu: common.item.GraphicsCard) => gpu.tier match {
case 0 => new component.GraphicsCard.Tier1() case 0 => new component.GraphicsCard.Tier1()

View File

@ -6,7 +6,17 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
trait Item extends api.driver.Item { trait Item extends api.driver.Item {
def nbt(stack: ItemStack) = { def dataTag(stack: ItemStack) = Item.dataTag(stack)
protected def isOneOf(stack: ItemStack, items: common.item.Delegate*) =
stack.getItem == Items.multi && (Items.multi.subItem(stack) match {
case None => false
case Some(subItem) => items.contains(subItem)
})
}
object Item {
def dataTag(stack: ItemStack) = {
if (!stack.hasTagCompound) { if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound("tag")) stack.setTagCompound(new NBTTagCompound("tag"))
} }
@ -16,10 +26,4 @@ trait Item extends api.driver.Item {
} }
nbt.getCompoundTag(Settings.namespace + "data") nbt.getCompoundTag(Settings.namespace + "data")
} }
}
protected def isOneOf(stack: ItemStack, items: common.item.Delegate*) =
stack.getItem == Items.multi && (Items.multi.subItem(stack) match {
case None => false
case Some(subItem) => items.contains(subItem)
})
}

View File

@ -4,6 +4,7 @@ import li.cil.oc.Items
import li.cil.oc.api.driver import li.cil.oc.api.driver
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object Memory extends Item with driver.Memory { object Memory extends Item with driver.Memory {
def amount(stack: ItemStack) = if (stack.getItem == Items.multi) Items.multi.subItem(stack) match { def amount(stack: ItemStack) = if (stack.getItem == Items.multi) Items.multi.subItem(stack) match {
@ -13,7 +14,7 @@ object Memory extends Item with driver.Memory {
def worksWith(stack: ItemStack) = isOneOf(stack, Items.ram3, Items.ram1, Items.ram2) def worksWith(stack: ItemStack) = isOneOf(stack, Items.ram3, Items.ram1, Items.ram2)
def createEnvironment(stack: ItemStack, container: AnyRef) = null def createEnvironment(stack: ItemStack, container: MCTileEntity) = null
def slot(stack: ItemStack) = Slot.Memory def slot(stack: ItemStack) = Slot.Memory
} }

View File

@ -4,11 +4,12 @@ import li.cil.oc.Items
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object NetworkCard extends Item { object NetworkCard extends Item {
def worksWith(stack: ItemStack) = isOneOf(stack, Items.lan) def worksWith(stack: ItemStack) = isOneOf(stack, Items.lan)
override def createEnvironment(stack: ItemStack, container: AnyRef) = new component.NetworkCard() override def createEnvironment(stack: ItemStack, container: MCTileEntity) = new component.NetworkCard()
def slot(stack: ItemStack) = Slot.Card def slot(stack: ItemStack) = Slot.Card
} }

View File

@ -6,11 +6,12 @@ import li.cil.oc.api.driver.Slot
import li.cil.oc.common.tileentity.{BundledRedstone, Redstone} import li.cil.oc.common.tileentity.{BundledRedstone, Redstone}
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object RedstoneCard extends Item { object RedstoneCard extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.rs) override def worksWith(stack: ItemStack) = isOneOf(stack, Items.rs)
override def createEnvironment(stack: ItemStack, container: AnyRef) = override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
container match { container match {
case redstone: BundledRedstone if isBundledRedstoneModAvailable => new component.BundledRedstoneCard(redstone) case redstone: BundledRedstone if isBundledRedstoneModAvailable => new component.BundledRedstoneCard(redstone)
case redstone: Redstone => new component.RedstoneCard(redstone) case redstone: Redstone => new component.RedstoneCard(redstone)

View File

@ -4,16 +4,13 @@ import li.cil.oc.Items
import li.cil.oc.api.driver.Slot import li.cil.oc.api.driver.Slot
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.{TileEntity => MCTileEntity}
object WirelessNetworkCard extends Item { object WirelessNetworkCard extends Item {
def worksWith(stack: ItemStack) = isOneOf(stack, Items.wlan) def worksWith(stack: ItemStack) = isOneOf(stack, Items.wlan)
override def createEnvironment(stack: ItemStack, container: AnyRef) = override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
container match { if (container != null) new component.WirelessNetworkCard(container) else null
case owner: TileEntity => new component.WirelessNetworkCard(owner)
case _ => null
}
def slot(stack: ItemStack) = Slot.Card def slot(stack: ItemStack) = Slot.Card
} }

View File

@ -66,7 +66,7 @@ object FileSystem extends api.detail.FileSystemAPI {
asManagedEnvironment(fileSystem, null: Label) asManagedEnvironment(fileSystem, null: Label)
private class ReadOnlyLabel(val label: String) extends Label { private class ReadOnlyLabel(val label: String) extends Label {
def setLabel(value: String) = throw new Exception("label is read only") def setLabel(value: String) = throw new IllegalArgumentException("label is read only")
def getLabel = label def getLabel = label
} }