| package li.cil.oc.api.network; |
| |
| /** |
| * Interface for interacting with networks. |
| * <p/> |
| * Computers and components form ad-hoc "networks" when placed next to each |
| * other. They allow computers to communicate with the components attached to |
| * them (and nodes amongst each other) by using the network as an index |
| * structure. |
| * <p/> |
| * There are three types of nodes: |
| * <ul> |
| * <li>{@link Node}, the most basic form.</li> |
| * <li>{@link Component}, used to expose callbacks to Lua.</li> |
| * <li>{@link Connector}, used for consuming of producing energy.</li> |
| * </ul> |
| * <p/> |
| * See <tt>Node</tt> for more details on the behavior of single nodes, and in |
| * particular how nodes represented by tile entities should be added. |
| * <p/> |
| * Another important concept of node networks is reachability and visibility, |
| * see {@link Visibility}. |
| * <p/> |
| * Note that network access in general is <em>not</em> thread safe! Networks |
| * should only be accessed from the main server thread. The exception are the |
| * connector nodes, which can be used to consume or produce energy from other |
| * threads. |
| * <p/> |
| * IMPORTANT: do *not* implement this interface yourself and create |
| * instances of your own network implementation; this will lead to |
| * incompatibilities with the built-in network implementation (which can only |
| * merge with other networks of its own type). Always use the methods provided |
| * in {@link li.cil.oc.api.Network} to create and join networks. |
| */ |
| public interface Network { |
| /** |
| * Adds a new node connection in the network. |
| * <p/> |
| * This is used by nodes to join an existing network. At least one of the two |
| * nodes must already be in the network. If one of the nodes is not yet in the |
| * network, it will be added to the network. If both nodes are already in the |
| * network only the connection between the two nodes is added. If one of the |
| * nodes is not in this network but in another network, the networks will be |
| * merged. |
| * <p/> |
| * This way of adding nodes is used to build an internal graph to allow |
| * properly splitting networks when nodes are removed. |
| * |
| * @param nodeA the first node. |
| * @param nodeB the second node. |
| * @return true if a new connection between the two nodes was added; false if |
| * the connection already existed. |
| * @throws IllegalArgumentException if neither node is in this network. |
| */ |
| boolean connect(Node nodeA, Node nodeB); |
| |
| /** |
| * Removes a node connection in the network. |
| * <p/> |
| * Both nodes must be part of this network. |
| * <p/> |
| * This can be useful for cutting connections that depend on some condition |
| * that does not involve the nodes' actual existence in the network, such as |
| * the distance between two nodes, for example (think access points of a |
| * wireless network). |
| * |
| * @param nodeA the first node. |
| * @param nodeB the second node. |
| * @return true if the connection was cut; false if there was none. |
| * @throws IllegalArgumentException if the nodes are not in this network. |
| */ |
| boolean disconnect(Node nodeA, Node nodeB); |
| |
| /** |
| * Removes a node from the network. |
| * <p/> |
| * This should be called by nodes when they are destroyed (e.g. in |
| * {@link net.minecraft.tileentity.TileEntity#invalidate()}) or unloaded |
| * (e.g. in {@link net.minecraft.tileentity.TileEntity#onChunkUnload()}). |
| * Removing the node can lead to one or more new networks if it was the a |
| * bridge node, i.e. the only node connecting the resulting networks. |
| * |
| * @param node the node to remove from the network. |
| * @return true if the node was removed; false if it wasn't in the network. |
| */ |
| boolean remove(Node node); |
| |
| // ----------------------------------------------------------------------- // |
| |
| /** |
| * Get the network node with the specified address. |
| * |
| * @param address the address of the node to get. |
| * @return the node with that address. |
| */ |
| Node node(String address); |
| |
| /** |
| * The list of all nodes in this network. |
| * |
| * @return the list of nodes in this network. |
| */ |
| Iterable<Node> nodes(); |
| |
| /** |
| * The list of addressed nodes in the network visible to the specified node. |
| * <p/> |
| * This does <em>not</em> include nodes with a visibility of <tt>None</tt> |
| * or a visibility of <tt>Neighbors</tt> when there is no direct connection |
| * between that node and the reference node. |
| * <p/> |
| * This does <em>not</em> include the node itself. |
| * <p/> |
| * This can be useful when performing a delayed initialization of a node. |
| * For example, computers will use this when starting up to generate |
| * <tt>component_added</tt> signals for all visible components in the |
| * network. |
| * |
| * @param reference the node to get the visible other nodes for. |
| * @return the nodes visible to the specified node. |
| */ |
| Iterable<Node> nodes(Node reference); |
| |
| /** |
| * The list of nodes the specified node is directly connected to. |
| * <p/> |
| * This <em>does</em> include nodes with a visibility of <tt>None</tt>. |
| * <p/> |
| * This does <em>not</em> include the node itself. |
| * <p/> |
| * This can be used to verify arguments for components that should only work |
| * for other components that are directly connected to them, for example. |
| * |
| * @param node the node to get the neighbors for. |
| * @return a list of nodes the node is directly connect to. |
| * @throws IllegalArgumentException if the specified node is not in this network. |
| */ |
| Iterable<Node> neighbors(Node node); |
| |
| // ----------------------------------------------------------------------- // |
| |
| /** |
| * Sends a message to the node with the specified address. |
| * <p/> |
| * If the target node with that address has a visibility of <tt>None</tt> |
| * the message will <em>not</em> be delivered to that node. If the target |
| * node with that address has a visibility of <tt>Neighbors</tt> and the |
| * source node is not directly connected to the target the message will |
| * <em>not</em> be delivered to that node. |
| * <p/> |
| * Messages should have a unique name to allow differentiating them when |
| * handling them in a network node. For example, computers will try to parse |
| * messages named <tt>computer.signal</tt> by converting the message data to |
| * a signal and inject that signal into the Lua VM, so no message not used |
| * for this purpose should be named <tt>computer.signal</tt>. |
| * |
| * @param source the node that sends the message. |
| * @param target the id of the node to send the message to. |
| * @param name the name of the message. |
| * @param data the message to send. |
| * @throws IllegalArgumentException if the source node is not in this network. |
| */ |
| void sendToAddress(Node source, String target, String name, Object... data); |
| |
| /** |
| * Sends a message to all addressed, visible neighbors of the source node. |
| * <p/> |
| * Targets are determined using {@link #neighbors(Node)} and additionally |
| * filtered for reachability (so that unreachable nodes are ignored). |
| * <p/> |
| * Messages should have a unique name to allow differentiating them when |
| * handling them in a network node. For example, computers will try to parse |
| * messages named <tt>computer.signal</tt> by converting the message data to |
| * a signal and inject that signal into the Lua VM, so no message not used |
| * for this purpose should be named <tt>computer.signal</tt>. |
| * |
| * @param source the node that sends the message. |
| * @param name the name of the message. |
| * @param data the message to send. |
| * @throws IllegalArgumentException if the source node is not in this network. |
| * @see `neighbors` |
| */ |
| void sendToNeighbors(Node source, String name, Object... data); |
| |
| /** |
| * Sends a message to all addressed nodes reachable to the source node. |
| * <p/> |
| * Targets are determined using {@link #nodes(Node)}. |
| * <p/> |
| * Messages should have a unique name to allow differentiating them when |
| * handling them in a network node. For example, computers will try to parse |
| * messages named <tt>computer.signal</tt> by converting the message data to |
| * a signal and inject that signal into the Lua VM, so no message not used |
| * for this purpose should be named <tt>computer.signal</tt>. |
| * |
| * @param source the node that sends the message. |
| * @param data the message to send. |
| * @throws IllegalArgumentException if the source node is not in this network. |
| * @see {@link #nodes(Node)} |
| */ |
| void sendToReachable(Node source, String name, Object... data); |
| |
| /** |
| * Sends a message to all addressed nodes visible to the source node. |
| * <p/> |
| * Targets are determined using {@link #nodes(Node)} and additionally |
| * filtered for visibility (so that invisible nodes are ignored). |
| * <p/> |
| * Note that messages sent this way are <em>only</em> delivered to other |
| * components. The message will <em>not</em> be delivered to normal nodes. |
| * <p/> |
| * Messages should have a unique name to allow differentiating them when |
| * handling them in a network node. For example, computers will try to parse |
| * messages named <tt>computer.signal</tt> by converting the message data to |
| * a signal and inject that signal into the Lua VM, so no message not used |
| * for this purpose should be named <tt>computer.signal</tt>. |
| * |
| * @param source the node that sends the message. |
| * @param data the message to send. |
| * @throws IllegalArgumentException if the source node is not in this network. |
| * @see {@link #nodes(Node)} |
| * @see {@link Component#canBeSeenFrom(Node)} |
| */ |
| void sendToVisible(Node source, String name, Object... data); |
| } |