blob: 6c67d1662e17ff77c4983ab1699cfb3c50bc3ca5 [file] [log] [blame] [raw]
package li.cil.oc.api.machine;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This annotation can be used for methods in an {@link li.cil.oc.api.network.Environment} to mark
* them for exposure to computers.
* <p/>
* Any method exposed like this can be enumerated and called from a computer
* that can see the node of the environment.
* <p/>
* Note that methods annotated with this interface must have the following
* signature:
* <pre>
* Object[] f(Context context, Arguments arguments) throws Exception;
* </pre>
* <p/>
* The method may return <tt>null</tt> in case it doesn't wish return anything,
* which is functionally equivalent to returning an empty array.
* <p/>
* To raise an error from your callback, simply throw an exception. The
* convention for Lua is to return (null, "reason") for 'soft' errors, i.e.
* errors that are no fault of the caller. For example, passing invalid
* arguments will generate an exception, requesting information and the lookup
* of said information failing should not.
*
* @see Context
* @see li.cil.oc.api.machine.Arguments
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Callback {
/**
* The name under which to make the callback available.
* <p/>
* This defaults to the name of the annotated method if left empty.
*/
String value() default "";
/**
* Whether this function may be called directly from the computer's executor
* thread instead of from the server thread.
* <p/>
* You will have to ensure anything your callback does is thread safe when
* setting this to <tt>true</tt>. Use this for minor lookups, for example.
* This is mainly intended to allow functions to perform faster than when
* called 'synchronously' (where the call takes at least one server tick).
* <p/>
* Keep in mind that the node {@link li.cil.oc.api.network.Network} is <em>not</em> thread safe!
* Be sure you know what you're doing if you're working with a node's
* network in a direct callback.
* <p/>
* An exception to that rule is {@link li.cil.oc.api.network.Connector#changeBuffer(double)},
* which is synchronized, so you can consume/produce power in direct calls.
*/
boolean direct() default false;
/**
* The maximum number of direct calls that may be performed on this
* component in a single <em>tick</em> on a tier two computer.
* <p/>
* This can be used to throttle call speed. For example, this is used by
* graphics cards to limit the amount of net traffic can be generated by
* updating the screen they are bound to.
* <p/>
* You should generally apply a limit if the callback allocates persisting
* memory (i.e. memory that isn't freed once the call returns), sends
* network messages, or uses any other kind of resource for which it'd be
* bad if it were to be used from user programs in an unchecked, unregulated
* manner.
* <p/>
* Note that the limit does <em>not</em> apply when the method is invoked
* via a direct call to {@link li.cil.oc.api.network.Component#invoke(String, Context, Object...)}
* from the host side. Also, this limit is per-computer, so the method may
* be invoked more often than this per tick, if different computers call it.
* <p/>
* Note that the interpretation of this value changed a bit in OC 1.4.
* Before, it was the actual number of calls that could be performed on
* the component per tick. Now it's more of a general cost value: for each
* direct call a computer makes, <tt>1/limit</tt> is subtracted from the
* computer's call budget. This budget may vary between computers, for
* example, tier three computers have a higher call budget than tier two
* computers.
*/
int limit() default Integer.MAX_VALUE;
/**
* A documentation string that is made available to the computers the
* component this callback belongs to is connected to. This allows for
* ingame documentation of callbacks.
* <p/>
* You may want to give a short description of what a method does here, but
* more importantly you should document the expected parameters and return
* type here.
* <p/>
* <em>Important</em>: the recommended format is either<br/>
* <tt>function(arg:type[, optionArg:type]):resultType -- Description.</tt><br/>
* or<br/>
* <tt>function(arg:type[, optionArg:type]):resultType; Description.</tt><br/>
* where the argument list can be of any format (as long as it doesn't contain
* further braces), and the return type is optional. These two formats are
* recognized by OC's NEI component documentation plugin. If you use a
* different format, the doc string will be used as-is.
*/
String doc() default "";
/**
* Whether this callback should work like a getter.
* <p/>
* Callbacks that are getters do not appear as methods on a component's
* proxy. Instead they are accessed as fields, for example in Lua via the
* proxy's <tt>__index</tt> metamethod, with its only parameter being the
* accessed key.
* <p/>
* Note: if you wish to have a field that is read/write, that is you need
* both a getter and a setter, you have to implement them in the same
* method. This a limitation due to callback names being unique. You can
* differentiate between contexts by checking the number of arguments.
* <p/>
* <em>Important</em>: this only works in environments (for components),
* it does <em>not</em> work for userdata (<tt>Value</tt> objects). For
* userdata, use the <tt>apply</tt> method instead.
*/
boolean getter() default false;
/**
* Whether this callback should work like a setter.
* <p/>
* Callbacks that are setters do not appear as methods on a component's
* proxy. Instead they are accessed as fields, for example in Lua via the
* proxy's <tt>__newindex</tt> metamethod, with its only two parameters
* being the accessed key and the new value.
* <p/>
* Note: if you wish to have a field that is read/write, that is you need
* both a getter and a setter, you have to implement them in the same
* method. This a limitation due to callback names being unique. You can
* differentiate between contexts by checking the number of arguments.
* <p/>
* <em>Important</em>: this only works in environments (for components),
* it does <em>not</em> work for userdata (<tt>Value</tt> objects). For
* userdata, use the <tt>unapply</tt> method instead.
*/
boolean setter() default false;
}