After searching around on how to do safe scripting in jme, allowing unsafe user supplied code to executed, I decided to give it a try and share with the world
Basically this is the LuaJ project extended and adjusted for the use of unsafe scripts. Mainly this means removing everything that might escape the Interpreted sandbox, and secondly removing everything that might hog large amount of ressources (eg while true do print(ālolololoā) end)
My motivation for this is to have smaller programmable parts in my spacegame, in the current Testszenario it is to allow long time players to adjust the bahaviour of a door in the spaceship.
Of course I see various different uses for this in other games
-> Programmable blocks in a blockworld
-> In game editor for a platformer (eg triggers for elevators)
-> Mod/Addon extension points
-> Or simply to quickly hack a prototype of a gameitem together in unity style.
Why lua?
-> Functions are first class objects, allowing for a reflection like logic and a very powerfull logic (callbacks ect.)
-> Lua can be used like a OO language, when providing the correct metatables
-> Many (non programmer)people know lua due to modding/playing around with CryEngine/Garrrysmod/Freelancer or other game engines.
-> Lua has no insane logical flaws (eg basic wich uses user provided line numbers for goto)
-> Many of the JVM embedded scripting languages are really powerfull (javascript for example), but nearly impossible to secure in terms of ressource hogging. Using a strictly interpreted languages (javascript in JVM compiles to native by default) allows vetos and limits enforced by the interpreter.
-> The Java based interpreter is fast, with comparable performance to the c one (some test cases are even faster).
-> The interpreter is really lightweight and having several hundered instances open is not costing much memory.(in my game I need around 300-900 instances running on one server)
-> The ability to have pausable Coroutines, one of my plans is to allow user scripts to create (a limited amount of ) worker Coroutine, that simply pauses when reaching the instruction limit, and will be continued in the next game tick.
local friends={'empire','jmonkeyrulez'}
local duser
local ddoor
function canOpenDoor(user,door)
--reduce cost of canOpenDoor as it might have a very low limit, and do work in the higher limid tick call
door.processing()
duser = user
ddoor = door
end
function tick()
if ddoor and duser then
print("Testing user " .. duser.name);
if table.contains(friends, duser.name) then
ddoor.open()
else
ddoor.deny()
end
ddoor = nil
duser = nil
end
end
Last but not least, Iām always happy to recieve feedback,
-> Be it unhandled security holes
-> Improvements in the limit handling
-> Common usecase java side functions to reduce interpreter cpu consumption
-> Others interested in using/embedding this into their games.Garrrysmod