2015-08-29 16 views
0

Я разрабатываю сервер для многопользовательской игры, где я хочу дать каждому игроку свой поток Lua, который я бы хотел заполнить некоторыми уникальными глобалами, например. имя и идентификатор игрока. В принципе, я хочу иметь возможность устанавливать локальные переменные потока из главного приложения без какого-либо дополнительного кода в реальных сценариях, которые я пишу, которые я могу использовать в течение всего сеанса воспроизведения, всякий раз, когда я вызываю функцию , Возможно ли это с Lua?Местная переменная потока

// Example of how it naturally doesn't work 

var L = Lua.LuaLNewState(); 
Lua.LuaRegister(L, "print", WriteLine); 
dostring(L, "print('hello, world')", null); 

var x = Lua.LuaNewThread(L); 
Lua.LuaPushLiteral(x, "charId"); 
Lua.LuaPushNumber(x, 123); 
Lua.LuaRawSet(x, Lua.LUA_GLOBALSINDEX); 
dostring(x, "print('x1 '..charId)", null); // call to a function that uses charId 

var y = Lua.LuaNewThread(L); 
Lua.LuaPushLiteral(y, "charId"); 
Lua.LuaPushNumber(y, 456); 
Lua.LuaRawSet(y, Lua.LUA_GLOBALSINDEX); 
dostring(y, "print('y1 '..charId)", null); // call to a function that uses charId 

dostring(x, "print('x2 '..charId)", null); // I want this to still be 123 

Обновление: Мое приложение многопоточное, несколько игроков могут запускать сценарии одновременно. Мое понимание настройки среды в Lua заключается в том, что она меняет ее по всему миру, что не будет работать в моем случае.

+0

См. Также здесь: http://stackoverflow.com/questions/24356520/thread-locals-in-lua – siffiejoe

+0

Я понимаю, что изменение среды функции глобально. Возможно, мне следовало бы это разъяснить, мы не говорим о потокобезопасном приложении здесь, задавая среду функции перед вызовом, это не вариант, так как несколько потоков могут запускать скрипты одновременно. – Mars

+1

Код в ответе связанного сообщения заменяет глобальную среду исполняемого скрипта только один раз перед созданием любых сопрограмм. И даже это необязательно, если вы согласны с использованием 'TL.variablename' вместо простого' variablename' для доступа к локальной переменной потока. – siffiejoe

ответ

0

Вы используете существующий игровой движок? Если это так, вероятно, стоит использовать существующие библиотеки. Например, если вы используете LÖVE2D, вы можете использовать что-то вроде this или this.

Вы можете создавать отдельные среды с использованием setfenv или _ENV (в зависимости от версии Lua) и опционально использовать в них coroutines.

+0

Спасибо за ваш ответ, но на самом деле он не отвечает на мой вопрос. Мне не нужна клиентская библиотека, и я не уверен, что sefenv делает то, что я ищу. Если я изменю среду для функции в одном потоке, она изменит ее и на все остальные потоки, не так ли? – Mars

+0

С Lua 5.2 я понимаю, что каждая функция может иметь свою собственную среду. Если вам нужны разные среды в разных потоках, можно создать отдельные функции, по одному для каждого потока (или обернуть общую функцию в зависимости от потока) и т. Д.)? – Aubergine18

+0

Каждая функция может иметь свою собственную среду, да, но я понимаю, что изменение среды функции глобально. Возможно, мне следовало бы это разъяснить, мы не говорим о потокобезопасном приложении здесь, задавая среду функции перед вызовом, это не вариант, так как несколько потоков могут запускать скрипты одновременно. – Mars

0

Я нашел еще один способ добиться этого, который мне кажется менее «взломанным». Lua имеет константу, называемую LUAI_EXTRASPACE, которая используется для добавления состояния Lua с заданным количеством байтов. Я теперь использую обычную библиотеку C Lua, которую я скомпилировал, где я изменил эту константу на 4, чтобы сделать пространство перед фактической структурой состояния Lua, чтобы сохранить ссылку на объект в моем приложении, чтобы я мог запрашивать когда мне это нужно в функции.

магазин

var NL = Lua.lua_newthread(L); 
unsafe 
{ 
    var ptr = (int*)NL.ToPointer(); 
    ptr -= 8; 
    *ptr = index; 
} 
return NL; 

Получить

var index = 0; 
unsafe 
{ 
    var ptr = (int*)L.ToPointer(); 
    ptr -= 4; 
    index = *ptr; 
} 
var obj = objects[index]; 

Хотя это не позволяет мне свободно толкать переменные, я могу легко писать функции, которые делают использование хранимой междунар, чтобы получить объект из массив и передать значения из него в Lua. В качестве альтернативы, если вам нужно всего несколько конкретных переменных, вы также можете сделать больше места.

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

 Смежные вопросы

  • Нет связанных вопросов^_^