寻找良好的服务器端语言,允许玩家上传可执行的代码

2024-03-18

我有一个想要编写的程序的想法,但哪种语言最好是我的问题。

如果我有一款赛车游戏,并且希望允许用户提交新的交互式 3D 赛道(想想 Speed Racer 电影中的赛道)、车辆及其自动驾驶车辆的代码,那么他们将创建 AI对于他们的汽车来说,这将使汽车能够确定如何处理危险。

因此,我需要一种运行速度快的语言,并且作为服务器拥有的所有可能的种族及其各种状态的世界地图的一部分。

例如,我很好奇这是否是考虑在 Scala 中创建 DSL 的好理由?

我不想重新启动应用程序来加载新的 dll 或 jar 文件,因此许多编译语言将成为问题。

我对 Linux 或 Windows 持开放态度,对于大多数脚本语言、F#、Scala、Erlang 或我可以使用的大多数 OOP 都持开放态度。

用户将能够监控他们的车辆的运行情况,如果他们为该车上传了多个人工智能,当遇到某些障碍时,他们应该能够根据需要将一个人工智能程序更换为另一个。

更新:到目前为止,解决方案是 javascript、使用 V8 和 Lua。

我很好奇这是否适合 DSL(实际上是 3 个独立的 DSL)。第一个用于创建赛道,另一个用于控制赛车,第三个用于创建新车。

如果是这样,Haskell、F# 或 Scala 是不错的选择吗?

Update:让不同的部分以不同的语言结束有意义吗?例如,如果 Erlang 用于控制汽车,Lua 用于汽车本身,以及动画赛道?


你的情况听起来很适合 Lua。

  • 你需要沙箱:这是Lua 很容易做 http://lua-users.org/wiki/SandBoxes。您只需通过覆盖或删除来初始化用户环境os.execute例如,命令,用户无法再访问该功能。
  • 您想要快速:查看一些Lua 与其他语言的基准测试 http://benchmarksgame.alioth.debian.org/u64q/which-programs-are-fastest.html.
  • 假设您需要与另一种语言进行互操作。至少 Lua 很容易(在我看来)嵌入到 C 或 C++ 中。我没用过Lua接口 http://luaforge.net/projects/luainterface/,但这就是 C# 绑定。
  • Lua 具有一阶函数,因此应该很容易即时交换函数。
  • Lua 在一定程度上支持OOP http://www.lua.org/pil/28.3.html与元表。
  • Lua的主要数据结构是table http://lua-users.org/wiki/TablesTutorial(关联数组)非常适合稀疏数据结构,例如与世界地图集成。
  • Lua 有非常规则的语法。分号或缩进没有什么有趣的技巧,所以当你的用户学习你的语言时,他们就少了一件需要学习的事情——更不用说,使用一种记录良好的语言会带走你必须做的一些工作。自己记录的条款。

此外,正如 @elviejo 在评论中指出的那样,Lua 已经在许多游戏中用作脚本语言。如果不出意外的话,按照您所描述的方式使用 Lua 肯定有一些先例。而且,正如 @gmonc 提到的,您的用户有可能已经在另一款游戏中使用过 Lua。


As far as how to integrate with Lua: generally, your users should simply need to upload a Lua script file. To grossly oversimplify, you might provide the users with available functions such as TurnLeft, TurnRight, Go, and Stop. Then, the users would upload a script like
Actions = {} -- empty table, but you might want to provide default functions 
function Actions.Cone()
    TurnLeft()
end

function Actions.Wall()
    Stop()
    TurnRight()
    TurnRight()
    Go()
end

然后在服务器端,您可能会用Go()。然后,当他们的车到达锥体时,你打电话给他们Actions.Cone()功能;一堵墙通向Actions.Wall()函数等。此时,您(希望)已经对 Lua 环境进行沙箱化,因此您可以简单地执行他们的脚本,甚至无需考虑错误检查 - 如果他们的脚本导致错误,您没有理由不能将错误直接传递给用户。如果有aren't任何错误,lua_State服务器代码中应包含汽车的最终状态。


更好的例子

这是一个独立的 C 文件,它从 stdin 获取 Lua 脚本并像我上面解释的那样运行它。游戏中你会遇到地面、栅栏或树枝,你必须分别奔跑、跳跃或躲避才能通过。您通过 stdin 输入 Lua 脚本来决定如何反应。源代码有点长,但希望它很容易理解(除了 Lua API 需要一段时间才能习惯)。这是我过去30分钟的原创作品,希望对你有帮助:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

