This is my code
https://pastebin.com/fnZreFKA
I have tried all the coroutine options, I have print statements at the start of each of the two functions, it prints, but it doesn't do anything in the loop
coroutine.wrap(constantWork)()
coroutine.wrap(lookForKeys)()
The loops start after line 170
Because they are not detached threads, they are green synchronous threads, only one of them will run the code at the time.
To simulate multitasking you forgot to use yield. coroutine.yield pauses the thread and runs the next code after you called the coroutine. You can resume the coroutine later on by calling wrapped coroutine again or using coroutine.resume if you created it using coroutine.create.
Read the documentation here: https://www.lua.org/pil/9.html
coroutine.wrap creates a new coroutine based on the function you passed it, and then creates a new function based on the coroutine. The first time you call it, it calls the original function until it yields. The next time, it returns from the yield and runs until the next yield. And so on.
In ComputerCraft, yielding is the same as waiting for an event.
ComputerCraft comes with the parallel library which runs two or more functions as coroutines in parallel. It does all the work for you.
You can use parallel.waitForAll or parallel.waitForAny, depending on when you want it to return.
Usage: parallel.waitForAll(constantWork, lookForKeys)
Related
I am trying to have a while loop in my on_input that will continuually execute piece of code every few seconds
while(action_id == hash("click"))
do
print("Going")
end
I have tried moving it into other functions that are called by on_input, but every time a run this piece of code it crashes the program.
EDIT: I found that I was supposed to make sure the condition becomes false, stupid mistake.
The on_input() function is called by the engine every frame that some kind of input is received. What you are doing is entering an infinite loop during the frame when you receive an action_id that is "click". The loop will never complete since action_id will not change and the engine will lock up.
I just needed to make sure the conditional is false. I initially thought that the while loop would simply execute and then execute, this should have been done by an if statement.
I'm implementing Lua scripting engine in my c++ game engine and I was wondering what is the best way to store and execute Lua scripts. I have many scene nodes where each of them could have it's own script assigned. Is calling lauL_dofile(...) every frame for that specific script a viable option, or is there a better way? For example, is there a way to store already parsed scripts? I was looking at luaL_loadfile and lua_pcall. I thought I would load scripts with first one, and call them with second one when I need, but lua_pcall doesn't seem to have an unique id as a parameter, so how should I know which script to execute?
If you're going to use the Lua API, you need to become comfortable with the Lua stack. And one of the most important things you can learn to do is understanding how to read the Lua API docs. For every function, there is a notation on the right about exactly how it affects the stack (if it modifies the stack at all).
luaL_loadfile loads a file and pushes that file as a Lua function onto the stack. lua_pcall executes a function on the stack. But it has a number of caveats about how it does stuff.
The way calling functions through Lua works in terms of the stack is simple. You push the function you want to call. Then you push all of the arguments, in order, from first to last. Then you issue your call of that function. lua_pcall works in this way. This means that the location of the function to execute is always nargs + 1, relative to the top of the stack, where nargs is the number of arguments you're passing to the function.
Note that lua_pcall will pop the function from the stack (along with all of the arguments). If you just loaded the file, this will be the only reference to that function in Lua. Thus, you will not be able to execute the file again. You should duplicate the function before pushing its arguments onto the stack, using lua_pushvalue to copy it. You should probably stick it in the LUA_REGISTRYINDEX table or something, so that it's value is preserved.
As I commented, you usually call luaL_loadfile at initialization time. The loaded files usually define some [global] names (or fill some slots in some global table) as Lua functions. The lua 5.2 documentation gives an example (§4 lua_call) of how to call one of them. You'll do such calls (perhaps using lua_pcall or lua_call) at appropriate places of your application, by pushing appropriate things on the Lua stack.
I'm using a game engine that allows you to program in Lua. The game engine commands are in a DLL created from C. There is a exe created in C that calls a Lua file. This Lua file is where you put all your game code including the main loop. There is no going back and forth with the exe, but you can call functions from the DLL.
So in here before the main loop I create a function which I'm going to create a coroutine from. This function iterates over a pretty big table so every n iterations I yield. This function has an infinite while loop around that because I need this stuff to run every single cycle of the main game loop, but it's OK if it's split between multiple cycles.
I then create a coroutine with this function as the parameter. In the main game loop I then resume this coroutine.
When I run my code I get the error: tempt to yield across metamethod/C-call boundary
I was reading some stuff online but not really understanding what the issue is here. Once the exe calls the Lua file it doesn't go back to the exe at all until the Lua file is finished, and since I have my main loop in the Lua file it never finishes in my test case.
What are my options with this then?
The error is telling you that you are attempting to yield from within Lua code where there is some C function between the Lua code doing the yielding and the Lua code that resumed the coroutine. To hit this error, what you have to have done is call some C function from Lua, which calls back into Lua code, which then calls coroutine.yield().
You can't do that. You must instead restructure your code to avoid this. Since you didn't provide any code, there's not much that can be suggested.
There are several things you can do if you cannot change your code to avoid the C/metamethod boundary:
If you are using standard Lua, and are compiling it yourself, try patching it with Coco — True C Coroutines for Lua.
True C coroutine semantics mean you can yield from a coroutine across a C call boundary and resume back to it.
Try using LuaJIT instead of the standard Lua interpreter. It uses a fully resumable VM meaning the boundary is not an issue.
Try using Lua 5.2. It features yieldable pcall and metamethods which means that it can handle your problem. However, there are some changes and incompatibilities between Lua 5.1 and Lua 5.2.
I am trying to create a sleep function for Lua, since my Lua-Scripts all run in a different thread/environment I wanted to yield their thread and restart from the main thread when the given amount of time elapsed, the main thread is in Java and the time elapsing is done with a loop.
Now this isn't really hard or something but I am trying to use Lua's own coroutines/threads so I don't have to create my own thread structure but (my Lua knowledge isn't top-notch) I don't know how I can yield a thread from outside of the thread.
Is it possible to yield a thread from the main thread?
Edit Nevermind, I just figured it out. I did a getfenv and used the coroutine.yield of the script it's own environment.
I used the script it's coroutine.yield function. Pretty easy looking back at it
I'm writing a GUI that's meant to be easily customizable by the end-users. The functions are in C++ and are called from Lua. I'm trying to make a Sleep() type function that will pause the script but not the program itself.
I was able to get it working by using threads and making one for each function. However, I want it to be an individual function. As in, instead of having it part of the CreateButton function and every other function, simply having a Delay or Sleep function that only halts the script, not the entire program.
Me being a novice at Lua, I really don't know how to go about this. Any help is appreciated.
I'd look into making a state machine using coroutines and message passing. Treat each button push like a c++ string that gets passed into coroutine resume. You can then build a little state machine that switches on the message. You can then do some UI work and then put the coroutine back to sleep till something sends it another message.
This is pretty handy if you have a state machine that does UI.
pseudo code:
c_obj:wait_for_message("mouse_down");
local message = coroutine.yield();
if(message == "mouse_down") then
update draw function.
end
c_obj:wait_for_message("mouse_up");
local message = coroutine.yield();
if(message == "mouse_up") then
Update UI..
update draw function.
end
etc...
To make your busy-waiting solution more efficient, how about using select() or similar to wait for some GUI events to process, rather than spinning? It seems like something you would need to do in the GUI regardless of the scripting side of things.