mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +00:00 
			
		
		
		
	Construct ILuaMachines in one go
This means creating an ILuaMachine is largely atomic - it either is created or it fails.
This commit is contained in:
		| @@ -4,12 +4,10 @@ | |||||||
| 
 | 
 | ||||||
| package dan200.computercraft.gametest.core | package dan200.computercraft.gametest.core | ||||||
| 
 | 
 | ||||||
| import dan200.computercraft.api.lua.ILuaAPI |  | ||||||
| import dan200.computercraft.core.apis.OSAPI | import dan200.computercraft.core.apis.OSAPI | ||||||
| import dan200.computercraft.core.lua.CobaltLuaMachine | import dan200.computercraft.core.lua.CobaltLuaMachine | ||||||
| import dan200.computercraft.core.lua.ILuaMachine | import dan200.computercraft.core.lua.ILuaMachine | ||||||
| import dan200.computercraft.core.lua.MachineEnvironment | import dan200.computercraft.core.lua.MachineEnvironment | ||||||
| import dan200.computercraft.core.lua.MachineResult |  | ||||||
| import dan200.computercraft.gametest.api.thenOnComputer | import dan200.computercraft.gametest.api.thenOnComputer | ||||||
| import dan200.computercraft.mixin.gametest.GameTestInfoAccessor | import dan200.computercraft.mixin.gametest.GameTestInfoAccessor | ||||||
| import dan200.computercraft.shared.computer.core.ServerContext | import dan200.computercraft.shared.computer.core.ServerContext | ||||||
| @@ -60,52 +58,18 @@ object ManagedComputers : ILuaMachine.Factory { | |||||||
|         return monitor |         return monitor | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun create(environment: MachineEnvironment): ILuaMachine = DelegateMachine(environment) |     override fun create(environment: MachineEnvironment, bios: InputStream): ILuaMachine { | ||||||
| 
 |         val os = environment.apis.asSequence().filterIsInstance(OSAPI::class.java).first() | ||||||
|     private class DelegateMachine(private val environment: MachineEnvironment) : ILuaMachine { |         val id = os.computerID | ||||||
|         private val apis = mutableListOf<ILuaAPI>() |         val label = os.computerLabel | ||||||
|         private var delegate: ILuaMachine? = null |         return when { | ||||||
| 
 |             id != 1 -> CobaltLuaMachine(environment, bios) | ||||||
|         override fun addAPI(api: ILuaAPI) { |             label != null && label[0] != null -> KotlinMachine(environment, label[0] as String) | ||||||
|             val delegate = this.delegate |             else -> { | ||||||
|             if (delegate != null) return delegate.addAPI(api) |                 LOGGER.error("Kotlin Lua machine must have a label") | ||||||
| 
 |                 CobaltLuaMachine(environment, bios) | ||||||
|             apis.add(api) |  | ||||||
| 
 |  | ||||||
|             if (api is OSAPI) { |  | ||||||
|                 val id = api.computerID |  | ||||||
|                 val label = api.computerLabel |  | ||||||
|                 val newMachine = when { |  | ||||||
|                     id != 1 -> CobaltLuaMachine(environment) |  | ||||||
|                     label != null && label[0] != null -> KotlinMachine(environment, label[0] as String) |  | ||||||
|                     else -> { |  | ||||||
|                         LOGGER.error("Kotlin Lua machine must have a label") |  | ||||||
|                         CobaltLuaMachine(environment) |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 this.delegate = newMachine |  | ||||||
|                 for (api in apis) newMachine.addAPI(api) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         override fun loadBios(bios: InputStream): MachineResult { |  | ||||||
|             val delegate = this.delegate ?: return MachineResult.error("Computer not created") |  | ||||||
|             return delegate.loadBios(bios) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         override fun handleEvent(eventName: String?, arguments: Array<out Any>?): MachineResult { |  | ||||||
|             val delegate = this.delegate ?: return MachineResult.error("Computer not created") |  | ||||||
|             return delegate.handleEvent(eventName, arguments) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         override fun printExecutionState(out: StringBuilder) { |  | ||||||
|             delegate?.printExecutionState(out) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         override fun close() { |  | ||||||
|             delegate?.close() |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private class KotlinMachine(environment: MachineEnvironment, private val label: String) : |     private class KotlinMachine(environment: MachineEnvironment, private val label: String) : | ||||||
|   | |||||||
| @@ -14,15 +14,16 @@ import dan200.computercraft.core.filesystem.FileSystem; | |||||||
| import dan200.computercraft.core.filesystem.FileSystemException; | import dan200.computercraft.core.filesystem.FileSystemException; | ||||||
| import dan200.computercraft.core.lua.ILuaMachine; | import dan200.computercraft.core.lua.ILuaMachine; | ||||||
| import dan200.computercraft.core.lua.MachineEnvironment; | import dan200.computercraft.core.lua.MachineEnvironment; | ||||||
|  | import dan200.computercraft.core.lua.MachineException; | ||||||
| import dan200.computercraft.core.metrics.Metrics; | import dan200.computercraft.core.metrics.Metrics; | ||||||
| import dan200.computercraft.core.metrics.MetricsObserver; | import dan200.computercraft.core.metrics.MetricsObserver; | ||||||
| import dan200.computercraft.core.util.Colour; | import dan200.computercraft.core.util.Colour; | ||||||
| import dan200.computercraft.core.util.IoUtil; |  | ||||||
| import dan200.computercraft.core.util.Nullability; | import dan200.computercraft.core.util.Nullability; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.util.ArrayDeque; | import java.util.ArrayDeque; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @@ -377,24 +378,20 @@ final class ComputerExecutor { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Create the lua machine |         // Create the lua machine | ||||||
|         var machine = luaFactory.create(new MachineEnvironment( |         try (var bios = biosStream) { | ||||||
|             new LuaContext(computer), metrics, timeout, computer.getGlobalEnvironment().getHostString() |             return luaFactory.create(new MachineEnvironment( | ||||||
|         )); |                 new LuaContext(computer), metrics, timeout, | ||||||
| 
 |                 () -> apis.stream().map(api -> api instanceof ApiWrapper wrapper ? wrapper.getDelegate() : api).iterator(), | ||||||
|         // Add the APIs. We unwrap them (yes, this is horrible) to get access to the underlying object. |                 computer.getGlobalEnvironment().getHostString() | ||||||
|         for (var api : apis) machine.addAPI(api instanceof ApiWrapper wrapper ? wrapper.getDelegate() : api); |             ), bios); | ||||||
| 
 |         } catch (IOException e) { | ||||||
|         // Start the machine running the bios resource |             LOG.error("Failed to read bios.lua", e); | ||||||
|         var result = machine.loadBios(biosStream); |             displayFailure("Error loading bios.lua", null); | ||||||
|         IoUtil.closeQuietly(biosStream); |             return null; | ||||||
| 
 |         } catch (MachineException e) { | ||||||
|         if (result.isError()) { |             displayFailure("Error loading bios.lua", e.getMessage()); | ||||||
|             machine.close(); |  | ||||||
|             displayFailure("Error loading bios.lua", result.getMessage()); |  | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         return machine; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void turnOn() throws InterruptedException { |     private void turnOn() throws InterruptedException { | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import dan200.computercraft.core.asm.LuaMethod; | |||||||
| import dan200.computercraft.core.asm.ObjectSource; | import dan200.computercraft.core.asm.ObjectSource; | ||||||
| import dan200.computercraft.core.computer.TimeoutState; | import dan200.computercraft.core.computer.TimeoutState; | ||||||
| import dan200.computercraft.core.metrics.Metrics; | import dan200.computercraft.core.metrics.Metrics; | ||||||
|  | import dan200.computercraft.core.util.Nullability; | ||||||
| import dan200.computercraft.core.util.ThreadUtils; | import dan200.computercraft.core.util.ThreadUtils; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| @@ -27,6 +28,7 @@ import org.squiddev.cobalt.lib.*; | |||||||
| import org.squiddev.cobalt.lib.platform.VoidResourceManipulator; | import org.squiddev.cobalt.lib.platform.VoidResourceManipulator; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.io.Serial; | import java.io.Serial; | ||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
| @@ -62,7 +64,7 @@ public class CobaltLuaMachine implements ILuaMachine { | |||||||
|     private @Nullable LuaThread mainRoutine = null; |     private @Nullable LuaThread mainRoutine = null; | ||||||
|     private @Nullable String eventFilter = null; |     private @Nullable String eventFilter = null; | ||||||
| 
 | 
 | ||||||
|     public CobaltLuaMachine(MachineEnvironment environment) { |     public CobaltLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException, IOException { | ||||||
|         timeout = environment.timeout(); |         timeout = environment.timeout(); | ||||||
|         context = environment.context(); |         context = environment.context(); | ||||||
|         debug = new TimeoutDebugHandler(); |         debug = new TimeoutDebugHandler(); | ||||||
| @@ -115,10 +117,20 @@ public class CobaltLuaMachine implements ILuaMachine { | |||||||
|         if (CoreConfig.disableLua51Features) { |         if (CoreConfig.disableLua51Features) { | ||||||
|             globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE); |             globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         // Add default APIs | ||||||
|  |         for (var api : environment.apis()) addAPI(api); | ||||||
|  | 
 | ||||||
|  |         // And load the BIOS | ||||||
|  |         try { | ||||||
|  |             var value = LoadState.load(state, bios, "@bios.lua", globals); | ||||||
|  |             mainRoutine = new LuaThread(state, value, globals); | ||||||
|  |         } catch (CompileException e) { | ||||||
|  |             throw new MachineException(Nullability.assertNonNull(e.getMessage())); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     private void addAPI(ILuaAPI api) { | ||||||
|     public void addAPI(ILuaAPI api) { |  | ||||||
|         if (globals == null) throw new IllegalStateException("Machine has been closed"); |         if (globals == null) throw new IllegalStateException("Machine has been closed"); | ||||||
| 
 | 
 | ||||||
|         // Add the methods of an API to the global table |         // Add the methods of an API to the global table | ||||||
| @@ -132,25 +144,6 @@ public class CobaltLuaMachine implements ILuaMachine { | |||||||
|         for (var name : names) globals.rawset(name, table); |         for (var name : names) globals.rawset(name, table); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |  | ||||||
|     public MachineResult loadBios(InputStream bios) { |  | ||||||
|         if (mainRoutine != null) throw new IllegalStateException("Already set up the machine"); |  | ||||||
|         if (state == null || globals == null) throw new IllegalStateException("Machine has been destroyed."); |  | ||||||
| 
 |  | ||||||
|         try { |  | ||||||
|             var value = LoadState.load(state, bios, "@bios.lua", globals); |  | ||||||
|             mainRoutine = new LuaThread(state, value, globals); |  | ||||||
|             return MachineResult.OK; |  | ||||||
|         } catch (CompileException e) { |  | ||||||
|             close(); |  | ||||||
|             return MachineResult.error(e); |  | ||||||
|         } catch (Exception e) { |  | ||||||
|             LOG.warn("Could not load bios.lua", e); |  | ||||||
|             close(); |  | ||||||
|             return MachineResult.GENERIC_ERROR; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |     @Override | ||||||
|     public MachineResult handleEvent(@Nullable String eventName, @Nullable Object[] arguments) { |     public MachineResult handleEvent(@Nullable String eventName, @Nullable Object[] arguments) { | ||||||
|         if (mainRoutine == null || state == null) throw new IllegalStateException("Machine has been closed"); |         if (mainRoutine == null || state == null) throw new IllegalStateException("Machine has been closed"); | ||||||
|   | |||||||
| @@ -4,10 +4,8 @@ | |||||||
| 
 | 
 | ||||||
| package dan200.computercraft.core.lua; | package dan200.computercraft.core.lua; | ||||||
| 
 | 
 | ||||||
| import dan200.computercraft.api.lua.IDynamicLuaObject; |  | ||||||
| import dan200.computercraft.api.lua.ILuaAPI; |  | ||||||
| 
 |  | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -17,32 +15,8 @@ import java.io.InputStream; | |||||||
|  * There should only be one concrete implementation at any one time, which is currently {@link CobaltLuaMachine}. If |  * There should only be one concrete implementation at any one time, which is currently {@link CobaltLuaMachine}. If | ||||||
|  * external mod authors are interested in registering their own machines, we can look into how we can provide some |  * external mod authors are interested in registering their own machines, we can look into how we can provide some | ||||||
|  * mechanism for registering these. |  * mechanism for registering these. | ||||||
|  * <p> |  | ||||||
|  * This should provide implementations of {@link dan200.computercraft.api.lua.ILuaContext}, and the ability to convert |  | ||||||
|  * {@link IDynamicLuaObject}s into something the VM understands, as well as handling method calls. |  | ||||||
|  */ |  */ | ||||||
| public interface ILuaMachine { | public interface ILuaMachine { | ||||||
|     /** |  | ||||||
|      * Inject an API into the global environment of this machine. This should construct an object, as it would for any |  | ||||||
|      * {@link IDynamicLuaObject} and set it to all names in {@link ILuaAPI#getNames()}. |  | ||||||
|      * <p> |  | ||||||
|      * Called before {@link #loadBios(InputStream)}. |  | ||||||
|      * |  | ||||||
|      * @param api The API to register. |  | ||||||
|      */ |  | ||||||
|     void addAPI(ILuaAPI api); |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Create a function from the provided program, and set it up to run when {@link #handleEvent(String, Object[])} is |  | ||||||
|      * called. |  | ||||||
|      * <p> |  | ||||||
|      * This should destroy the machine if it failed to load the bios. |  | ||||||
|      * |  | ||||||
|      * @param bios The stream containing the boot program. |  | ||||||
|      * @return The result of loading this machine. Will either be OK, or the error message when loading the bios. |  | ||||||
|      */ |  | ||||||
|     MachineResult loadBios(InputStream bios); |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Resume the machine, either starting or resuming the coroutine. |      * Resume the machine, either starting or resuming the coroutine. | ||||||
|      * <p> |      * <p> | ||||||
| @@ -71,6 +45,16 @@ public interface ILuaMachine { | |||||||
|     void close(); |     void close(); | ||||||
| 
 | 
 | ||||||
|     interface Factory { |     interface Factory { | ||||||
|         ILuaMachine create(MachineEnvironment environment); |         /** | ||||||
|  |          * Attempt to create a Lua machine. | ||||||
|  |          * | ||||||
|  |          * @param environment The environment under which to create the machine. | ||||||
|  |          * @param bios        The {@link InputStream} which contains the initial function to run. This should be used to | ||||||
|  |          *                    load the initial function - it should <em>NOT</em> be executed. | ||||||
|  |          * @return The successfully created machine, or an error. | ||||||
|  |          * @throws IOException      If reading the underlying {@link InputStream} failed. | ||||||
|  |          * @throws MachineException An error occurred while creating the machine. | ||||||
|  |          */ | ||||||
|  |         ILuaMachine create(MachineEnvironment environment, InputStream bios) throws IOException, MachineException; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| 
 | 
 | ||||||
| package dan200.computercraft.core.lua; | package dan200.computercraft.core.lua; | ||||||
| 
 | 
 | ||||||
|  | import dan200.computercraft.api.lua.ILuaAPI; | ||||||
| import dan200.computercraft.api.lua.ILuaContext; | import dan200.computercraft.api.lua.ILuaContext; | ||||||
| import dan200.computercraft.core.computer.GlobalEnvironment; | import dan200.computercraft.core.computer.GlobalEnvironment; | ||||||
| import dan200.computercraft.core.computer.TimeoutState; | import dan200.computercraft.core.computer.TimeoutState; | ||||||
| @@ -17,6 +18,8 @@ import dan200.computercraft.core.metrics.MetricsObserver; | |||||||
|  * @param metrics    A sink to submit metrics to. You do not need to submit task timings here, it should only be for additional |  * @param metrics    A sink to submit metrics to. You do not need to submit task timings here, it should only be for additional | ||||||
|  *                   metrics such as {@link Metrics#COROUTINES_CREATED} |  *                   metrics such as {@link Metrics#COROUTINES_CREATED} | ||||||
|  * @param timeout    The current timeout state. This should be used by the machine to interrupt its execution. |  * @param timeout    The current timeout state. This should be used by the machine to interrupt its execution. | ||||||
|  |  * @param apis       APIs to inject into the global environment. Each API should be converted into a Lua object | ||||||
|  |  *                   (following the same rules as any other value), and then set to all names in {@link ILuaAPI#getNames()}. | ||||||
|  * @param hostString A {@linkplain GlobalEnvironment#getHostString() host string} to identify the current environment. |  * @param hostString A {@linkplain GlobalEnvironment#getHostString() host string} to identify the current environment. | ||||||
|  * @see ILuaMachine.Factory |  * @see ILuaMachine.Factory | ||||||
|  */ |  */ | ||||||
| @@ -24,6 +27,7 @@ public record MachineEnvironment( | |||||||
|     ILuaContext context, |     ILuaContext context, | ||||||
|     MetricsObserver metrics, |     MetricsObserver metrics, | ||||||
|     TimeoutState timeout, |     TimeoutState timeout, | ||||||
|  |     Iterable<ILuaAPI> apis, | ||||||
|     String hostString |     String hostString | ||||||
| ) { | ) { | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | // SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers | ||||||
|  | // | ||||||
|  | // SPDX-License-Identifier: MPL-2.0 | ||||||
|  | 
 | ||||||
|  | package dan200.computercraft.core.lua; | ||||||
|  | 
 | ||||||
|  | import java.io.Serial; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An exception thrown by a {@link ILuaMachine}. | ||||||
|  |  */ | ||||||
|  | public class MachineException extends Exception { | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 400833668352232261L; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a new {@link MachineException}. | ||||||
|  |      * | ||||||
|  |      * @param message The message to display. This should be user-friendly, and not contain any internal information - | ||||||
|  |      *                that should just be logged to the console. | ||||||
|  |      */ | ||||||
|  |     public MachineException(String message) { | ||||||
|  |         super(message); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -7,14 +7,12 @@ package dan200.computercraft.core.lua; | |||||||
| import dan200.computercraft.core.computer.TimeoutState; | import dan200.computercraft.core.computer.TimeoutState; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
| import java.io.InputStream; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The result of executing an action on a machine. |  * The result of executing an action on a machine. | ||||||
|  * <p> |  * <p> | ||||||
|  * Errors should halt the machine and display the error to the user. |  * Errors should halt the machine and display the error to the user. | ||||||
|  * |  * | ||||||
|  * @see ILuaMachine#loadBios(InputStream) |  | ||||||
|  * @see ILuaMachine#handleEvent(String, Object[]) |  * @see ILuaMachine#handleEvent(String, Object[]) | ||||||
|  */ |  */ | ||||||
| public final class MachineResult { | public final class MachineResult { | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ import dan200.computercraft.core.filesystem.FileSystemException; | |||||||
| import dan200.computercraft.core.filesystem.WritableFileMount; | import dan200.computercraft.core.filesystem.WritableFileMount; | ||||||
| import dan200.computercraft.core.lua.CobaltLuaMachine; | import dan200.computercraft.core.lua.CobaltLuaMachine; | ||||||
| import dan200.computercraft.core.lua.MachineEnvironment; | import dan200.computercraft.core.lua.MachineEnvironment; | ||||||
| import dan200.computercraft.core.lua.MachineResult; | import dan200.computercraft.core.lua.MachineException; | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| import dan200.computercraft.test.core.computer.BasicEnvironment; | import dan200.computercraft.test.core.computer.BasicEnvironment; | ||||||
| import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; | import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; | ||||||
| @@ -477,14 +477,8 @@ public class ComputerTestDelegate { | |||||||
|      * This is a super nasty hack, but is also an order of magnitude faster than tracking this in Lua. |      * This is a super nasty hack, but is also an order of magnitude faster than tracking this in Lua. | ||||||
|      */ |      */ | ||||||
|     private class CoverageLuaMachine extends CobaltLuaMachine { |     private class CoverageLuaMachine extends CobaltLuaMachine { | ||||||
|         CoverageLuaMachine(MachineEnvironment environment) { |         CoverageLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException, IOException { | ||||||
|             super(environment); |             super(environment, bios); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         @Override |  | ||||||
|         public MachineResult loadBios(InputStream bios) { |  | ||||||
|             var result = super.loadBios(bios); |  | ||||||
|             if (result != MachineResult.OK) return result; |  | ||||||
| 
 | 
 | ||||||
|             LuaTable globals; |             LuaTable globals; | ||||||
|             LuaThread mainRoutine; |             LuaThread mainRoutine; | ||||||
| @@ -535,8 +529,6 @@ public class ComputerTestDelegate { | |||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|             mainRoutine.getDebugState().setHook(hook, false, true, false, 0); |             mainRoutine.getDebugState().setHook(hook, false, true, false, 0); | ||||||
| 
 |  | ||||||
|             return MachineResult.OK; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ class KotlinComputerManager : AutoCloseable { | |||||||
|         BasicEnvironment(), |         BasicEnvironment(), | ||||||
|         ComputerThread(1), |         ComputerThread(1), | ||||||
|         NoWorkMainThreadScheduler(), |         NoWorkMainThreadScheduler(), | ||||||
|     ) { DummyLuaMachine(it) } |     ) { env, _ -> DummyLuaMachine(env) } | ||||||
|     private val errorLock: Lock = ReentrantLock() |     private val errorLock: Lock = ReentrantLock() | ||||||
|     private val hasError = errorLock.newCondition() |     private val hasError = errorLock.newCondition() | ||||||
| 
 | 
 | ||||||
| @@ -153,15 +153,11 @@ class KotlinComputerManager : AutoCloseable { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private inner class DummyLuaMachine(private val environment: MachineEnvironment) : KotlinLuaMachine(environment) { |     private inner class DummyLuaMachine(private val environment: MachineEnvironment) : KotlinLuaMachine(environment) { | ||||||
|         private var tasks: Queue<FakeComputerTask>? = null |         private val tasks: Queue<FakeComputerTask> = | ||||||
|         override fun addAPI(api: ILuaAPI) { |             environment.apis.asSequence().filterIsInstance(QueuePassingAPI::class.java).first().tasks | ||||||
|             super.addAPI(api) |  | ||||||
|             if (api is QueuePassingAPI) tasks = api.tasks |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         override fun getTask(): (suspend KotlinLuaMachine.() -> Unit)? { |         override fun getTask(): (suspend KotlinLuaMachine.() -> Unit)? { | ||||||
|             try { |             try { | ||||||
|                 val tasks = this.tasks ?: throw NullPointerException("Not received tasks yet") |  | ||||||
|                 val task = tasks.remove() |                 val task = tasks.remove() | ||||||
|                 return { |                 return { | ||||||
|                     try { |                     try { | ||||||
|   | |||||||
| @@ -4,13 +4,11 @@ | |||||||
| 
 | 
 | ||||||
| package dan200.computercraft.test.core.computer | package dan200.computercraft.test.core.computer | ||||||
| 
 | 
 | ||||||
| import dan200.computercraft.api.lua.ILuaAPI |  | ||||||
| import dan200.computercraft.api.lua.ILuaContext | import dan200.computercraft.api.lua.ILuaContext | ||||||
| import dan200.computercraft.core.lua.ILuaMachine | import dan200.computercraft.core.lua.ILuaMachine | ||||||
| import dan200.computercraft.core.lua.MachineEnvironment | import dan200.computercraft.core.lua.MachineEnvironment | ||||||
| import dan200.computercraft.core.lua.MachineResult | import dan200.computercraft.core.lua.MachineResult | ||||||
| import kotlinx.coroutines.* | import kotlinx.coroutines.* | ||||||
| import java.io.InputStream |  | ||||||
| import kotlin.coroutines.CoroutineContext | import kotlin.coroutines.CoroutineContext | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -19,9 +17,9 @@ import kotlin.coroutines.CoroutineContext | |||||||
| abstract class KotlinLuaMachine(environment: MachineEnvironment) : ILuaMachine, AbstractLuaTaskContext() { | abstract class KotlinLuaMachine(environment: MachineEnvironment) : ILuaMachine, AbstractLuaTaskContext() { | ||||||
|     override val context: ILuaContext = environment.context |     override val context: ILuaContext = environment.context | ||||||
| 
 | 
 | ||||||
|     override fun addAPI(api: ILuaAPI) = addApi(api) |     init { | ||||||
| 
 |         for (api in environment.apis) addApi(api) | ||||||
|     override fun loadBios(bios: InputStream): MachineResult = MachineResult.OK |     } | ||||||
| 
 | 
 | ||||||
|     override fun handleEvent(eventName: String?, arguments: Array<out Any>?): MachineResult { |     override fun handleEvent(eventName: String?, arguments: Array<out Any>?): MachineResult { | ||||||
|         if (hasEventListeners) { |         if (hasEventListeners) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates