This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
tutorial:modding_architecture:zh [2023/11/03 06:58] hfsr [Registering an architecture] |
tutorial:modding_architecture:zh [2023/11/03 08:00] (current) hfsr [Example code] |
||
---|---|---|---|
Line 37: | Line 37: | ||
- **注意:**在写这段内容的时候,我发现我忘记了把一些执行检查所需的方法放入API中。这将在下一个API更新中得到修复,使这些方法在`Component`接口中可用。现在的话,要么将它们反射进去,要么从OC源码自行构建模组。我对此表示抱歉。 | - **注意:**在写这段内容的时候,我发现我忘记了把一些执行检查所需的方法放入API中。这将在下一个API更新中得到修复,使这些方法在`Component`接口中可用。现在的话,要么将它们反射进去,要么从OC源码自行构建模组。我对此表示抱歉。 | ||
- | Example code | + | 样例代码 |
------------ | ------------ | ||
- | Let's say you have some VM that provides the following interfaces: | + | 假设你有能提供以下接口的虚拟机: |
```java | ```java | ||
- | /** The VM itself. This is just an example, it's not a "real" interface. */ | + | /**虚拟机自身。这里的仅为一个样例,不是“真的”接口。*/ |
public interface PseudoVM { | public interface PseudoVM { | ||
Object[] run(Object[] args) throws Exception; | Object[] run(Object[] args) throws Exception; | ||
Line 49: | Line 49: | ||
} | } | ||
- | /** Interface defining callbacks provided by the host. */ | + | /**定义了主机提供的回调的接口。*/ |
public interface PseudoNativeFunction { | public interface PseudoNativeFunction { | ||
Object invoke(Object[] args); | Object invoke(Object[] args); | ||
Line 55: | Line 55: | ||
``` | ``` | ||
- | A very primitive architecture implementation might look something like this: | + | 一个简单的架构实现大概看起来像这样子: |
```java | ```java | ||
- | /** This is the class you implement; Architecture is from the OC API. */ | + | /**这是你实现的类;这里的架构来自OC的API。*/ |
@Architecture.Name("Pseudolang") | @Architecture.Name("Pseudolang") | ||
public class PseudoArchitecture implements Architecture { | public class PseudoArchitecture implements Architecture { | ||
Line 65: | Line 65: | ||
private PseudoVM vm; | private PseudoVM vm; | ||
- | /** The constructor must have exactly this signature. */ | + | /**构造函数的签名必须与此处完全一致。*/ |
public PseudoArchitecture(Machine machine) { | public PseudoArchitecture(Machine machine) { | ||
this.machine = machine; | this.machine = machine; | ||
Line 75: | Line 75: | ||
public boolean initialize() { | public boolean initialize() { | ||
- | // Set up new VM here, and register all API callbacks you want to | + | //在此处新建虚拟机,并在里面注册你想要的所有API回调函数。 |
- | // provide to it. | + | |
vm = new PseudoVM(); | vm = new PseudoVM(); | ||
vm.setApiFunction("invoke", new PseudoNativeFunction() { | vm.setApiFunction("invoke", new PseudoNativeFunction() { | ||
Line 87: | Line 86: | ||
} | } | ||
catch (e LimitReachedException) { | catch (e LimitReachedException) { | ||
- | // Perform logic also used to sleep / perform synchronized calls. | + | //这里的执行逻辑也可用于休眠/执行同步调用。 |
- | // In this example we'll follow a protocol where if this returns | + | //在此样例中我们遵循这样的协议: |
- | // (true, something) the call succeeded, if it returns (false) | + | //成功时返回(true,某物),到达上限时返回(false)。 |
- | // the limit was reached. | + | //此后虚拟机中运行的脚本需要将控制权交还给 |
- | // The script running in the VM is then supposed to return control | + | //初始化了当前执行的任务的调用者(例如,若支持的话 |
- | // to the caller initiating the current execution (e.g. by yielding | + | //可以yield,或者在事件驱动的系统中直接return) |
- | // if supported, or just returning, when in an event driven system). | + | |
return new Object[]{false}; | return new Object[]{false}; | ||
} | } | ||
Line 115: | Line 113: | ||
} | } | ||
}); | }); | ||
- | // ... more callbacks. | + | // ... 更多回调。 |
return true; | return true; | ||
} | } | ||
Line 124: | Line 122: | ||
ExecutionResult runThreaded(boolean isSynchronizedReturn) { | ExecutionResult runThreaded(boolean isSynchronizedReturn) { | ||
- | // Perform stepping in here. Usually you'll want to resume the VM | + | //在此处执行所需步骤。通常你会希望通过将队列中下一个信号传递给 |
- | // by passing it the next signal from the queue, but you may decide | + | //虚拟机的方式来唤醒它,但你也可能会选择让你的虚拟机手动拉取信号。 |
- | // to allow your VM to poll for signals manually. | + | |
try { | try { | ||
final Signal signal; | final Signal signal; | ||
if (isSynchronizedReturn) { | if (isSynchronizedReturn) { | ||
- | // Don't pull signals when we're coming back from a sync call, | + | //正在从同步调用中返回时不要拉取信号!因为我们正在执行其他事情。 |
- | // since we're in the middle of something else! | + | |
signal = null; | signal = null; | ||
} | } | ||
Line 145: | Line 141: | ||
} | } | ||
- | // You'll want to define some internal protocol by which to decide | + | //你可能会想定义一些内部协议,用以决定何时执行同步调用。 |
- | // when to perform a synchronized call. Let's say we expect the VM | + | //假设我们希望虚拟机在出现待决定的同步调用时返回数字值,代表休眠 |
- | // to return either a number for a sleep, a boolean to indicate | + | //或者返回布尔值,代表关机/重启或其他东西。 |
- | // shutdown/reboot and anything else a pending synchronous call. | + | |
if (result != null) { | if (result != null) { | ||
if (result[0] instanceof Boolean) { | if (result[0] instanceof Boolean) { | ||
Line 157: | Line 152: | ||
} | } | ||
} | } | ||
- | // If this is returned, the next 'resume' will be runSynchronized. | + | //若返回此值,下次'resume'时会调用runSynchronized。 |
- | // The next call to runThreaded after that call will have the | + | //此次调用后的下次对runThreaded函数的调用中 |
- | // isSynchronizedReturn argument set to true. | + | //isSynchronizedReturn参数将会设定为true。 |
return new ExecutionResult.SynchronizedCall(); | return new ExecutionResult.SynchronizedCall(); | ||
} | } | ||
Line 168: | Line 163: | ||
void runSynchronized() { | void runSynchronized() { | ||
- | // Synchronized calls are run from the MC server thread, making it | + | //同步调用在MC的服务端线程中执行,让回调与世界交互更方便 |
- | // easier for callbacks to interact with the world (because sync is | + | //(因为它们之间的同步由执行机/架构完成) |
- | // taken care for them by the machine / architecture). | + | //这意味着若虚拟机中的代码开始了一次同步调用,就需要*暂停* |
- | // This means that if some code in the VM starts a sync call it has | + | //并且放弃对主机的控制,然后我们切换到同步调用模式(参看runThreaded), |
- | // to *pause* and relinquish control to the host, where we then | + | //并等待MC服务端线程,接着再进行实际的调用。 |
- | // switch to sync call mode (see runThreaded), wait for the MC server | + | //可以在runThread中传递调用所需的信息,将其存储在架构中, |
- | // thread, and then do the actual call. It'd be possible to pass the | + | //然后在此处直接进行调用。 |
- | // info required for the call out in runThreaded, keep it around in | + | //对此样例而言,让我们假定状态信息存储于虚拟机内部,并且 |
- | // the arch and do the call directly here. For this example, let's | + | //下次resume使其进行*实际*调用。下面给出了处理它们的伪代码。 |
- | // assume the state info is kept inside the VM, and the next resume | + | |
- | // makes it perform the *actual* call. For some pseudo-code handling | + | |
- | // this in the VM, see below. | + | |
vm.run(null); | vm.run(null); | ||
} | } | ||
Line 185: | Line 177: | ||
void onConnect() {} | void onConnect() {} | ||
- | // Use this to load the VM state, if it can be persisted. | + | //用这行代码加载虚拟机状态,假如虚拟机可持续。 |
void load(NBTTagCompound nbt) {} | void load(NBTTagCompound nbt) {} | ||
- | // Use this to save the VM state, if it can be persisted. | + | //用这行代码保存虚拟机状态,假如虚拟机可持续。 |
void save(NBTTagCompound nbt) {} | void save(NBTTagCompound nbt) {} | ||
} | } | ||
``` | ``` | ||
- | Some pseudo-code for handling synchronized calls in the VM: | + | 一些用于在虚拟机中处理同步调用的伪代码: |
```scala | ```scala | ||
private def invokeSynchronous(address, method, ...) { | private def invokeSynchronous(address, method, ...) { | ||
- | yield; // This is where it returns to runThreaded(). | + | yield; //此处为返回到runThreaded()的地方。 |
- | // This is where we enter in runSynchronized(); | + | //此处为进入runSynchronized();的地方 |
val result = native.invoke(address, method, ...); | val result = native.invoke(address, method, ...); | ||
- | // See definition of invoke in initialize() for values of result. | + | //查看initialize()中invoke的定义以获取结果值的信息。 |
- | yield; // And return to runSynchronized(); | + | yield; //并返回runSynchronized(); |
- | // And the next runThreaded() enters again. | + | //并且下一个runThreaded()又进入了。 |
return result[1]; | return result[1]; | ||
} | } | ||
private def invokeDirect(address, method, ...) { | private def invokeDirect(address, method, ...) { | ||
val result = native.invoke(address, method, ...); | val result = native.invoke(address, method, ...); | ||
- | // See definition of invoke in initialize() for values of result. | + | //查看initialize()中invoke的定义以获取结果值的信息。 |
if (result[0] == true) { | if (result[0] == true) { | ||
return result[1]; | return result[1]; |