Поиск хорошего языка серверной стороны, который позволит плеерам загружать код, который может быть выполнен

Я начал использовать рубин-activedirectory и даже расширил его несколько вещей, разместив judy-activedirectory в GitHub.

Выполнение следующего повторения, я обнаружил, что ActiveLdap имеет намного лучшую кодовую базу, и я серьезно собираюсь переключаться на него. У кого-либо есть личный опыт с этим?

6
задан James Black 26 October 2009 в 20:59
поделиться

5 ответов

Your situation sounds like a good candidate for Lua.

  • You need sandboxing: This is easy to do in Lua. You simply initialize the users' environment by overwriting or deleting the os.execute command, for instance, and there is no way for the user to access that function anymore.
  • You want fast: Check out some of the Lua benchmarks against other languages.
  • Assumably you need to interoperate with another language. Lua is very easy (IMO) to embed in C or C++, at least. I haven't used LuaInterface, but that's the C# binding.
  • Lua has first-order functions, so it should be easy to swap functions on-the-fly.
  • Lua supports OOP to some extent with metatables.
  • Lua's primary data structure is the table (associative array) which is well-suited to sparse data structures like integrating with a world map.
  • Lua has a very regular syntax. There are no funny tricks with semicolons or indentation, so that's one less thing for your users to learn when they are picking up your language -- not to mention, using a well-documented language takes away some of the work you have to do in terms of documenting it yourself.

Also, as @elviejo points out in a comment, Lua is already used as a scripting language in many games. If nothing else, there's certainly some precedent for using Lua in the way you've described. And, as @gmonc mentions, there is a chance that your users have already used Lua in another game.


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 в песочнице, поэтому вы можете просто выполнить их сценарий, даже не обращая внимания на проверку ошибок - если их сценарий приводит к ошибке, нет причин, по которым вы не можете передать ошибку напрямую пользователю. И если там нет ошибок, lua_State в коде вашего сервера должен содержать окончательное состояние их машины.


Лучший пример

Вот автономный файл C, который берет сценарий Lua из стандартного ввода-вывода и запускает его, как я объяснил выше. Игра состоит в том, что вы встретите землю, забор, или Ветвь, и вы должны соответственно Бежать, Прыгать или Пригнуться, чтобы пройти. Вы вводите сценарий 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!
32
ответ дан 8 December 2019 в 02:09
поделиться

Почему не JavaScript или EcmaScript? Google V8 - действительно хороший способ сделать это в песочнице. Я помню, как это было очень легко. Конечно, вам придется написать для него несколько привязок.

10
ответ дан 8 December 2019 в 02:09
поделиться

Я делал раньше в MMO, вы знаете, сценарии ответа NPC использовали python, в то время как он находится в структуре C ++, скажем, любое действие, связанное с NPC, запустит структуру для запуска сценария python (конечно, интерфейс C-python, а не вызов оболочки, такой как "python /script/run.py"). Сценарии являются заменяемой средой выполнения, хотя игроку или администратору игры требуется, чтобы он выдал команду для выполнения обновления, но в любом случае программа игрового сервера не требуется перезапускать.

На самом деле я забыл, что нужно ли выполнять обновление, выполнив команду "требовалось или не требовалось для новой среды выполнения сценария .. 2 года назад ... но я думаю, что это подходит для вас.

1
ответ дан 8 December 2019 в 02:09
поделиться

Я бы порекомендовал Dot Net по нескольким причинам:

Игроки могут выбирать, на каком языке они реализуют свои решения: C #, IronPython, VB.NET, Boo и т. Д., Но ваша среда выполнения не будет ' t Care - он просто динамически загружает сборки точечных сетей в свою песочницу. Но это дает вашим игрокам возможность выбрать свой любимый язык. Это побуждает игроков получать удовольствие от игры, а не некоторые игроки решают не участвовать, потому что им просто не нравится выбранный вами язык. Ваша общая структура, вероятно, будет на C #, но код игроков может быть на любом языке Dot Net.

Песочница и динамическая загрузка очень развиты в Dot Net. Вы можете загрузить сборки игроков в свои собственные изолированные домены приложений, которые работают с частичным доверием. Вам не придется перезапускать процесс контейнера для загрузки и выгрузки этих доменов приложений.