#define FAIL 0
#define SUCCESS 1

/* Possible states for the player */
enum STATE {
    RUNNING,
    JUMPING,
    DUCKING
};

/* Possible obstacles */
enum OBSTACLE {
    GROUND,
    FENCE,
    BRANCH
};

/* Using global vars here for brevity */
enum STATE playerstate = RUNNING;
enum OBSTACLE currentobstacle = GROUND;

/* Functions to be bound to Lua */
int Duck(lua_State *L)
{
    playerstate = DUCKING;
    return 0; /* no return values to Lua */
}

int Run(lua_State *L)
{
    playerstate = RUNNING;
    return 0;
}

int Jump(lua_State *L)
{
    playerstate = JUMPING;
    return 0;
}

/* Check if player can pass obstacle, offer feedback */
int CanPassObstacle()
{
    if ( (playerstate == RUNNING && currentobstacle == GROUND) )
    {
        printf("Successful run!\n");
        return SUCCESS;
    }
    if (playerstate == JUMPING && currentobstacle == FENCE)
    {
        printf("Successful jump!\n");
        return SUCCESS;
    }
    if (playerstate == DUCKING && currentobstacle == BRANCH)
    {
        printf("Successful duck!\n");
        return SUCCESS;
    }
    printf("Wrong move!\n");
    return FAIL;
}

/* Pick a random obstacle */
enum OBSTACLE GetNewObstacle()
{
    int i = rand() % 3;
    if (i == 0) { return GROUND; }
    if (i == 1) { return FENCE; }
    else { return BRANCH; }
}

/* Execute appropriate function defined in Lua for the next obstacle */
int HandleObstacle(lua_State *L)
{
    /* Get the table named Actions */
    lua_getglobal(L, "Actions");
    if (!lua_istable(L, -1)) {return FAIL;}
    currentobstacle = GetNewObstacle();

    /* Decide which user function to call */
    if (currentobstacle == GROUND)
    {
        lua_getfield(L, -1, "Ground");
    }
    else if (currentobstacle == FENCE)
    {
        lua_getfield(L, -1, "Fence");
    }
    else if (currentobstacle == BRANCH)
    {
        lua_getfield(L, -1, "Branch");
    }

    if (lua_isfunction(L, -1))
    {
        lua_call(L, 0, 0); /* 0 args, 0 results */
        return CanPassObstacle();
    }
    return FAIL;
}

