SAMP.Lua

Изначально эта библиотека задумывалась как простой апи исключительно для обработки сетевых пакетов, но в процессе было решешо, что лучше бы сделать её полноценной библиотекой для работы с сампом, в будущем это позволит избавить от необходимости использования SAMPFUNCS. Пока реализован только модуль, значительно упрощающий работу с пакетами, так что говорить сейчас будем о нём.

SAMP.Events
Этот модуль добавляет событийную обработку входящих и исходящих RakNet пакетов. Имеет удобный API, полностью кастомизируем, предоставляет те же возможности, что и обычные хуки: чтение, перезапись, игнорирование.


Использование
Простой пример обработки исходящего сообщения в чат:
Lua:
local sampev = require 'lib.samp.events'

function sampev.onSendChat(msg)
  print('You said: ' .. msg)
end
Да, настолько просто. Нужно лишь загрузить библиотеку и добавить функцию с соответствующими аргументами, вот и всё.
Перезапись данных в пакете настолько же проста, нужно лишь вернуть из функции все значения в том же порядке, занеся их в таблицу.
Lua:
function sampev.onSendChat(msg)
  return {'I said: ' .. msg}
end
Будет дописывать текст "I said:" в начало каждого отправляемого сообщения.
Если вернуть из функции false, то пакет будет проигнорирован клиентом. Этот код запретит серверу изменять позицию игрока:
Lua:
function sampev.onSetPlayerPos(position)
  print(string.format('Server tried to change your position to %0.2f %0.2f %0.2f', position.x, position.y, position.z))
  return false
end
Структуры всех пакетов находятся в файле events.lua.

Перезапись исходящих пакетов синхронизации слегка отличается от всех остальных - они не требуют возврата аргументов, а вместо этого данные перезаписываются как в обычной таблице lua. Это сделано для повышения производительности.
Пример перезаписи позиции в исходящих данных синхронизации игрока:
Lua:
function sampev.onSendPlayerSync(data)
  print('Original position:', data.position.x, data.position.y, data.position.z)
  data.position.x = 1337
  data.position.y = 1488
  data.position.z = 228
end
Это применимо только в событиях onSendPlayerSync, onSendVehicleSync, onSendPassengerSync, onSendAimSync, onSendUnoccupiedSync, onSendTrailerSync, onSendBulletSync, onSendSpectatorSync.
Структуры всех пакетов синхронизации находятся в файле synchronization.lua.


Примеры скриптов
AntiCarJack - перехват и игнорирование входящего RPC и пакета синхронизации
Bubble Sniffer - перехват и обработка входящего RPC
DerpCam - перезапись данных исходящего пакета синхронизации
Chat Bliss - перезапись, игнорирование и обработка исходящего RPC


Кастомизация
API структурирован так, что позволяет вносить в него любые изменения, не прибегая к изменению исходных файлов модулей.
Добавление своего обработчика для серверного пакета проигрывания звука:
Lua:
local sampev = 'lib.samp.events'
local raknet = 'lib.samp.raknet'
sampev.INTERFACE.INCOMING_RPCS[raknet.RPC.PLAYSOUND] = {'onPlaySound', {soundId = 'int32'}, {x = 'float'}, {y = 'float'}, {z = 'float'}}
И теперь в тот же файл можно добавить функцию для обработки события:
Lua:
function sampev.onPlaySound(sound, x, y, z)
-- добавляем сообщение в лог
print(string.format('Sound %d at coords %0.2f, %0.2f, %0.2f', sound, x, y, z))
-- и отключаем звук, запрещая дальнейшую обработку пакета
return false
end
Следует сразу разобрать код регистрации события, чтобы стало понятнее.
Lua:
sampev.INTERFACE. -- поле INTERFACE - это все экспортируемые элементы модуля
INCOMING_RPCS -- обращение к списку входящих RPC
[raknet.RPC.PLAYSOUND] -- обращение к элементу таблицы INCOMING_RPCS по индексу, в данном случае INCOMING_RPCS - это таблица, содержащая список структур всех входящих RPC, а raknet.RPC.PLAYSOUND - идентификатор требуемого RPC
= -- присваиваем ему новое значение - таблицу с информацией о событии и структурой пакета
{'onPlaySound', -- название события, функция события будет использовать это имя
-- структура пакета. каждый параметр должен быть заключен в отдельную таблицу, иметь название и тип в формате {названиеПараметра = 'тип'}
{soundId = 'int32'}, {coords = 'vector3d'}}
Очевидно, что INCOMING_RPCS - это не единственная таблица, их четыре:
INCOMING_RPCS - входящие RPC
OUTCOMING_RPCS - исходящие RPC
INCOMING_PACKETS - входящие пакеты
OUTCOMING_PACKETS - исходящие пакеты

