mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 03:05:30 -04:00
started to work on moving architecture and machine interfaces to the public api
This commit is contained in:
parent
d6b0eb9cae
commit
bb9f073fc9
45
src/main/java/li/cil/oc/api/Machine.java
Normal file
45
src/main/java/li/cil/oc/api/Machine.java
Normal file
@ -0,0 +1,45 @@
|
||||
package li.cil.oc.api;
|
||||
|
||||
import li.cil.oc.api.detail.MachineAPI;
|
||||
import li.cil.oc.api.machine.Architecture;
|
||||
import li.cil.oc.api.machine.Owner;
|
||||
|
||||
/**
|
||||
* This API is intended for people who would like to implement custom computer
|
||||
* blocks or anything else hosting a computer.
|
||||
* <p/>
|
||||
* It also allows registering new {@link li.cil.oc.api.machine.Architecture}s,
|
||||
* which are implementations of specific languages (e.g. assembler). The built-
|
||||
* in ones are available as static fields in this class.
|
||||
* <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 Machine {
|
||||
/**
|
||||
* The built-in architecture that uses the native Lua implementation.
|
||||
*/
|
||||
public static Class<? extends Architecture> NativeLuaArchitecture = null;
|
||||
|
||||
/**
|
||||
* The built-in architecture that uses the LuaJ Lua implementation.
|
||||
*/
|
||||
public static Class<? extends Architecture> JavaLuaArchitecture = null;
|
||||
|
||||
void add(Class<? extends Architecture> architecture) {
|
||||
if (instance != null) instance.add(architecture);
|
||||
}
|
||||
|
||||
li.cil.oc.server.component.machine.Machine create(Owner owner, Class<? extends Architecture> architecture) {
|
||||
if (instance != null) return instance.create(owner, architecture);
|
||||
return null;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private Machine() {
|
||||
}
|
||||
|
||||
public static MachineAPI instance = null;
|
||||
}
|
@ -8,21 +8,118 @@ import li.cil.oc.api.fs.Label;
|
||||
import li.cil.oc.api.network.ManagedEnvironment;
|
||||
|
||||
public interface FileSystemAPI {
|
||||
/**
|
||||
* Creates a new file system based on the location of a class.
|
||||
* <p/>
|
||||
* This can be used to wrap a folder in the assets folder of your mod's JAR.
|
||||
* The actual path is built like this:
|
||||
* <pre>"/assets/" + domain + "/" + root</pre>
|
||||
* <p/>
|
||||
* 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
|
||||
* file system, this will create a read-only file system first trying from
|
||||
* the actual location of the class file, and failing that by searching the
|
||||
* class path (i.e. it'll look for a path constructed as described above).
|
||||
* <p/>
|
||||
* If the specified path cannot be located, the creation fails and this
|
||||
* returns <tt>null</tt>.
|
||||
*
|
||||
* @param clazz the class whose containing JAR to wrap.
|
||||
* @param domain the domain, usually your mod's ID.
|
||||
* @param root an optional subdirectory.
|
||||
* @return a file system wrapping the specified folder.
|
||||
*/
|
||||
FileSystem fromClass(Class<?> clazz, String domain, String root);
|
||||
|
||||
/**
|
||||
* Creates a new <em>writable</em> file system in the save folder.
|
||||
* <p/>
|
||||
* 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-
|
||||
* folder of the save folder. The actual path is built like this:
|
||||
* <pre>"saves/" + WORLD_NAME + "/opencomputers/" + root</pre>
|
||||
* The first part may differ, in particular for servers.
|
||||
* <p/>
|
||||
* Usually the name will be the address of the node used to represent the
|
||||
* file system.
|
||||
* <p/>
|
||||
* Note that by default file systems are "buffered", meaning that any
|
||||
* changes made to them are only saved to disk when the world is saved. This
|
||||
* ensured that the file system contents do not go "out of sync" when the
|
||||
* game crashes, but introduces additional memory overhead, since all files
|
||||
* in the file system have to be kept in memory.
|
||||
*
|
||||
* @param root the name of the file system.
|
||||
* @param capacity the amount of space in bytes to allow being used.
|
||||
* @param buffered whether data should only be written to disk when saving.
|
||||
* @return a file system wrapping the specified folder.
|
||||
*/
|
||||
FileSystem fromSaveDirectory(String root, long capacity, boolean buffered);
|
||||
|
||||
/**
|
||||
* Creates a new <em>writable</em> file system that resides in memory.
|
||||
* <p/>
|
||||
* Any contents created and written on this file system will be lost when
|
||||
* the node is removed from the network.
|
||||
* <p/>
|
||||
* This is used for computers' <tt>/tmp</tt> mount, for example.
|
||||
*
|
||||
* @param capacity the capacity of the file system.
|
||||
* @return a file system residing in memory.
|
||||
*/
|
||||
FileSystem fromMemory(long capacity);
|
||||
|
||||
/**
|
||||
* Creates a new file system based on a read-only ComputerCraft mount.
|
||||
*
|
||||
* @param mount the mount to wrap with a file system.
|
||||
* @return a file system wrapping the specified mount.
|
||||
*/
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
FileSystem fromComputerCraft(IMount mount);
|
||||
|
||||
/**
|
||||
* Creates a new file system based on a read-write ComputerCraft mount.
|
||||
*
|
||||
* @param mount the mount to wrap with a file system.
|
||||
* @return a file system wrapping the specified mount.
|
||||
*/
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
FileSystem fromComputerCraft(IWritableMount mount);
|
||||
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fs, Label label);
|
||||
/**
|
||||
* Creates a network node that makes the specified file system available via
|
||||
* the common file system driver.
|
||||
* <p/>
|
||||
* This can be useful for providing some data if you don't wish to implement
|
||||
* 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
|
||||
* it. In that case you will have to forward any disk driver messages to the
|
||||
* node, though.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the label of the file system.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fileSystem, Label label);
|
||||
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fs, String label);
|
||||
/**
|
||||
* Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)},
|
||||
* but creates a read-only label initialized to the specified value.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the read-only label of the file system.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fileSystem, String label);
|
||||
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fs);
|
||||
/**
|
||||
* Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label)},
|
||||
* but creates an unlabeled file system (i.e. the label can neither be read
|
||||
* nor written).
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fileSystem);
|
||||
}
|
11
src/main/java/li/cil/oc/api/detail/MachineAPI.java
Normal file
11
src/main/java/li/cil/oc/api/detail/MachineAPI.java
Normal file
@ -0,0 +1,11 @@
|
||||
package li.cil.oc.api.detail;
|
||||
|
||||
import li.cil.oc.api.machine.Architecture;
|
||||
import li.cil.oc.api.machine.Owner;
|
||||
import li.cil.oc.server.component.machine.Machine;
|
||||
|
||||
public interface MachineAPI {
|
||||
void add(Class<? extends Architecture> architecture);
|
||||
|
||||
Machine create(Owner owner, Class<? extends Architecture> architecture);
|
||||
}
|
@ -6,9 +6,71 @@ import li.cil.oc.api.network.Visibility;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
public interface NetworkAPI {
|
||||
/**
|
||||
* Tries to add a tile entity's network node(s) at the specified coordinates
|
||||
* 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.
|
||||
*/
|
||||
void joinOrCreateNetwork(TileEntity tileEntity);
|
||||
|
||||
/**
|
||||
* Creates a new network with the specified node as its initial node.
|
||||
* <p/>
|
||||
* This can be used to create networks that are not bound to any tile
|
||||
* entity. For example, this is used to create the internal networks of
|
||||
* robots.
|
||||
*
|
||||
* @param node the node to create the network for.
|
||||
* @throws IllegalArgumentException if the node already is in a network.
|
||||
*/
|
||||
void joinNewNetwork(Node node);
|
||||
|
||||
/**
|
||||
* Factory function for creating new nodes.
|
||||
* <p/>
|
||||
* Use this to create a node for your environment (e.g. tile entity). This
|
||||
* will return a builder that can be used to further specialize the node,
|
||||
* making it either a component node (for callbacks), a connector node
|
||||
* (for power interaction) or both.
|
||||
* <p/>
|
||||
* Example use:
|
||||
* <pre>
|
||||
* class YourThing extends TileEntity implements Environment {
|
||||
* private ComponentConnector node_ =
|
||||
* api.Network.newNode(this, Visibility.Network).
|
||||
* withComponent("your_thing").
|
||||
* withConnector(32).
|
||||
* create();
|
||||
*
|
||||
* public Node node() { return node_; }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
* </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 computers. 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 user programs running on the computer the
|
||||
* card installed in can see interact with it).
|
||||
*
|
||||
* @param host the environment the node is created for.
|
||||
* @param reachability the reachability of the node.
|
||||
* @return a new node builder.
|
||||
*/
|
||||
Builder.NodeBuilder newNode(Environment host, Visibility reachability);
|
||||
}
|
@ -15,7 +15,7 @@ public interface Processor extends Item {
|
||||
* The additional number of components supported if this processor is
|
||||
* installed in the server.
|
||||
*
|
||||
* @param stack
|
||||
* @param stack the processor to get the number of supported components for.
|
||||
* @return the number of additionally supported components.
|
||||
*/
|
||||
int supportedComponents(ItemStack stack);
|
||||
|
136
src/main/java/li/cil/oc/api/machine/Architecture.java
Normal file
136
src/main/java/li/cil/oc/api/machine/Architecture.java
Normal file
@ -0,0 +1,136 @@
|
||||
package li.cil.oc.api.machine;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* This interface abstracts away any language specific details for the Machine.
|
||||
* <p/>
|
||||
* This allows the introduction of other languages, e.g. computers that run
|
||||
* assembly or some other language interpreter. The two architectures included
|
||||
* in OpenComputers are the native Lua architecture (using native LuaC) and the
|
||||
* Java Lua architecture (using LuaJ).
|
||||
*/
|
||||
public interface Architecture {
|
||||
/**
|
||||
* A display friendly name of the architecture,
|
||||
* @return
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Used to check if the machine is fully initialized. If this is false no
|
||||
* signals for detected components will be generated. Avoids duplicate
|
||||
* signals if <tt>component_added</tt> signals are generated in the
|
||||
* language's startup script, for already present components (see Lua's
|
||||
* init.lua script).
|
||||
* <p/>
|
||||
* This is also used to check whether limits on direct calls should be
|
||||
* enforced or not - this allows a quick boot phase in the language's
|
||||
* kernel logic before switching to business-as-usual.
|
||||
*
|
||||
* @return whether the machine is fully initialized.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* This is called when the amount of memory in the machine may have changed.
|
||||
* This is usually triggered by the owner when its composition changes. For
|
||||
* example this is called from computer cases' onInventoryChanged method.
|
||||
*/
|
||||
void recomputeMemory();
|
||||
|
||||
/**
|
||||
* Called when a machine starts up. Used to (re-)initialize the underlying
|
||||
* architecture logic. For example, for Lua this creates a new Lua state.
|
||||
* <p/>
|
||||
* This also sets up any built-in APIs for the underlying language, such as
|
||||
* querying available memory, listing and interacting with components and so
|
||||
* on. If this returns <tt>false</tt> the machine fails to start.
|
||||
* <p/>
|
||||
* Note that the owning machine has not necessarily been connected to a
|
||||
* network when this is called, in case this is called from the machine's
|
||||
* load logic. Use {@link #onConnect()} for additional initialization that
|
||||
* depends on a node network (such as connecting a ROM file system).
|
||||
*
|
||||
* @return whether the architecture was initialized successfully.
|
||||
*/
|
||||
boolean init();
|
||||
|
||||
/**
|
||||
* Called when a machine stopped. Used to clean up any handles, memory and
|
||||
* so on. For example, for Lua this destroys the Lua state.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Performs a synchronized call initialized in a previous call to
|
||||
* {@link #runThreaded(boolean)}.
|
||||
* <p/>
|
||||
* This method is invoked from the main server thread, meaning it is safe
|
||||
* to interact with the world without having to perform manual
|
||||
* synchronization.
|
||||
* <p/>
|
||||
* This method is expected to leave the architecture in a state so it is
|
||||
* prepared to next be called with <tt>runThreaded(true)</tt>. For example,
|
||||
* the Lua architecture will leave the results of the synchronized call on
|
||||
* the stack so they can be further processed in the next call to
|
||||
* <tt>runThreaded</tt>.
|
||||
*/
|
||||
void runSynchronized();
|
||||
|
||||
/**
|
||||
* Continues execution of the machine. The first call may be used to
|
||||
* initialize the machine (e.g. for Lua we load the libraries in the first
|
||||
* call so that the computers boot faster). After that the architecture
|
||||
* <em>should</em> return <tt>true</tt> from {@link #isInitialized()}.
|
||||
* <p/>
|
||||
* The resumed state is either a return from a synchronized call, when a
|
||||
* synchronized call has been completed (via <tt>runSynchronized</tt>), or
|
||||
* a normal yield in all other cases (sleep, interrupt, boot, ...).
|
||||
* <p/>
|
||||
* This is expected to return within a very short time, usually. For example,
|
||||
* in Lua this returns as soon as the state yields, and returns at the latest
|
||||
* when the Settings.timeout is reached (in which case it forces the state
|
||||
* to crash).
|
||||
* <p/>
|
||||
* This is expected to consume a single signal if one is present and return.
|
||||
* If returning from a synchronized call this should consume no signal.
|
||||
*
|
||||
* @param isSynchronizedReturn whether the architecture is resumed from an
|
||||
* earlier synchronized call. In the case of
|
||||
* Lua this means the results of the call are
|
||||
* now on the stack, for example.
|
||||
* @return the result of the execution. Used to determine the new state.
|
||||
*/
|
||||
ExecutionResult runThreaded(boolean isSynchronizedReturn);
|
||||
|
||||
/**
|
||||
* Called when the owning machine was connected to the component network.
|
||||
* <p/>
|
||||
* This can be useful for connecting custom file systems (read only memory)
|
||||
* in case {@link #init()} was called from the machine's load logic (where
|
||||
* it was not yet connected to the network).
|
||||
*/
|
||||
void onConnect();
|
||||
|
||||
/**
|
||||
* Restores the state of this architecture as previously saved in
|
||||
* {@link #save(NBTTagCompound)}. The architecture should be in the same
|
||||
* state it was when it was saved after this, so it can be resumed from
|
||||
* whatever state the owning machine was in when it was saved.
|
||||
*
|
||||
* @param nbt the tag compound to save to.
|
||||
*/
|
||||
void load(NBTTagCompound nbt);
|
||||
|
||||
/**
|
||||
* Saves the architecture for later restoration, e.g. across games or chunk
|
||||
* unloads. Used to persist a machine's execution state. For native Lua this
|
||||
* uses the Eris library to persist the main coroutine, for example.
|
||||
* <p/>
|
||||
* Note that the tag compound is shared with the Machine.
|
||||
*
|
||||
* @param nbt the tag compound to save to.
|
||||
*/
|
||||
void save(NBTTagCompound nbt);
|
||||
}
|
66
src/main/java/li/cil/oc/api/machine/ExecutionResult.java
Normal file
66
src/main/java/li/cil/oc/api/machine/ExecutionResult.java
Normal file
@ -0,0 +1,66 @@
|
||||
package li.cil.oc.api.machine;
|
||||
|
||||
/**
|
||||
* Used by the Machine to determine the result of a call to
|
||||
* {@link Architecture#runThreaded()}.
|
||||
* <p/>
|
||||
* Do not implement this interface, only use the predefined internal classes.
|
||||
*/
|
||||
public abstract class ExecutionResult {
|
||||
/**
|
||||
* Indicates the machine may sleep for the specified number of ticks. This
|
||||
* is merely considered a suggestion. If signals are in the queue or are
|
||||
* pushed to the queue while sleeping, the sleep will be interrupted and
|
||||
* {@link Architecture#runThreaded()} will be called so that the next signal
|
||||
* is pushed.
|
||||
*/
|
||||
public static final class Sleep extends ExecutionResult {
|
||||
/**
|
||||
* The number of ticks to sleep.
|
||||
*/
|
||||
public final int ticks;
|
||||
|
||||
public Sleep(int ticks) {
|
||||
this.ticks = ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates tha the computer should shutdown or reboot.
|
||||
*/
|
||||
public static final class Shutdown extends ExecutionResult {
|
||||
/**
|
||||
* Whether to reboot. If false the computer will stop.
|
||||
*/
|
||||
public final boolean reboot;
|
||||
|
||||
public Shutdown(boolean reboot) {
|
||||
this.reboot = reboot;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that a synchronized call should be performed. The architecture
|
||||
* is expected to be in a state that allows the next call to be to
|
||||
* {@link Architecture#runSynchronized()} instead of
|
||||
* {@link Architecture#runThreaded()}. This is used to perform calls from
|
||||
* the server's main thread, to avoid threading issues when interacting with
|
||||
* other objects in the world.
|
||||
*/
|
||||
public static final class SynchronizedCall extends ExecutionResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that an error occurred and the computer should crash.
|
||||
*/
|
||||
public static final class Error extends ExecutionResult {
|
||||
/**
|
||||
* The error message.
|
||||
*/
|
||||
public final String message;
|
||||
|
||||
public Error(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
23
src/main/java/li/cil/oc/api/machine/Machine.java
Normal file
23
src/main/java/li/cil/oc/api/machine/Machine.java
Normal file
@ -0,0 +1,23 @@
|
||||
package li.cil.oc.api.machine;
|
||||
|
||||
import li.cil.oc.api.network.Context;
|
||||
import li.cil.oc.api.network.ManagedEnvironment;
|
||||
|
||||
public interface Machine extends ManagedEnvironment, Context {
|
||||
/**
|
||||
* The underlying architecture of the machine.
|
||||
* <p/>
|
||||
* This is what actually evaluates code running on the machine, where the
|
||||
* machine class itself serves as a scheduler.
|
||||
*
|
||||
* @return the architecture of this machine.
|
||||
*/
|
||||
Architecture architecture();
|
||||
|
||||
/**
|
||||
* The owner of the machine, usually a tile entity hosting the machine.
|
||||
*
|
||||
* @return the owner of the machine.
|
||||
*/
|
||||
Owner owner();
|
||||
}
|
73
src/main/java/li/cil/oc/api/machine/Owner.java
Normal file
73
src/main/java/li/cil/oc/api/machine/Owner.java
Normal file
@ -0,0 +1,73 @@
|
||||
package li.cil.oc.api.machine;
|
||||
|
||||
import li.cil.oc.api.network.Context;
|
||||
import li.cil.oc.api.network.Environment;
|
||||
import li.cil.oc.api.network.Node;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* This interface has to be implemented by 'owners' of machine instances.
|
||||
* <p/>
|
||||
* It provides some context for the machine, in particular which world it is
|
||||
* running in, to allow querying the time of day, for example.
|
||||
*/
|
||||
public interface Owner extends Context {
|
||||
/**
|
||||
* The world the machine is running in, e.g. if the owner is a tile entity
|
||||
* this is the world the tile entity lives in.
|
||||
*
|
||||
* @return the world the machine runs in.
|
||||
*/
|
||||
World world();
|
||||
|
||||
/**
|
||||
* The amount of memory (RAM) made available to the machine, in bytes.
|
||||
* <p/>
|
||||
* This is usually determined by the components installed in the owner, for
|
||||
* example the memory sticks in a computer case.
|
||||
*
|
||||
* @return the amount of memory that can be used by the machine, in bytes.
|
||||
*/
|
||||
int installedMemory();
|
||||
|
||||
/**
|
||||
* The number of components the machine can address without crashing.
|
||||
* <p/>
|
||||
* This is usually determined by the components installed in the owner, for
|
||||
* example the CPUs in a server.
|
||||
* <p/>
|
||||
* Note that the component count does <em>not</em> include file systems.
|
||||
*
|
||||
* @return the number of supported components.
|
||||
*/
|
||||
int maxComponents();
|
||||
|
||||
/**
|
||||
* This is called by the machine when its state changed (which can be
|
||||
* multiple times per actual game tick), to notify the owner that it should
|
||||
* save its state on the next world save.
|
||||
* <p/>
|
||||
* This method is called from executor threads, so it must be thread-safe.
|
||||
*/
|
||||
void markAsChanged();
|
||||
|
||||
/**
|
||||
* This is called on the owner when the machine's {@link Environment#onConnect(Node)}
|
||||
* method gets called. This can be useful for reacting to network events
|
||||
* when the owner does not have its own node (for example, computer cases
|
||||
* expose their machine's node as their own node). This callback allows it
|
||||
* to connect its components (graphics cards and the like) when it is
|
||||
* connected to a node network (when added to the world, for example).
|
||||
*
|
||||
* @param node the node that was connected to the network.
|
||||
*/
|
||||
void onMachineConnect(Node node);
|
||||
|
||||
/**
|
||||
* Like {@link #onMachineConnect(Node)}, except that this is called whenever
|
||||
* the machine's {@link Environment#onDisconnect(Node)} method is called.
|
||||
*
|
||||
* @param node the node that was disconnected from the network.
|
||||
*/
|
||||
void onMachineDisconnect(Node node);
|
||||
}
|
@ -79,7 +79,6 @@ public @interface Callback {
|
||||
* more importantly you should document the expected parameters and return
|
||||
* type here.
|
||||
* <p/>
|
||||
* TODO Actually implement for this to be available to computers...
|
||||
*/
|
||||
String doc() default "";
|
||||
}
|
||||
|
@ -37,5 +37,5 @@
|
||||
@cpw.mods.fml.common.API(
|
||||
owner = "OpenComputers|Core",
|
||||
provides = "OpenComputersAPI",
|
||||
apiVersion = "1.4.0")
|
||||
apiVersion = "1.4.1")
|
||||
package li.cil.oc.api;
|
@ -9,6 +9,7 @@ import li.cil.oc._
|
||||
import li.cil.oc.common.asm.SimpleComponentTickHandler
|
||||
import li.cil.oc.common.multipart.MultiPart
|
||||
import li.cil.oc.server.component.Keyboard
|
||||
import li.cil.oc.server.component.machine
|
||||
import li.cil.oc.server.network.Network
|
||||
import li.cil.oc.server.{TickHandler, driver, fs, network}
|
||||
import li.cil.oc.util.WirelessNetwork
|
||||
@ -26,6 +27,7 @@ class Proxy {
|
||||
|
||||
api.Driver.instance = driver.Registry
|
||||
api.FileSystem.instance = fs.FileSystem
|
||||
api.Machine.instance = machine.Machine
|
||||
api.Network.instance = network.Network
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.common.tileentity
|
||||
import cpw.mods.fml.common.Optional
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.machine.Owner
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.server.component.machine.Machine
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver}
|
||||
@ -17,7 +18,7 @@ import stargatetech2.api.bus.IBusDevice
|
||||
|
||||
// See AbstractBusAware as to why we have to define the IBusDevice here.
|
||||
@Optional.Interface(iface = "stargatetech2.api.bus.IBusDevice", modid = "StargateTech2")
|
||||
abstract class Computer(isRemote: Boolean) extends Environment with ComponentInventory with Rotatable with BundledRedstoneAware with AbstractBusAware with IBusDevice with Analyzable with Machine.Owner {
|
||||
abstract class Computer(isRemote: Boolean) extends Environment with ComponentInventory with Rotatable with BundledRedstoneAware with AbstractBusAware with IBusDevice with Analyzable with Owner {
|
||||
protected val _computer = if (isRemote) null else new Machine(this)
|
||||
|
||||
def computer = _computer
|
||||
@ -71,6 +72,10 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
case Some(component) => component
|
||||
}
|
||||
|
||||
override def onMachineConnect(node: Node) = this.onConnect(node)
|
||||
|
||||
override def onMachineDisconnect(node: Node) = this.onDisconnect(node)
|
||||
|
||||
def hasAbstractBusCard = items.exists {
|
||||
case Some(item) => computer.isRunning && driver.item.AbstractBusCard.worksWith(item)
|
||||
case _ => false
|
||||
|
@ -415,7 +415,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
override def onMachineConnect(node: Node) {
|
||||
super.onConnect(node)
|
||||
if (node == this.node) {
|
||||
computer.node.connect(buffer.node)
|
||||
@ -434,7 +434,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
}
|
||||
}
|
||||
|
||||
override def onDisconnect(node: Node) {
|
||||
override def onMachineDisconnect(node: Node) {
|
||||
super.onDisconnect(node)
|
||||
if (node == this.node) {
|
||||
buffer.node.remove()
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.server.component
|
||||
import li.cil.oc.Items
|
||||
import li.cil.oc.api.driver
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.api.machine.Owner
|
||||
import li.cil.oc.api.network.{Message, Node}
|
||||
import li.cil.oc.common.inventory.ComponentInventory
|
||||
import li.cil.oc.common.inventory.ServerInventory
|
||||
@ -14,7 +15,7 @@ import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class Server(val rack: tileentity.Rack, val number: Int) extends Machine.Owner {
|
||||
class Server(val rack: tileentity.Rack, val number: Int) extends Owner {
|
||||
val machine = new Machine(this)
|
||||
|
||||
val inventory = new NetworkedInventory()
|
||||
@ -76,9 +77,9 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Machine.Owner {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) = inventory.onConnect(node)
|
||||
override def onMachineConnect(node: Node) = inventory.onConnect(node)
|
||||
|
||||
override def onDisconnect(node: Node) = inventory.onDisconnect(node)
|
||||
override def onMachineDisconnect(node: Node) = inventory.onDisconnect(node)
|
||||
|
||||
def load(nbt: NBTTagCompound) {
|
||||
machine.load(nbt.getCompoundTag("machine"))
|
||||
|
@ -1,101 +0,0 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
/**
|
||||
* This trait abstracts away any language specific details for the Machine.
|
||||
*
|
||||
* At some point in the future this may allow us to introduce other languages,
|
||||
* e.g. computers that run assembly or non-persistent computers that use a pure
|
||||
* Java implementation of Lua.
|
||||
*/
|
||||
trait Architecture {
|
||||
/**
|
||||
* Used to check if the machine is fully initialized. If this is false no
|
||||
* signals for detected components will be generated. Avoids duplicate signals
|
||||
* if component_added signals are generated in the language's startup script,
|
||||
* for already present components (see Lua's init.lua script).
|
||||
*
|
||||
* @return whether the machine is fully initialized.
|
||||
*/
|
||||
def isInitialized: Boolean
|
||||
|
||||
/**
|
||||
* This is called when the amount of memory in the computer may have changed.
|
||||
* It is triggered by the tile entity's onInventoryChanged.
|
||||
*/
|
||||
def recomputeMemory()
|
||||
|
||||
/**
|
||||
* Performs a synchronized call initialized in a previous call to runThreaded.
|
||||
*/
|
||||
def runSynchronized()
|
||||
|
||||
/**
|
||||
* Continues execution of the machine. The first call may be used to
|
||||
* initialize the machine (e.g. for Lua we load the libraries in the first
|
||||
* call so that the computers boot faster).
|
||||
*
|
||||
* The resumed state is either Machine.State.SynchronizedReturn, when a
|
||||
* synchronized call has been completed (via runSynchronized), or
|
||||
* Machine.State.Yielded in all other cases (sleep, interrupt, boot, ...).
|
||||
*
|
||||
* This is expected to return within a very short time, usually. For example,
|
||||
* in Lua this returns as soon as the state yields, and returns at the latest
|
||||
* when the Settings.timeout is reached (in which case it forces the state
|
||||
* to crash).
|
||||
*
|
||||
* This is expected to consume a single signal if one is present and return.
|
||||
* If returning from a synchronized call this should consume no signal.
|
||||
*
|
||||
* @param enterState the state that is being resumed.
|
||||
* @return the result of the execution. Used to determine the new state.
|
||||
*/
|
||||
def runThreaded(enterState: Machine.State.Value): ExecutionResult
|
||||
|
||||
/**
|
||||
* Called when a computer starts up. Used to (re-)initialize the underlying
|
||||
* architecture logic. For example, for Lua the creates a new Lua state.
|
||||
*
|
||||
* This also sets up any built-in APIs for the underlying language, such as
|
||||
* querying available memory, listing and interacting with components and so
|
||||
* on. If this returns false the computer fails to start.
|
||||
*
|
||||
* @return whether the architecture was initialized successfully.
|
||||
*/
|
||||
def init(): Boolean
|
||||
|
||||
/**
|
||||
* Called when the owning machine was connected to the component network.
|
||||
*
|
||||
* This can be useful for connecting custom file systems (read only memory)
|
||||
* in case init() was called from the machine's load() method (where it was
|
||||
* not yet connected to the network).
|
||||
*/
|
||||
def onConnect()
|
||||
|
||||
/**
|
||||
* Called when a computer stopped. Used to clean up any handles, memory and
|
||||
* so on. For example, for Lua this destroys the Lua state.
|
||||
*/
|
||||
def close()
|
||||
|
||||
/**
|
||||
* Restores the state of this architecture as previously saved in save().
|
||||
*
|
||||
* @param nbt the tag compound to save to.
|
||||
*/
|
||||
def load(nbt: NBTTagCompound)
|
||||
|
||||
/**
|
||||
* Saves the architecture for later restoration, e.g. across games or chunk
|
||||
* unloads. Used to persist a computer's executions state. For native Lua this
|
||||
* uses the Eris library to persist the main coroutine.
|
||||
*
|
||||
* Note that the tag compound is shared with the Machine, so collisions have
|
||||
* to be avoided (see Machine.save for used keys).
|
||||
*
|
||||
* @param nbt the tag compound to save to.
|
||||
*/
|
||||
def save(nbt: NBTTagCompound)
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
/**
|
||||
* Used by the Machine to determine the result of a call to runThreaded.
|
||||
*
|
||||
* Do not implement this interface, only use the predefined classes below.
|
||||
*/
|
||||
trait ExecutionResult
|
||||
|
||||
object ExecutionResult {
|
||||
|
||||
/**
|
||||
* Indicates the machine may sleep for the specified number of ticks. This is
|
||||
* merely considered a suggestion. If signals are in the queue or are pushed
|
||||
* to the queue while sleeping, the sleep will be interrupted and runThreaded
|
||||
* will be called so that the next signal is pushed.
|
||||
*
|
||||
* @param ticks the number of ticks to sleep.
|
||||
*/
|
||||
class Sleep(val ticks: Int) extends ExecutionResult
|
||||
|
||||
/**
|
||||
* Indicates tha the computer should shutdown or reboot.
|
||||
*
|
||||
* @param reboot whether to reboot. If false the computer will stop.
|
||||
*/
|
||||
class Shutdown(val reboot: Boolean) extends ExecutionResult
|
||||
|
||||
/**
|
||||
* Indicates that a synchronized call should be performed. The architecture
|
||||
* is expected to be in a state that allows the next call to be to
|
||||
* runSynchronized instead of runThreaded. This is used to perform calls from
|
||||
* the server's main thread, to avoid threading issues when interacting with
|
||||
* other objects in the world.
|
||||
*/
|
||||
class SynchronizedCall extends ExecutionResult
|
||||
|
||||
/**
|
||||
* Indicates that an error occurred and the computer should crash.
|
||||
*
|
||||
* @param message the error message.
|
||||
*/
|
||||
class Error(val message: String) extends ExecutionResult
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
import li.cil.oc.api.FileSystem
|
||||
import li.cil.oc.api.machine.Architecture
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.{Settings, OpenComputers}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
@ -1,8 +1,8 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
import Machine.State
|
||||
import java.io.{IOException, FileNotFoundException}
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.api.machine.ExecutionResult
|
||||
import li.cil.oc.util.ScalaClosure._
|
||||
import li.cil.oc.util.{ScalaClosure, GameTimeFormatter}
|
||||
import li.cil.oc.{OpenComputers, server, Settings}
|
||||
@ -33,6 +33,8 @@ class LuaJLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def name() = "LuaJ"
|
||||
|
||||
override def isInitialized = doneWithInitRun
|
||||
|
||||
override def recomputeMemory() = memory = machine.owner.installedMemory
|
||||
@ -44,38 +46,37 @@ class LuaJLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
synchronizedCall = null
|
||||
}
|
||||
|
||||
override def runThreaded(enterState: State.Value) = {
|
||||
override def runThreaded(isSynchronizedReturn: Boolean) = {
|
||||
try {
|
||||
// Resume the Lua state and remember the number of results we get.
|
||||
val results = enterState match {
|
||||
case Machine.State.SynchronizedReturn =>
|
||||
// If we were doing a synchronized call, continue where we left off.
|
||||
val result = thread.resume(synchronizedResult)
|
||||
synchronizedResult = null
|
||||
result
|
||||
case Machine.State.Yielded =>
|
||||
if (!doneWithInitRun) {
|
||||
// We're doing the initialization run.
|
||||
val result = thread.resume(LuaValue.NONE)
|
||||
// Mark as done *after* we ran, to avoid switching to synchronized
|
||||
// calls when we actually need direct ones in the init phase.
|
||||
doneWithInitRun = true
|
||||
// We expect to get nothing here, if we do we had an error.
|
||||
if (result.narg == 1) {
|
||||
// Fake zero sleep to avoid stopping if there are no signals.
|
||||
LuaValue.varargsOf(LuaValue.TRUE, LuaValue.valueOf(0))
|
||||
}
|
||||
else {
|
||||
LuaValue.NONE
|
||||
}
|
||||
val results = if (isSynchronizedReturn) {
|
||||
// If we were doing a synchronized call, continue where we left off.
|
||||
val result = thread.resume(synchronizedResult)
|
||||
synchronizedResult = null
|
||||
result
|
||||
}
|
||||
else {
|
||||
if (!doneWithInitRun) {
|
||||
// We're doing the initialization run.
|
||||
val result = thread.resume(LuaValue.NONE)
|
||||
// Mark as done *after* we ran, to avoid switching to synchronized
|
||||
// calls when we actually need direct ones in the init phase.
|
||||
doneWithInitRun = true
|
||||
// We expect to get nothing here, if we do we had an error.
|
||||
if (result.narg == 1) {
|
||||
// Fake zero sleep to avoid stopping if there are no signals.
|
||||
LuaValue.varargsOf(LuaValue.TRUE, LuaValue.valueOf(0))
|
||||
}
|
||||
else machine.popSignal() match {
|
||||
case Some(signal) =>
|
||||
thread.resume(LuaValue.varargsOf(Array(LuaValue.valueOf(signal.name)) ++ signal.args.map(ScalaClosure.toLuaValue)))
|
||||
case _ =>
|
||||
thread.resume(LuaValue.NONE)
|
||||
else {
|
||||
LuaValue.NONE
|
||||
}
|
||||
case s => throw new AssertionError("Running computer from invalid state " + s.toString)
|
||||
}
|
||||
else machine.popSignal() match {
|
||||
case Some(signal) =>
|
||||
thread.resume(LuaValue.varargsOf(Array(LuaValue.valueOf(signal.name)) ++ signal.args.map(ScalaClosure.toLuaValue)))
|
||||
case _ =>
|
||||
thread.resume(LuaValue.NONE)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the kernel is still alive.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.api.machine.{Architecture, Owner, ExecutionResult}
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.api.{FileSystem, Network}
|
||||
import li.cil.oc.common.tileentity
|
||||
@ -14,11 +15,11 @@ import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.nbt._
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.integrated.IntegratedServer
|
||||
import net.minecraft.world.World
|
||||
import scala.Array.canBuildFrom
|
||||
import scala.collection.mutable
|
||||
import li.cil.oc.api.detail.MachineAPI
|
||||
|
||||
class Machine(val owner: Machine.Owner) extends ManagedComponent with Context with Runnable {
|
||||
class Machine(val owner: Owner) extends ManagedComponent with Context with Runnable {
|
||||
val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("computer", Visibility.Neighbors).
|
||||
withConnector(if (isRobot) Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel else Settings.get.bufferComputer).
|
||||
@ -432,7 +433,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
}
|
||||
}
|
||||
// For computers, to generate the components in their inventory.
|
||||
owner.onConnect(node)
|
||||
owner.onMachineConnect(node)
|
||||
}
|
||||
|
||||
override def onDisconnect(node: Node) {
|
||||
@ -447,7 +448,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
}
|
||||
}
|
||||
// For computers, to save the components in their inventory.
|
||||
owner.onDisconnect(node)
|
||||
owner.onMachineDisconnect(node)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -684,7 +685,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
|
||||
// This is a really high level lock that we only use for saving and loading.
|
||||
override def run(): Unit = Machine.this.synchronized {
|
||||
val enterState = state.synchronized {
|
||||
val isSynchronizedReturn = state.synchronized {
|
||||
if (state.top != Machine.State.Yielded &&
|
||||
state.top != Machine.State.SynchronizedReturn) {
|
||||
return
|
||||
@ -694,13 +695,13 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
state.push(Machine.State.Paused)
|
||||
return
|
||||
}
|
||||
switchTo(Machine.State.Running)
|
||||
switchTo(Machine.State.Running) == Machine.State.SynchronizedReturn
|
||||
}
|
||||
|
||||
cpuStart = System.nanoTime()
|
||||
|
||||
try {
|
||||
val result = architecture.runThreaded(enterState)
|
||||
val result = architecture.runThreaded(isSynchronizedReturn)
|
||||
|
||||
// Check if someone called pause() or stop() in the meantime.
|
||||
state.synchronized {
|
||||
@ -752,7 +753,15 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
}
|
||||
}
|
||||
|
||||
object Machine {
|
||||
object Machine extends MachineAPI {
|
||||
|
||||
val architectures = mutable.Set.empty[Class[_ <: Architecture]]
|
||||
|
||||
override def add(architecture: Class[_ <: Architecture]) {
|
||||
|
||||
}
|
||||
|
||||
override def create(owner: Owner, architecture: Class[_ <: Architecture]) = ???
|
||||
|
||||
private[component] class LimitReachedException extends Exception
|
||||
|
||||
@ -793,19 +802,4 @@ object Machine {
|
||||
private[component] class Signal(val name: String, val args: Array[Any])
|
||||
|
||||
private val threadPool = ThreadPoolFactory.create("Computer", Settings.get.threads)
|
||||
|
||||
trait Owner extends Context {
|
||||
def installedMemory: Int
|
||||
|
||||
def maxComponents: Int
|
||||
|
||||
def world: World
|
||||
|
||||
def markAsChanged()
|
||||
|
||||
def onConnect(node: Node)
|
||||
|
||||
def onDisconnect(node: Node)
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import com.google.common.base.Strings
|
||||
import com.naef.jnlua._
|
||||
import java.io.{IOException, FileNotFoundException}
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.api.machine.ExecutionResult
|
||||
import li.cil.oc.util.ExtendedLuaState.extendLuaState
|
||||
import li.cil.oc.util.{GameTimeFormatter, LuaStateFactory}
|
||||
import li.cil.oc.{OpenComputers, server, Settings}
|
||||
@ -29,6 +30,8 @@ class NativeLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def name() = "Lua"
|
||||
|
||||
override def isInitialized = kernelMemory > 0
|
||||
|
||||
override def recomputeMemory() = Option(lua) match {
|
||||
@ -65,7 +68,7 @@ class NativeLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
}
|
||||
}
|
||||
|
||||
override def runThreaded(enterState: Machine.State.Value): ExecutionResult = {
|
||||
override def runThreaded(isSynchronizedReturn: Boolean): ExecutionResult = {
|
||||
try {
|
||||
// The kernel thread will always be at stack index one.
|
||||
assert(lua.isThread(1))
|
||||
@ -77,44 +80,43 @@ class NativeLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
}
|
||||
|
||||
// Resume the Lua state and remember the number of results we get.
|
||||
val results = enterState match {
|
||||
case Machine.State.SynchronizedReturn =>
|
||||
// If we were doing a synchronized call, continue where we left off.
|
||||
assert(lua.getTop == 2)
|
||||
assert(lua.isTable(2))
|
||||
lua.resume(1, 1)
|
||||
case Machine.State.Yielded =>
|
||||
if (kernelMemory == 0) {
|
||||
// We're doing the initialization run.
|
||||
if (lua.resume(1, 0) > 0) {
|
||||
// We expect to get nothing here, if we do we had an error.
|
||||
0
|
||||
}
|
||||
else {
|
||||
// Run the garbage collector to get rid of stuff left behind after
|
||||
// the initialization phase to get a good estimate of the base
|
||||
// memory usage the kernel has (including libraries). We remember
|
||||
// that size to grant user-space programs a fixed base amount of
|
||||
// memory, regardless of the memory need of the underlying system
|
||||
// (which may change across releases).
|
||||
lua.gc(LuaState.GcAction.COLLECT, 0)
|
||||
kernelMemory = math.max(lua.getTotalMemory - lua.getFreeMemory, 1)
|
||||
recomputeMemory()
|
||||
val results = if (isSynchronizedReturn) {
|
||||
// If we were doing a synchronized call, continue where we left off.
|
||||
assert(lua.getTop == 2)
|
||||
assert(lua.isTable(2))
|
||||
lua.resume(1, 1)
|
||||
}
|
||||
else {
|
||||
if (kernelMemory == 0) {
|
||||
// We're doing the initialization run.
|
||||
if (lua.resume(1, 0) > 0) {
|
||||
// We expect to get nothing here, if we do we had an error.
|
||||
0
|
||||
}
|
||||
else {
|
||||
// Run the garbage collector to get rid of stuff left behind after
|
||||
// the initialization phase to get a good estimate of the base
|
||||
// memory usage the kernel has (including libraries). We remember
|
||||
// that size to grant user-space programs a fixed base amount of
|
||||
// memory, regardless of the memory need of the underlying system
|
||||
// (which may change across releases).
|
||||
lua.gc(LuaState.GcAction.COLLECT, 0)
|
||||
kernelMemory = math.max(lua.getTotalMemory - lua.getFreeMemory, 1)
|
||||
recomputeMemory()
|
||||
|
||||
// Fake zero sleep to avoid stopping if there are no signals.
|
||||
lua.pushInteger(0)
|
||||
1
|
||||
}
|
||||
// Fake zero sleep to avoid stopping if there are no signals.
|
||||
lua.pushInteger(0)
|
||||
1
|
||||
}
|
||||
else machine.popSignal() match {
|
||||
case Some(signal) =>
|
||||
lua.pushString(signal.name)
|
||||
signal.args.foreach(arg => lua.pushValue(arg))
|
||||
lua.resume(1, 1 + signal.args.length)
|
||||
case _ =>
|
||||
lua.resume(1, 0)
|
||||
}
|
||||
case s => throw new AssertionError("Running computer from invalid state " + s.toString)
|
||||
}
|
||||
else machine.popSignal() match {
|
||||
case Some(signal) =>
|
||||
lua.pushString(signal.name)
|
||||
signal.args.foreach(arg => lua.pushValue(arg))
|
||||
lua.resume(1, 1 + signal.args.length)
|
||||
case _ =>
|
||||
lua.resume(1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the kernel is still alive.
|
||||
|
Loading…
x
Reference in New Issue
Block a user