我目前正在研究基于文本的Ruby游戏引擎,应用程序分为/ lib中的Ruby代码和/ data中的YAML数据,在游戏需要时加载。我想允许数据文件包含基本脚本,主要是在事件/观察者模型中。但是,我还希望用户能够生成和共享自定义方案,而无需担心脚本中嵌入的恶意代码。
附录:我最初的计划是将用户创建的内容分为两种类型,“模块”只是数据(因此是安全的)和插件,它们增加了额外的功能(但显然是不安全)。为了对桌面游戏进行类比,模块就像已发布的冒险场景和内容,而插件将是包含其他规则和系统的规则手册。
示例脚本(当然语法可根据解决方案进行更改):
---
Location:
observers:
on_door_open: |
monster = spawn_monster(:goblin);
monster.add_item(random_item());
monster.hostile = true;
从安全的角度来看,如果脚本严格选择加入,可能是通过包含一些DSL的mixin来实现的,例如:
class Frog
include Scriptable
def jump; ... ; end # this can be called from a script
allow_scripting :jump
def ribbit; ... ; end # this cannot be called from a script
end
我看过三个四个选项,但我不确定哪种方法最好:
使用Ruby脚本,但在某种沙箱中。
优点:非常熟悉Ruby,不需要“粘合”代码或在语言之间集成对象的问题。
缺点:对安全问题或沙盒不太熟悉,没有找到任何适合的开箱即用解决方案。
实施嵌入其他脚本语言,例如LUA。
优点: Ruby和Lua是基于C的,因此绑定应该相当简单。 Lua是一种相当流行的语言,如果我以后遇到问题,请提供帮助。安全,因为我没有特别绑定的任何功能都将无法从脚本中获取。
缺点:现有的Ruby-Lua绑定似乎是单向的,旧的,维护不良,或两者兼而有之。似乎有点狡猾,将脚本语言嵌入到另一种脚本语言中。
使用Ruby解释器实现自定义脚本语言。我一直在试验Treetop,制作一个足以满足脚本的简单语法应该不会太难。
优点:无需嵌入其他语言。只有我专门实现的功能才可用于脚本。
缺点:矫枉过正。 “没有建在这里”的综合症。可能是可怕的虫巢等待发生。
使用特定于域的语言完全在Ruby中实现数据文件。
优点:简单易用。
缺点:用户创建的数据无法信任。
我也对那些我可能没有想过的不在该名单上的建议持开放态度。安全实现嵌入数据文件的脚本的最佳解决方案是什么?
编辑2011年12月23日:在DSL中添加了第四个选项,在顶部添加了“附录”以及其他想法/背景。
答案 0 :(得分:5)
您可以考虑使用Shikashi gem,它允许您创建沙箱并在单个对象上定义允许的方法调用的白名单。
答案 1 :(得分:1)
考虑使用jRuby而不是Ruby。最初实现Java是为了支持移动代码(早在机顶盒时代),并且有一个经过良好测试的security model/implementation,我怀疑它可以包装足够的jRuby以防止用户脚本/类与其他人一起造成破坏游戏系统。 jRuby也支持embedding,这可能有助于将游戏核心与用户应用程序分开,尽管我不知道它目前有多强大。
当然,jRuby是Ruby!