int main()
{
    int i, res;
    srand(time(NULL));
    lua_State *L = lua_open();

    /* Bind the C functions to Lua functions */
    lua_pushcfunction(L, &Duck);
    lua_setglobal(L, "Duck");

    lua_pushcfunction(L, &Run);
    lua_setglobal(L, "Run");

    lua_pushcfunction(L, &Jump);
    lua_setglobal(L, "Jump");

    /* execute script from stdin */
    res = luaL_dofile(L, NULL); 
    if (res)
    {
        printf("Lua script error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    for (i = 0 ; i < 5 ; i++)
    {
        if (HandleObstacle(L) == FAIL)
        {
            printf("You failed!\n");
            return 0;
        }
    }

    printf("You passed!\n");

    return 0;
}

在 GCC 上构建上述内容gcc runner.c -o runner -llua5.1 -I/usr/include/lua5.1.

几乎唯一每次都会成功通过的 Lua 脚本是:

Actions = {}

function Actions.Ground() Run() end
function Actions.Fence() Jump() end
function Actions.Branch() Duck() end

也可以写成

Actions = {}
Actions.Ground = Run
Actions.Fence = Jump
Actions.Branch = Duck

使用好的脚本,您将看到如下输出:



Successful duck!
Successful run!
Successful jump!
Successful jump!
Successful duck!
You passed!
  

如果用户尝试恶意操作,程序将简单地提供错误:



$ echo "Actions = {} function Actions.Ground() os.execute('rm -rf /') end" | ./runner 
PANIC: unprotected error in call to Lua API (stdin:1: attempt to index global 'os' (a nil value))
  

如果移动脚本不正确,用户将看到他执行了错误的移动:



$ echo "Actions = {} Actions.Ground = Jump; Actions.Fence = Duck; Actions.Branch = Run" | ./runner 
Wrong move!
You failed!
  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

寻找良好的服务器端语言,允许玩家上传可执行的代码 的相关文章

  • 现在N层架构意味着什么?

    从传统意义上讲 N 层意味着将应用程序分成 层 并将每个 层 放在不同的服务器上 这样做至少有 3 个原因 维护 a 代码维护 更容易进行错误修复和功能添加 b 硬件维护 关闭一台服务器不会中断其他层的服务 性能 一台服务器的速度通常不够快
  • BL 服务:异常还是方法结果?

    最好的方法是什么 为什么 V1 try var service IoC Resolve
  • 前端和后端应该由不同的控制器处理吗?

    在我之前的学习项目中 我总是使用单个控制器 但现在我想知道这是否是好的做法 甚至总是可能的 在所有 RESTful Rails 教程中 控制器都有一个show an edit and an index看法 如果授权用户登录 则edit视图变
  • Appengine 网站的架构指南?

    我使用 PHP 创建了难以维护的网站 因为它很容易做一些又快又脏的事情 我不想在 Google 的 appengine 上使用 Python Django 做同样的事情 使用 Django 和 appengine 创建网站有什么好的架构参考
  • 异常与临时类型。什么情况下容易摔倒?

    我在从事 MVC 3 项目时正在阅读一本企业应用程序开发的书 我目前正在决定如何处理异常 以前我会让异常在堆栈中冒泡 然后在最高层处理它 这本书建议在域模型中创建一个临时类并返回它 例如 public sealed class Missin
  • Hub、Spoke 和 ESB 之间的区别

    我知道对此已经有一个很好的问题 但它并没有真正回答我正在寻找的问题 据我了解 1 两者都用作应用程序之间的中心焦点2 两者都可以在服务 应用程序之间使用路由 中介 转换等 但我真正能看到的唯一区别是 中心辐射型通常有许多不同的格式进入中心
  • 在 MVC 中拥有巨大的控制器或许多控制器更好?

    我们正在 ASP NET MVC 中构建一个相当大的 HR 应用程序 到目前为止 我们的控制器变得相当大 例如 我们有一个员工控制器 并且包含所有员工视图 个人信息 员工扣除额 家属等 每个视图都可能有多个操作或子视图 例如 CRUD 每个
  • ASP.NET MVC 和 Web 服务

    向我的 ASP NET MVC 项目添加 Web 服务是否会破坏 MVC 的整个概念 该 Web 服务 WCF 依赖于我的 MVC 项目中的模型层来与后端进行通信 因此在我看来 它需要成为 MVC 解决方案的一部分 我应该将其添加到控制器层
  • 宏定义确定大端还是小端机?

    是否有一行宏定义来确定机器的字节顺序 我正在使用以下代码 但将其转换为宏会太长 unsigned char test endian void int test var 1 unsigned char test endian unsigned
  • 如何建立一个类似Jira的SaaS网站?

    任何人都知道如何构建单租户 SaaS 应用程序 例如 Jira Wordpress com 等 其中每个客户都有一个单独的站点 但托管在公司服务器上 网络上似乎有很多关于多租户 SaaS 应用程序以及如何在 Heroku Openshift
  • 使用 Google Cloud Functions 实现微服务的 API 网关

    Inputs 例如 我们有一些服务 账户服务 产品服务 支付服务 每项服务都是一个单独的 Google Cloud Function 每个服务都有自己的 HTTP API 例如 账户服务有 https REGION FUNCTIONS PR
  • 与云无关的架构? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在对一个新解决方案进行一些架构工作 该解决方案最初将在 Windows Azure 中运行 不过 我希望解决方案 或至少是架构 设计 与云无
  • 你现在在做MDA(模型驱动架构)吗?如果是这样,您使用什么工具,效果如何?

    模型驱动架构是这样一种想法 您创建模型 以一种不依赖任何 或至少大多数 实现技术的方式表达您需要解决的问题 然后为一个或多个特定平台生成实现 人们声称 在更高的抽象级别上工作更加强大和高效 此外 您的模型比技术更长寿 因此 当您的第一语言
  • 在 DDD 中,表示层可以同时使用 Repository 和 Service 类吗?

    如果表示层只应该使用服务 那么服务类必须公开存储库已实现的相同方法 以使它们可供表示层使用 这似乎是错误的 有人可以帮我澄清一下吗 我敢打赌 这似乎是错误的 因为您实际上并不需要这种抽象级别 应用服务有facades http en wik
  • C:epoll和多线程

    我需要创建专门的 HTTP 服务器 为此我计划使用 epoll sycall 但我想利用多个处理器 核心 但我无法提出架构解决方案 ATM我的想法如下 使用自己的epoll描述符创建多个线程 主线程接受连接并将它们分配给线程epoll 但还
  • 使用 C# 作为我的 DSL——这可能吗?如果可以,如何实现?

    是否可以使用 C 作为 DSL其中 C 源代码由最终用户在 TextBox 中编辑 在应用程序运行时编译 然后由已运行的应用程序调用 我问这个问题是因为在接下来的几个月里 我将需要实现一个简单的数学运算 DSL 类似于 Rachel Lim
  • socket.io 广播功能 & Redis pub/sub 架构

    如果有人能帮助我解决一个小疑问 我将不胜感激 使用socket io广播功能和在Redis上使用pub sub设计架构有什么区别 例如 在另一个示例中 node js 服务器正在侦听 socket io 针对 键 模型 todo 和值 数据
  • “if”在 ASP.NET MVC View (.aspx) 文件中被认为有害?

    我记得看到一个博客 或其他内容 说你不应该在 ASP NET MVC 的 aspx 文件中使用 但我不记得它说的替代方案是什么 有人记得看过这个并指出我吗 基本上 这意味着您的视图中不应该有大量的 if 语句 您的控制器和视图模型应该能够处
  • 使用 LINQ to SQL 的 .NET 架构的最佳设计实践(DAL 必要吗?我们真的可以使用 POCO吗?要采用的设计模式吗?)

    我避免在 net arch n 层架构上编写看起来像是另一个线程的内容 但请耐心等待 希望我和其他人一样 在选择用于企业应用程序的架构时 考虑到当今的趋势和新兴技术 仍然没有 100 满意或不清楚应采取的最佳方法 我想我正在寻求大众社区对方
  • 关于多客户端和可定制 Web 应用程序的架构所需的建议[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐

  • 如何在自定义验证属性中获取/注入服务

    我们使用 NET Core 3 1 5 这是一个 Blazor 服务器应用程序 我们有一个 ValidationAttribute 并需要访问外部服务来验证对象 ValidationAttribute 有 IsValid 方法 protec
  • 有没有办法在 C# 中修改进程 DACL

    我有更改进程 DACL 的遗留 C 代码 并尝试使用 NET 3 5 中的托管代码类 我在网上找到了代码 其中有人创建了一个 SetAclOnServices 类 该类扩展了服务的 NativeObjectSecurity 类 我认为我可以
  • jQuery 数据表中的列排序

    我已经了解了 jQuery 数据表插件中的列排序以及控制它的各种方法 我有一个查询是否可以通过单击上箭头图标将按升序和下箭头图标进行排序的方式控制排序会按降序排序吗 有两种方法可以做到这一点 具体取决于datatables版本 编辑数据表版
  • 如何在Python中将一个对象的所有属性复制到另一个对象?

    在Python中 是否有一个库方法可以复制同一类的两个 已经存在的 实例之间的所有属性 我的意思是 类似 Apache Commons 的东西PropertyUtilsBean copyProperties Try destination
  • ActiveRecord 查询比直接 SQL 慢得多?

    我一直致力于优化项目的数据库调用 我注意到下面两个相同的调用之间的性能存在 显着 差异 connection ActiveRecord Base connection pgresult connection execute SELECT S
  • 当我“推”到 Bitbucket 时,可以从 VPS 中“拉”一个钩子

    我正在 Bitbucket 中管理我的 WordPress 模板 每次我push主题 我必须登录我的 VPS 服务器并且pull回购协议 我想自动完成 如果我自己运行 git daemon 我找到了一个解决方案 推送到服务器后执行自动拉取请
  • 基于现有模板生成Word文档的最佳方法是什么

    TL DR 我可以使用 NET 生成 Word 文档 如 XAML ItemTemplates 吗 我发现很难找到一个满足我所有要求的解决方案 所以我想我会把它扔到 stackoverflow 希望有人能指导我 非常感谢 简单来说 我需要根
  • 如何根据条目的长度过滤 pandas 数据框

    在 pandas 数据框中 我有一个字段 amp 应由长度为 495 的列表填充 是否有一种 pandas ic 方法可以快速过滤此长度 使得具有字段 amp 的所有行不等于 495被丢弃 I tried df len df amp 495
  • 如何将 SQL 查询与不同的表达式结合起来?

    我的三个查询已经达到了我的 SQL 知识的顶峰 Microsoft SQL 2005 如果这很重要 现在我需要将它们组合成一个查询 并将所有值放在一行上 我的实际查询如下 但我认为如果我在这里提供一个简单的版本会更容易 查询一 Provid
  • 尝试覆盖 Hive 分区时写入 __HIVE_DEFAULT_PARTITION__ 的行已损坏

    当尝试使用 Spark 2 3 覆盖 Hive 表中的分区时 我看到一些非常奇怪的行为 首先 我在构建 SparkSession 时设置以下设置 config spark sql sources partitionOverwriteMode
  • XmlPullParser:获取包含 XML 标签的内部文本

    假设您有一个如下所示的 XML 文档
  • 有什么方法可以使用 boto3 直接将文件写入 S3 吗?

    我编写了一个 python 脚本来处理非常大的文件 总共几 TB 我将在 EC2 实例上运行该脚本 之后 我想将处理后的文件存储在 S3 存储桶中 目前 我的脚本首先将数据保存到磁盘 然后将其上传到S3 不幸的是 考虑到等待实例首先写入磁盘
  • Google PageSpeed 用户代理的名称是什么?

    这一页 https developers google com speed docs insights faq whyonlinediff表示它使用自定义用户代理 但没有提及名称 如果用户代理来自 PageSpeed 我希望能够运行一些逻辑
  • VS2013测试代理和控制器不通信

    我有一个运行 VS2013 负载测试控制器的 Windows Azure VM 和另一个运行 2013 负载测试代理的 Azure VM 我一直无法让两人成功沟通 我将每个虚拟机的主机名和 IP 添加到另一个虚拟机的 HOSTS 文件中 我
  • 依赖注入上下文中的组合根是什么?

    我正在探索依赖注入和术语成分根到处都在使用 那么它是什么 组合根是应用程序中使用依赖项注入容器组合应用程序的对象图的单个位置 尽管如何完成此操作无关紧要 它可以使用容器 也可以使用手动完成 pure DI http blog ploeh d
  • 是否可以在 HTML 中创建多级有序列表? [复制]

    这个问题在这里已经有答案了 我要这个 1 Main 1 1 sub1 1 2 sub2 2 Main2 2 1 sub3 可以在 HTML 中做到这一点吗 谢谢 这个解决方案对我有用 hide original list counter o
  • 我什么时候使用像 Paxos 这样的共识算法,什么时候使用像向量时钟这样的算法?

    我已经阅读了很多有关保证分布式系统中节点之间一致性的不同策略的文章 但我在弄清楚何时使用哪种算法时遇到了一些麻烦 我会在什么样的系统中使用矢量时钟之类的东西 哪个系统最适合使用 Paxos 之类的东西 两者是互相排斥的吗 有一个由 2 个节
  • Laravel 有许多多对多对一雄辩

    我没有太多运气以 Laravel 的方式解决这个问题 所以我提出两个问题 假设我有一辆汽车 并且该汽车可以有许多特征 但该特征也按特征类型分隔 我如何返回所述汽车的所有特征 分隔特征类型 我有四个表 listings features 是数
  • 调整 UISearchDisplayController 变暗黑色覆盖层的大小

    单击搜索栏后 有人知道如何过度调整暗黑色的大小吗 当我单击 取消 时 我遇到问题 表格视图将消耗然后动画消失 我用它来调整我的结果表视图的大小 void searchDisplayController UISearchDisplayCont
  • 寻找良好的服务器端语言,允许玩家上传可执行的代码

    我有一个想要编写的程序的想法 但哪种语言最好是我的问题 如果我有一款赛车游戏 并且希望允许用户提交新的交互式 3D 赛道 想想 Speed Racer 电影中的赛道 车辆及其自动驾驶车辆的代码 那么他们将创建 AI对于他们的汽车来说 这将使