Игрокам рекомендуется «играть» в эту игру, потому что язык (какой бы язык Dot Net они ни выбрали) не только полезен для написания сценариев игры, но и может привести к настоящей карьере в отрасли. Выполнение поиска работы для "C #" дает, например, на много больше совпадений, чем для "Lua" или "Haskell". Таким образом, игра доставляет удовольствие не только молодым игрокам, но и помогает им овладеть действительно полезными, востребованными навыками, которые впоследствии могут принести им деньги. Это большой стимул к участию в этой игре.

Скорость исполнения огромна. В отличие от некоторых альтернатив, таких как Lua, это скомпилированный код, который хорошо известен своей отличной производительностью даже в играх в реальном времени. (См., Например, Unity3d).

Игроки могут использовать MonoDevelop на Mac и Linux, или они могут использовать Visual Studio Express бесплатно от Microsoft, или они могут использовать старый добрый блокнот и командную строку. Отличие от представленных здесь альтернатив состоит в том, что зрелые современные IDE доступны, если игроки захотят их использовать.

DSL не кажется хорошей идеей для части проблемы, связанной с ИИ, просто потому, что внедрение ИИ для транспортных средств является от игроков потребуется много творческого решения проблем. С помощью DSL вы ограничиваете их только тем способом, которым вы определили проблему, когда задумались над ней. Умные игроки с полной платформой, такой как Dot Net (или некоторые другие упомянутые варианты), могут иметь радикально новые и инновационные решения некоторых проблем AI, которые вы никогда не предвидели. С правильными инструментами Эти игроки могут реализовать сумасшедшие обучающие программы или небольшие нейронные сети, или неизвестно что, чтобы реализовать свой ИИ. Но если вы зафиксируете их в упрощенном DSL, может не быть большого разнообразия в реализациях ИИ разных игроков (потому что их набор доступных выражений идей намного меньше).

Что касается других частей проблемы, таких как определение треков, DSL может подойти. Тем не менее, я бы снова склонился к одному из более простых языков Dot Net, например Boo, просто чтобы у вас был единый технический стек для всего проекта.

Реализации ИИ (потому что их набор доступных выражений идей намного меньше).

Для других частей проблемы, таких как определение треков, DSL может подойти. Тем не менее, я бы снова склонился к одному из более простых языков Dot Net, например Boo, просто чтобы у вас был единый технический стек для всего проекта.

Реализации ИИ (потому что их набор доступных выражений идей намного меньше).

Для других частей проблемы, таких как определение треков, DSL может подойти. Тем не менее, я бы снова склонился к одному из более простых языков Dot Net, например Boo, просто чтобы у вас был единый технический стек для всего проекта.

2
ответ дан 8 December 2019 в 02:09
поделиться

Рассмотрим Erlang:

  • Вам нужна песочница / DSL: вы можете написать "генераторы синтаксического анализатора" для очистки доступа к критическим / уязвимым системным вызовам. Стандартный компилятор можно "легко" расширить с помощью этой функциональности.

  • Вам необходимо детальное планирование: у вас есть некоторый контроль над этим также при условии, что вы запускаете каждого «пользователя» в отдельных эмуляторах. Может быть, у вас получится лучше, но мне придется копать больше. Помните, что планирование - O (1): -)

  • Вам нужно разделить ресурсы между вашимиигроки »(думаю, если я правильно понял): Erlang не имеет общего состояния, поэтому это помогает с самого начала. Вы можете легко создать несколько супервизоров, которые будут следить за потреблением ресурсов игроками и т. д. См. также ссылку на пункт выше (много ручки для управления эмулятором).

  • Вам нужна горячая замена кода: Erlang был разработан для этого с самого начала

  • Вам нужно масштабирование: Erlang хорошо масштабируется с помощью SMP, и поскольку он основан на передаче сообщений с бесшовным интерфейсом -машинная связь, вы можете масштабироваться по горизонтали

  • Вы можете оптимизировать критические пути с помощью драйверов C

  • Интегрированная функция «супервизора» для корректного перезапуска «пользователей»

Ульф Вигер на параллелизме

1
ответ дан 8 December 2019 в 02:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: