| package li.cil.oc.api.prefab; |
| |
| import li.cil.oc.api.Network; |
| import li.cil.oc.api.network.Environment; |
| import li.cil.oc.api.network.Message; |
| import li.cil.oc.api.network.Node; |
| import li.cil.oc.api.network.Visibility; |
| import net.minecraft.nbt.NBTTagCompound; |
| import net.minecraft.tileentity.TileEntity; |
| |
| /** |
| * TileEntities can implement the {@link li.cil.oc.api.network.Environment} |
| * interface to allow them to interact with the component network, by providing |
| * a {@link li.cil.oc.api.network.Node} and connecting it to said network. |
| * <p/> |
| * Nodes in such a network can communicate with each other, or just use the |
| * network as an index structure to find other nodes connected to them. |
| */ |
| @SuppressWarnings("UnusedDeclaration") |
| public abstract class TileEntityEnvironment extends TileEntity implements Environment { |
| // See constructor. |
| protected Node node; |
| |
| // See updateEntity(). |
| protected boolean addedToNetwork = false; |
| |
| /** |
| * This expects a node that is used to represent this tile entity. |
| * <p/> |
| * You must only create new nodes using the factory method in the network |
| * API, {@link li.cil.oc.api.Network#newNode(Environment, Visibility)}. |
| * <p/> |
| * For example: |
| * <pre> |
| * // The first parameters to newNode is the host() of the node, which will |
| * // usually be this tile entity. The second one is it's reachability, |
| * // which determines how other nodes in the same network can query this |
| * // node. See {@link li.cil.oc.api.network.Network#nodes(li.cil.oc.api.network.Node)}. |
| * super(Network.newNode(this, Visibility.Network) |
| * // This call allows the node to consume energy from the |
| * // component network it is in and act as a consumer, or to |
| * // inject energy into that network and act as a producer. |
| * // If you do not need energy remove this call. |
| * .withConnector() |
| * // This call marks the tile entity as a component. This means you |
| * // can mark methods in it using the {@link li.cil.oc.api.network.LuaCallback} |
| * // annotation, making them callable from Lua. The first parameter |
| * // is the name by which the component will be known in Lua, in this |
| * // case it could be accessed as <tt>component.example</tt>. The |
| * // second parameter is the component's visibility. This is like the |
| * // node's reachability, but only applies to Lua. For example, |
| * // network cards can only be <em>seen</em> by the computer they're |
| * // installed in, but can be <em>reached</em> by all other network |
| * // cards in the same network. |
| * // If you do not need Lua callbacks remove this call. |
| * .withComponent("example", Visibility.Neighbors) |
| * // Finalizes the construction of the node and returns it. |
| * .create()); |
| * </pre> |
| */ |
| protected TileEntityEnvironment(Node node) { |
| this.node = node; |
| } |
| |
| // ----------------------------------------------------------------------- // |
| |
| @Override |
| public Node node() { |
| return node; |
| } |
| |
| @Override |
| public void onConnect(Node node) { |
| // This is called when the call to Network.joinOrCreateNetwork(this) in |
| // updateEntity was successful, in which case `node == this`. |
| // This is also called for any other node that gets connected to the |
| // network our node is in, in which case `node` is the added node. |
| // If our node is added to an existing network, this is called for each |
| // node already in said network. |
| } |
| |
| @Override |
| public void onDisconnect(Node node) { |
| // This is called when this node is removed from its network when the |
| // tile entity is removed from the world (see onChunkUnload() and |
| // invalidate()), in which case `node == this`. |
| // This is also called for each other node that gets removed from the |
| // network our node is in, in which case `node` is the removed node. |
| // If a net-split occurs this is called for each node that is no longer |
| // connected to our node. |
| } |
| |
| @Override |
| public void onMessage(Message message) { |
| // This is used to deliver messages sent via node.sendToXYZ. Handle |
| // messages at your own discretion. If you do not wish to handle a |
| // message you should *not* throw an exception, though. |
| } |
| |
| // ----------------------------------------------------------------------- // |
| |
| @Override |
| public void updateEntity() { |
| super.updateEntity(); |
| // On the first update, try to add our node to nearby networks. We do |
| // this in the update logic, not in validate() because we need to access |
| // neighboring tile entities, which isn't possible in validate(). |
| // We could alternatively check node != null && node.network() == null, |
| // but this has somewhat better performance, and makes it clearer. |
| if (!addedToNetwork) { |
| addedToNetwork = true; |
| Network.joinOrCreateNetwork(this); |
| } |
| } |
| |
| @Override |
| public void onChunkUnload() { |
| super.onChunkUnload(); |
| // Make sure to remove the node from its network when its environment, |
| // meaning this tile entity, gets unloaded. |
| if (node != null) node.remove(); |
| } |
| |
| @Override |
| public void invalidate() { |
| super.invalidate(); |
| // Make sure to remove the node from its network when its environment, |
| // meaning this tile entity, gets unloaded. |
| if (node != null) node.remove(); |
| } |
| |
| // ----------------------------------------------------------------------- // |
| |
| @Override |
| public void readFromNBT(NBTTagCompound nbt) { |
| super.readFromNBT(nbt); |
| // The host check may be superfluous for you. It's just there to allow |
| // some special cases, where getNode() returns some node managed by |
| // some other instance (for example when you have multiple internal |
| // nodes in this tile entity). |
| if (node != null && node.host() == this) { |
| // This restores the node's address, which is required for networks |
| // to continue working without interruption across loads. If the |
| // node is a power connector this is also required to restore the |
| // internal energy buffer of the node. |
| node.load(nbt.getCompoundTag("oc:node")); |
| } |
| } |
| |
| @Override |
| public void writeToNBT(NBTTagCompound nbt) { |
| super.writeToNBT(nbt); |
| // See readFromNBT() regarding host check. |
| if (node != null && node.host() == this) { |
| NBTTagCompound nodeNbt = new NBTTagCompound(); |
| node.save(nodeNbt); |
| nbt.setCompoundTag("oc:node", nodeNbt); |
| } |
| } |
| } |