Новый тип тоже можно добавить без изменения исходников библиотеки:
Lua:
events.INTERFACE.BitStreamIO.fvector3 = { -- название типа после последней точки
   read = function(bs) -- функция чтения. первый аргумент - битстрим
     local vec = {}
     vec.x = raknetBitStreamReadFloat(bs)
     vec.y = raknetBitStreamReadFloat(bs)
     vec.z = raknetBitStreamReadFloat(bs)
     return vec
   end,
   write = function(bs, value) -- функция записи
     raknetBitStreamWriteFloat(bs, value.x)
     raknetBitStreamWriteFloat(bs, value.y)
     raknetBitStreamWriteFloat(bs, value.z)
   end
}
В случае, если пакет имеет какую-то сложную структуру, не описываемую даже с помощью пользовательских типов, то вместо структуры можно передать функцию, которая будет обрабатывать данные. Например как это сделано для RPC InitGame:
Lua:
INCOMING_RPCS[RPC.INITGAME] = {'onInitGame', onInitGameReader, onInitGameWriter} -- второй и третий аргумент - это функции чтения и записи
Для большего количества примеров смотрите исходный код.

Что касается всей библиотеки в целом, то она ещё находится на зачаточной стадии и обсуждать кроме планов нечего. По сути она должна заменить собой основную часть SAMPFUNCS - моддинг сампа.

Скачать последнюю версию и следить за изменениями всегда можно на GitHub.
Установка: скачать samp.zip из последнего релиза и целиком скопировать папку 'samp' (не содержимое папки!) из архива в каталог 'moonloader/lib/'.

Любая помощь в разработке приветствуется, особенно с добавлением новых структур. Предложите Pull request на гитхабе или напишите в этой теме.

Ну и конечно же крохотное нано-спасибо hnnssy за помощь.
 
Последнее редактирование:

romacaddy

Известный
Проверенный
234
206
Тупо не выводит никакую информацию
PHP:
function SE.onShowTextDraw(textdrawId, data)
    sampAddChatMessage(string.format("boxColor: %d"), data.boxColor, 0xFFFFFF)
end

Лог Moonloader'a -
PHP:
[13:07:33.859360] (error)    TextDrawHelper: E:\GTASA\moonloader\chat bliss.lua:113: bad argument #2 to 'format' (no value)
[13:07:33.874361] (error)    TextDrawHelper: Script died due to error. (0195EB9C)

Lua:
function SE.onShowTextDraw(textdrawId, data)
    sampAddChatMessage(string.format("boxColor: %d", data.boxColor), 0xFFFFFF)
end
data.boxColor должен быть внутри string.format
 

Salik_Davince

Известный
37
3
Lua:
function SE.onShowTextDraw(textdrawId, data)
    sampAddChatMessage(string.format("boxColor: %d", data.boxColor), 0xFFFFFF)
end
data.boxColor должен быть внутри string.format
Спасибо, чет даже не заметил, по теме: Можно-ли не открывая диалог кидать информацию о Диалоге и его параметрах (Какой Лист и какая Кнопка нажата)?

Спасибо, чет даже не заметил, по теме: Можно-ли не открывая диалог кидать информацию о Диалоге и его параметрах (Какой Лист и какая Кнопка нажата)?
Как примерно такой вызов реализовать?? Что-бы Диалог даже не показывался и кидал информацию серверу.
PHP:
function sampev.onShowDialog(dialogId)
    if dialogId == 1 then
          sampev.onSendDialogResponse(.dialogId = 1, .button = 1, .listboxId = 2, .input = "");
          return false
    end
end
 
Последнее редактирование модератором:

FYP

Известный
Автор темы
Администратор
1,757
5,684
Как примерно такой вызов реализовать?? Что-бы Диалог даже не показывался и кидал информацию серверу.
PHP:
function sampev.onShowDialog(dialogId)
    if dialogId == 1 then
          sampev.onSendDialogResponse(.dialogId = 1, .button = 1, .listboxId = 2, .input = "");
          return false
    end
end
sampSendDialogResponse(int id, int button, int listitem, zstring input)
return false
 

Salik_Davince

Известный
37
3
@FYP, подкорректировать-бы RPC TextDrawShow - куча не состыковок, data.rotation - 3д вектор, кстати вообще с чего есть и rotation и position, за что вообще отвечает data.flags и data.letterColor? Нету куча информации, SetOutline и тд.
PHP:
Инфу можно взять тут - 
https://sampwiki.blast.hk/wiki/Category:Textdraw
 

Dark_Knight

Me, me and me.
Друг
4,056
2,075
Ты кто такой для начал и что тебе мешает самому отредактировать файл? И что по твоему это такое?
1.png
 

Salik_Davince

Известный
37
3
Это ты прикол? Я о чем и говорю, нужно подредактировать, нету в SA:MP'e LetterColor'a есть BGColor, Color, но нету letterColor'a!

p.s Что за флаги вообще и за что отвечают? (их нету в SA:MP'e) Можешь сразу ответить? Нет? Так я о чем!
 

Dark_Knight

Me, me and me.
Друг
4,056
2,075
В сетевом движке данные передаются так, а не как в павне ты можешь указать параметры. Это структура текстадрава, когда она приходит от сервера к клиенту. Если ты тут не видишь letterColor'a, то ты реально слепой.
 

NookieONE

Участник
128
1
function sampev.onServerMessage(color, text)
из-за этой строчки оишбка. HELP
 
Последнее редактирование:

Salik_Davince

Известный
37
3
В сетевом движке данные передаются так, а не как в павне ты можешь указать параметры. Это структура текстадрава, когда она приходит от сервера к клиенту. Если ты тут не видишь letterColor'a, то ты реально слепой.
Я тебя понял, только ты вот уже какой раз не понимаешь, вот именно letterColor'a нету в SA:MP'e.

UPD: Тебе будет наверное лень и может сейчас дойдет до тебя...
Вот нативы в SA:MP'e (И тут очень много не состыковок, НЕ СУЩЕСТВУЕТ в SA:MP'e letterColor'a и других. Но и НЕ ХВАТАЕТ некоторых нативок! (Посмотри сюда и в структуру!) -

  • TextDrawCreate: Create a textdraw.
  • TextDrawDestroy: Destroy a textdraw.
  • TextDrawColor: Set the color of the text in a textdraw.
  • TextDrawBoxColor: Set the color of the box in a textdraw.
  • TextDrawBackgroundColor: Set the background color of a textdraw.
  • TextDrawAlignment: Set the alignment of a textdraw.
  • TextDrawFont: Set the font of a textdraw.
  • TextDrawLetterSize: Set the letter size of the text in a textdraw.
  • TextDrawTextSize: Set the size of a textdraw box.
  • TextDrawSetOutline: Choose whether the text has an outline.
  • TextDrawSetShadow: Toggle shadows on a textdraw.
  • TextDrawSetProportional: Scale the text spacing in a textdraw to a proportional ratio.
  • TextDrawUseBox: Toggle if the textdraw has a box or not.
  • TextDrawSetString: Set the text in an existing textdraw.
 
Последнее редактирование:

Dark_Knight

Me, me and me.
Друг
4,056
2,075
Я тебя понял, только ты вот уже какой раз не понимаешь, вот именно letterColor'a нету в SA:MP'e.

UPD: Тебе будет наверное лень и может сейчас дойдет до тебя...
Вот нативы в SA:MP'e (И тут очень много не состыковок, НЕ СУЩЕСТВУЕТ в SA:MP'e letterColor'a и других. Но и НЕ ХВАТАЕТ некоторых нативок! (Посмотри сюда и в структуру!) -
Причем тут нативы в павн? Ты не сравнивай серверную часть и клиентскую. Есть только 4 RPC для работы с текстдравами в клиенте. Это RPC_ClickTextDraw, RPC_ScrTextDrawSetString, RPC_ScrShowTextDraw и RPC_ScrTextDrawHideForPlayer.
 
Последнее редактирование:

Dark_Knight

Me, me and me.
Друг
4,056
2,075
Окей. Если ты не понял, то эта библиотека для КЛИЕНТА, а не СЕРВЕРА.
 

FYP

Известный
Автор темы
Администратор
1,757
5,684
:facepalm:

@Salik_Davince неужели, блять, так сложно было засунуть этот ёбаный letterColor в переводчик и выяснить что это? letter - символ, color - цвет, letterColor - цвет символов, его значение и задаётся через TextDrawColor. data.flags это набор флагов текстдрава, туда входят параметры alignment, proportional и пара других.
это не несостыковки, такова структура пакета. и outline тоже есть, смотри внимательнее.

и причем тут нахуй уршадов? он не имеет ни малейшего отношения к SAMP.Lua и к тому же давно забанен на форуме.
 

Salik_Davince

Известный
37
3
Хорошо, я с чего взял то такой вопрос, т.e в структуре имеется data.color (подумал что это значение для TextDrawColor) и насчет флагов, можно как-то объяснить как брать значения т.e alignment, prop, и тд я просто незнаю, он идет как read.int8(bs)