diff --git a/docs/quirks.md b/docs/quirks.md index 6f9b156..d2cff39 100644 --- a/docs/quirks.md +++ b/docs/quirks.md @@ -1,4 +1,4 @@ -## Quirks in TeaVM +## TeaVM Quirks and Caveats When TeaVM compiles code, it sometimes does strange things. #### Property Suffixes @@ -14,4 +14,15 @@ Update 13/09/2024: Any form of incorrect data type, even passing the wrong values, can cause this sort of hang. I encountered this when trying to set a block in the world to any form of wood or leaf block, without adding iproperties to the tree type. Update 13/09/2024: -Calling methods while the TeaVM thread is in a critical transition state (see `ModAPI.util.isCritical()`) will shift the call stack, cause methods to access the incorrect values at runtime, and also cause the stack to implode. Gotta love TeaVM. \ No newline at end of file +Calling methods while the TeaVM thread is in a critical transition state (see `ModAPI.util.isCritical()`) will shift the call stack, cause methods to access the incorrect values at runtime, and also cause the stack to implode. Gotta love TeaVM. + +Update 22/09/2024: +See Asynchronous Code + +#### TeaVM thread suspension/resumption +TeaVM allows for writing asynchronous callbacks, which eaglercraft uses for file operations and downloading from URIs. However, when a method that makes use of an async callback gets run from ModAPI, it triggers a stack implosion due to mismatches in value types upon return (as well as a whole other myriad of symptoms). Currently this is not supported by ModAPI, and it will take some time until it will be. In the meanwhile, avoid using constructors or methods that access a file or use other asynchronous apis. Examples: + - Constructing an EntityPlayerMP + - Setting blocks in the world in some occasions + +Potential workarounds: This isn't confirmed yet, but there is a probable chance that overriding or patching methods in classes like VFile2 or PlatformFilesystem is a viable workaround. (22/09/2024). +I'll be verifying this is the future and if it is possible, releasing a library for it. (the maybe-library is going to be called AsyncSink if it will exist) \ No newline at end of file diff --git a/examplemods/npcspawner.js b/examplemods/npcspawner.js index d0afafc..1df91bc 100644 --- a/examplemods/npcspawner.js +++ b/examplemods/npcspawner.js @@ -17,8 +17,9 @@ // Get the EntityPlayerMP class to spawn the fake player const EntityPlayerMPClass = ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP"); + console.log(ModAPI.server.getConfigurationManager()); const fakePlayer = EntityPlayerMPClass.constructors[0]( - world.getMinecraftServer(), world.getRef(), fakeProfile, playerInteractionManager + ModAPI.server.getRef(), world.getRef(), fakeProfile, playerInteractionManager ); // Set the fake player position to be near the command sender diff --git a/examplemods/threadtesting.js b/examplemods/threadtesting.js new file mode 100644 index 0000000..1b0a633 --- /dev/null +++ b/examplemods/threadtesting.js @@ -0,0 +1,63 @@ +//SUCCESS - While there is no TeaVM thread actively running, I am able to run an asyncronous function, and get a result. +ModAPI.hooks._teavm.$rt_startThread(() => { + return ModAPI.hooks.methods.nlevi_PlatformRuntime_downloadRemoteURI(ModAPI.util.str("data:text/plain,hi")) +}, function (...args) { console.log(this, args) }) + + +//WIP - Pausing and resuming client thread +globalThis.suspendTest = function (...args) { + if (!ModAPI.util.isCritical()) { + var thread = ModAPI.hooks._teavm.$rt_nativeThread(); + var javaThread = ModAPI.hooks._teavm.$rt_getThread(); + globalThis.testThread = thread; + console.log("BeforeAnything: ", thread.stack); + thread.suspend(function () { + console.log("Pausing for 10 seconds.", thread.stack); + setTimeout(function () { + console.log("Resuming...", thread.stack); + ModAPI.hooks._teavm.$rt_setThread(javaThread); + thread.resume(); + console.log("After resume: ", thread.stack); + }, 10000); + }); + } + return suspendTest.apply(this, args); +} + + + + + +function jl_Thread_sleep$_asyncCall_$(millis) { + var thread = $rt_nativeThread(); + var javaThread = $rt_getThread(); + var callback = function () { }; + callback.$complete = function (val) { + thread.attribute = val; + $rt_setThread(javaThread); + thread.resume(); + }; + callback.$error = function (e) { + thread.attribute = $rt_exception(e); + $rt_setThread(javaThread); + thread.resume(); + }; + callback = otpp_AsyncCallbackWrapper_create(callback); + thread.suspend(function () { + try { + jl_Thread_sleep0(millis, callback); + } catch ($e) { + callback.$error($rt_exception($e)); + } + }); + return null; +} +function jl_Thread_sleep0($millis, $callback) { + var $current, $handler; + $current = jl_Thread_currentThread(); + $handler = new jl_Thread$SleepHandler; + $handler.$thread = $current; + $handler.$callback = $callback; + $handler.$scheduleId = otp_Platform_schedule($handler, Long_ge($millis, Long_fromInt(2147483647)) ? 2147483647 : Long_lo($millis)); + $current.$interruptHandler = $handler; +} \ No newline at end of file diff --git a/index.html b/index.html index a013e29..7affca3 100644 --- a/index.html +++ b/index.html @@ -89,6 +89,8 @@
Awaiting input...