I believe there aren't many projects which uses lua with sockets. So far, there's this
project by XKeeper that implements a netplay feature for Tetris, but looking at what the
source may look like, things seem to get messy quick. There's also
my attempt at using remote calls over sockets, but this I guess it may not be easy to use in practice. That being said, there are certainly other projects with networking features in "real time" in lua related to emulators, but I didn't find source code about it.
Anyway, while it's definitely not easy to debug what's going on a network, I believe there are a couple of ways to reduce the overhead, such as:
- Avoid blocking calls which depends on emu.frameadvance
- Make a minimal script version that can run directly into the native lua console, for debug/testing purpose
- If you use a particular resource, make sure you control access in a mutual exclusive way
- Make modular code, favor good idiom, use message queue, etc
So, where's to begin? Well, I just made a simple chat client. So maybe this can be used as a start point for something more complex. The chat client is made in
MoonScript. Basically, this can be "recompiled" to Lua 5.1 and run in BizHawk without issue. MoonScript works the same way as C++ can wrap C... or just as "CoffeeScript/TypeScript/ES6/..." can wrap JS. I figured this worked well and syntax reminds of python. Also, it's kinda easier to write modules and you can use fancy features such as "continue"(for the "for" loop), "switch" feature, etc. Also, there's a plugin available with Atom to provide a nice lint.
Here's the code.
Couple of technical note:
- The Luasocket library is used for udp sockets with another client. At some point, the script could be extended to connect with other multiple clients in a P2P fashion. Other improvements that I'm still thinking is adding a TCP mode, since it can often be easier to connect with anyone on the web using TCP without packet loss, etc. Furthermore, sometimes it can also be a bit easier to tunnel an app with TCP across the web.
- The iup library is used as a "timer", which is basically the only way to interrupt the code flow of the application, since lua is single threaded. As long, as there's no native timer functionality in the lua API, a library such as iup is being required. Without the timer, the application will have to depend on emu.frameadvance and can cause much annoyance while receiving packets,etc.
- Currently the UI makes use of the forms library in BizHawk, so you can configure your address/ports to connect to. This means, you'll probably need to change what's going in the formConnect module, to get this working with other emulator.
- As alternative functionality, you can also use the lua interpreter in the LuaConsole window(example: say "ohoh!")
- For testing purpose, you can run client_udp.lua from the command line as well if you don't want to start another instance of BizHawk.
Other thoughts:
- Despite using Lua/MoonScript to directly handle sockets in BizHawk, I guess one easier way to handle complex case would be to directly make a lua library dll in C and works from there.
- If someone really doesn't want to have any relation to lua, etc. Well, I guess it's always possible to hack directly in the emulator and add a web/HTTP API inside BizHawk and have fun from there.
Couple of screenshots:
Usage:
- Drag the startServer.lua into BizHawk.
- Type the udp port and ip and press connect
Troubleshoots:
- If you have dll issues, you may have to put the dll the socket folder next to EmuHawk.exe
- If you can't connect, make sure you can ping the remote machine and verify your firewall accept the port used.
Possible improvements:
- Support more than 2 clients
- Find and support a free service to tunnel message
- Improve the serialization/deserialization
- Support Joystick input
That's about it, let me know if you have any questions or interested in any project related.