Переход с Pawno на Lua. Часть 4 — server и client side. Чтобы пойти дальше, нам необходимо узнать о серверных и клиентских скриптах и об их различиях.
С этим понятием вы уже встречались в предыдущих уроках.
Грубо говоря — клиентские скрипты, это то, что может выполнятся только на стороне клиента. А серверные — только на стороне сервера.
В клиентских скриптах всегда определен игрок, и скрипт будет выполнятся только для этого игрока. В этом плюс клиентских скриптов — там в функциях не надо писать для какого игрока эта функция будет выполнятся.
Звучит сложновато, поэтому давайте разберем все это дело на примере создания иконок.
Если вы будете использовать эту функцию в серверной части, то вот, что вам придется делать:
Code
createBlip ( float x, float y, float z, [int icon=0, int size=2, int r=255, int g=0, int b=0, int a=255,
int ordering=0 *, float visibleDistance=99999.0, visibleTo = getRootElement()] )
А вот что в клиентской части:
Code
createBlip ( float x, float y, float z, [int icon=0, int size=2, int r=255, int g=0, int b=0, int a=255,
int ordering=0, float visibleDistance ] )
Что изменилось? Во втором примере нету visibleTo = getRootElement(), этот параметр отвечает за то, кому будет показываться иконка. А, как вы только что узнали, в клиентской части игрок уже определен, соответственно и иконка, создаваемая в клиенте, будет показываться только этому игроку.
Что бы вы поняли что к чему, вот еще один пример:
Забрать деньги у игрока:
Сервер
Code
takePlayerMoney ( player thePlayer, int amount )
Клиент
Code
takePlayerMoney ( int amount )
Нету thePlayer, параметра, который отвечает за то, у какого игрока забрать деньги.
Но есть такие функции, в которых игрока надо определять и для клиента и для сервера, например функция получить имя игрока:
Сервер
Code
getPlayerName(source)
Клиент
Code
getPlayerName(getLocalPlayer())
Функция getLocalPlayer () получает игрока этого клиентского ресурса. Это так же может пригодится в функциях, связанных с элементами или педами (пед — это, насколько я понял, модель игрока, то есть, педом может быть как игрок, так и NPC), например:
Code
setElementData ( getLocalPlayer(), “level”, 1 )
getLocalPlayer вам будет часто пригождаться, поэтому, чтобы вам меньше писать, предлагаю в начало каждого своего клиентского скрипта добавлять:
Code
localPlayer = getLocalPlayer()
И потом уже заместо getLocalPlayer использовать везде просто localPlayer. Есть функции, которые работают только в клиенте (например getLocalPlayer() работает только в клиенте) или только на сервере, вот примеры:
Пример сервера:
Code
giveWeapon ( source, 31, 200 )
То есть, если вы вставите эту функцию в клиентский скрипт, то она там работать не будет.
Пример клиента:
Code
guiCreateButton( 0.7, 0.1, 0.2, 0.1, "Output!", true )
То же самое, в сервере работать не будет. Но ведь довольно часто бывает, что надо из клиента вызвать сервервную функцию (или наоборот), для этого используют triggerServerEvent или triggerClientEvent.
Первая используется для вызова серверной функции из клиента, а вторая используется для вызова клиентской функции из сервера.
Полный код triggerServerEvent:
Code
triggerServerEvent ( ивент, элемент, который будет source сервеной функции, аргумент )
Пример:
В клиенте вводите это:
Code
function greetingCommand ( commandName )
triggerServerEvent ( "onGreeting", getLocalPlayer(), "Hello World!" )
end
addCommandHandler ( "greet", greetingCommand )
А в сервере это:
Code
function greetingHandler ( message )
outputChatBox ( "Сообщение от клиентской части: " .. message, source )
end
addEvent( "onGreeting", true )
addEventHandler( "onGreeting", getRootElement(), greetingHandler )
Здесь, когда вы вводите команду /greet, вам напишет:
Сообщение от клиентской части: Hello World! Полный код triggerClientEvent:
Code
triggerClientEvent ( для какого лемента вызваем, название ивента, какой элемент будет рутом, аргументы )
Пример:
В сервере вводите это:
Code
function greetingCommandOne ( source, commandName )
triggerClientEvent ( source, "onGreeting", getRootElement(), "Hello World!")
end
addCommandHandler ( "greet", greetingCommandOne )
А в клиенте это:
Code
function greetingHandler ( message )
outputChatBox ( "Сообщение от серверной части: " .. message )
end
addEvent( "onGreeting", true )
addEventHandler( "onGreeting", getRootElement(), greetingHandler )
Здесь, когда вы вводите команду /greet, вам напишет:
Сообщение от серверной части: Hello World! Что еще:
Все клиентские скрипты скачиваются игроку, следовательно он может их открыть.
Чтобы сервер знал, что этот скрипт у вас клиентский, надо добавлять в meta.xml
подробнее смотрите во втором уроке.
У меня бывает, что вызываемая через triggerClientEvent функция совершенно непонятно почему не работает.
Таки плюшки, как: GUI, замена моделей, проигрывание звука, работает только в клиентской части. P.S. Этот, и все остальные мои уроки написанны так, как я понимаю Lua и как мне удобно в нем работать
Ссылки:
Клиентские функции
Серверные функции
triggerClientEvent
triggerServerEvent