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 за помощь.
 
Последнее редактирование:

Garrus

Известный
159
20
Обработчик килл-листа будет выглядеть так? Вроде работает, но через время игра почему-то крашится.
Lua:
sampev.INTERFACE.INCOMING_RPCS[raknet.RPC.DEATHMESSAGE] = {'onDeathMessage', {killerId = 'int16'}, {playerId = 'int16'}, {reason = 'int8'}}

function sampev.onDeathMessage(killerId, playerId, reason)
print(killerId, playerId, reason)
end

К примеру, после выхода с AFK, в логе SF следующее:
[15:20:25] SAMPFUNCS v5.3.3 release #19 (SA-MP 0.3.7) loaded. Base address: 0x042B0000.
[15:20:25] Compiled: Aug 8 2016 13:19:58
[15:20:25] Initializing opcodes...
[15:20:25] Opcodes initialized successfully. Total opcodes count: 382.
[15:20:27] samp.dll base addres: 0x02FA0000
[15:20:27] Installing hooks:
[15:20:27] Hook command process input installed.
[15:20:27] Hook on dialog response installed.
[15:20:27] Hook init netgame installed.
[15:20:27] Hook QuitGameHook installed.
[15:20:27] All hooks installed.
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Session started.
[15:20:42] {C0C0C0}[ML] {C0C0C0}
MoonLoader v.021-alpha loaded.
[15:20:42] {C0C0C0}[ML] {C0C0C0}Developers: FYP, hnnssy, EvgeN 1137

[15:20:42] {C0C0C0}[ML] {C0C0C0}© BlastHack Team, 2016
[15:20:42] {C0C0C0}[ML] {C0C0C0}https://www.blast.hk/moonloader/

[15:20:42] {C0C0C0}[ML] {A9EFF5}(info) {C0C0C0}Working directory: D:\Games\San Andreas Multiplayer\moonloader
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Installing pre-game hooks...
[15:20:42] {C0C0C0}[ML] {C0C0C0}OK.
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Loading script 'D:\Games\San Andreas Multiplayer\moonloader\Script.lua'...
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {E0E0E0}Script: {C0C0C0}Loaded successfully.
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Loading script 'D:\Games\San Andreas Multiplayer\moonloader\reload_all.lua'...
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {E0E0E0}ML-ReloadAll: {C0C0C0}Loaded successfully.
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Loading script 'D:\Games\San Andreas Multiplayer\moonloader\SF Integration.lua'...
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {E0E0E0}SAMPFUNCS Integration: {C0C0C0}Loaded successfully.
[15:20:42] {C0C0C0}[ML] {FA9746}(system) {C0C0C0}Installing post-load hooks...
[15:20:42] {C0C0C0}[ML] {C0C0C0}OK.
[15:20:43] Direct3DDevice9 hook installed.
[15:20:44] Hook RakPeer::HandleRPCPacket installed.
[15:20:44] Initializing SAMP data...
[15:20:44] Info initialized.
[15:20:44] Pools initialized.
[15:20:44] Player pool initialized.
[15:20:44] Vehicle pool initialized.
[15:20:44] Chat initialized.
[15:20:44] Input initialized.
[15:20:44] Death list initialized.
[15:20:44] Dialog initialized.
[15:20:44] Misc data initialized.
[15:20:44] Scoreboard initialized.
[15:20:44] RakNet initialized.
[15:20:44] ==========================================
[15:20:44] SAMPFUNCS v5.3.3 release #19 (SA-MP 0.3.7)
Compiled: Aug 8 2016 13:18:13

Author: FYP
Active developers: FYP, SR_Team, EXPORT

Past developers and special thanks:
MogAika, urShadow, legend2360, NarutoUA, Dark_Knight

Website: https://www.blast.hk
BlastHack © 2013 - 2016
[15:20:44] ==========================================
[15:20:44] SAMPFUNCS v5.3.3 release #19 (SA-MP 0.3.7) completely loaded!
[16:00:25] SAMPFUNCS v5.3.3 release #19 (SA-MP 0.3.7) caught an exception.
[16:00:25] Base address: 042B0000
[16:00:25] > Exception record:
[16:00:25] Exception at address: 0FCB7414, Flags: 00000000
[16:00:25] Module: D:\Games\San Andreas Multiplayer\MoonLoader.asi (0FC90000)
[16:00:25] Cause: EXCEPTION_ACCESS_VIOLATION
[16:00:25] Attempted to read from: 00000000
[16:00:25] > Exception context:
[16:00:25] EAX: 01CA26C4 ESI: 0177EFE4
[16:00:25] EBX: 0177F0A0 EDX: 00000000
[16:00:25] ECX: 01CA2709 EDI: 00000001
[16:00:25] EBP: 0177F18C ESP: 0177EFC8
[16:00:25] DR0: 00000000 DR1: 00000000
[16:00:25] DR2: 00000000 DR3: 00000000
[16:00:25] DR6: 00000000 DR7: 00000000
[16:00:25] SegGs: 00000000 SegFs: 0000003B
[16:00:25] SegEs: 00000023 SegDs: 00000023
[16:00:25] > Stack:
0177F0A8 00000000 0FCE99D3 0177EFE4
0000FFFF 0177F0A8 00000000 636E6100
505F6F68 65726961 01DE0073 00000000
0000000F 0FCE73CE 0177F0A8 0177F170
01CA26F0 0177F088 00000000 0FCF0522
0177F0A8 0177F170 01CA26F0 0177F088
00000000 0FCF0589 0177F0A8 0000FFFF
0000FFFF 01EA01C0 00000001 0177F0A0
0177F17B 0177F170 01CA26F0 0177F088
01EA01C0 00000001 0FD10FD0 01EA01C0
01EA0D00 00000000 0FCE9357 0177F0A8
00000002 0177F114 01EA01C0 00000001
0000FFFF 0177F17B 0177F170 01CA26F0
01EA01C0 00000000 00000001 00000001
636E6100 505F6F68 0FD10FD0 01EA01C0
0177F18C 01EA0D00 0FCE9822 0177F114
[16:00:25] > Modules:
gta_sa.exe, 00400000, 01177000
ntdll.dll, 770B0000, 00186000
KERNEL32.DLL, 74970000, 00096000
KERNELBASE.dll, 73C60000, 001A7000
apphelp.dll, 726B0000, 00092000
AcLayers.DLL, 78B40000, 00277000
msvcrt.dll, 74DA0000, 000BE000
USER32.dll, 750D0000, 00149000
win32u.dll, 74950000, 00019000
GDI32.dll, 74FA0000, 0002B000
gdi32full.dll, 73E10000, 0015A000
SHELL32.dll, 75490000, 013D9000
cfgmgr32.dll, 73FC0000, 00036000
windows.storage.dll, 74140000, 0056E000
combase.dll, 74AC0000, 00211000
ucrtbase.dll, 74000000, 000E0000
RPCRT4.dll, 76A10000, 000C3000
bcryptPrimitives.dll, 740E0000, 0005A000
powrprof.dll, 73BE0000, 00045000
advapi32.dll, 74D00000, 00077000
sechost.dll, 74A10000, 00041000
shlwapi.dll, 74F50000, 00046000
kernel.appcore.dll, 73C30000, 0000D000
shcore.dll, 74EC0000, 00088000
profapi.dll, 73C50000, 0000F000
OLEAUT32.dll, 74FD0000, 00094000
msvcp_win.dll, 746B0000, 0007B000
SETUPAPI.dll, 76C90000, 0040B000
MPR.dll, 61C50000, 00016000
sfc.dll, 66680000, 00003000
WINSPOOL.DRV, 6F930000, 0006A000
bcrypt.dll, 73B40000, 0001D000
sfc_os.DLL, 66AB0000, 0000F000
AcGenral.DLL, 50580000, 00264000
ole32.dll, 75310000, 000EA000
SspiCli.dll, 73940000, 00023000
UxTheme.dll, 72790000, 0007A000
WINMM.dll, 72510000, 00024000
samcli.dll, 6D7D0000, 00015000
MSACM32.dll, 663E0000, 00018000
VERSION.dll, 706F0000, 00008000
USERENV.dll, 73610000, 0001A000
dwmapi.dll, 71F20000, 0001F000
urlmon.dll, 68670000, 00194000
WINMMBASE.dll, 724A0000, 00023000
iertutil.dll, 6BCD0000, 00229000
IMM32.DLL, 769E0000, 00026000
WS2_32.dll, 76AE0000, 00063000
vorbisfile.dll, 6F380000, 00011000
EAX.DLL, 10000000, 00030000
samp.dll, 02FA0000, 00330000
PSAPI.DLL, 770A0000, 00006000
d3dx9_25.dll, 032D0000, 00253000
COMCTL32.dll, 5F010000, 00094000
WSOCK32.dll, 6D200000, 00008000
BASS.dll, 11000000, 0004D000
usp10.dll, 68810000, 00017000
vorbishooked.DLL, 001C0000, 00011000
ogg.dll, 001A0000, 00009000
vorbis.dll, 01780000, 00108000
CRYPTSP.dll, 73750000, 00013000
rsaenh.dll, 73680000, 0002F000
CRYPT32.dll, 74730000, 0017D000
MSASN1.dll, 73C40000, 0000E000
DPAPI.dll, 735C0000, 00008000
CRYPTBASE.dll, 73770000, 0000A000
CLEO.asi, 5B430000, 0006B000
FileSystemOperations.cleo, 61250000, 00014000
IniFiles.cleo, 61230000, 00018000
IntOperations.cleo, 5F250000, 00013000
MoonLoader.asi, 0FC90000, 001E3000
d3dx9_43.dll, 0F750000, 001FF000
WININET.dll, 6AF60000, 0022F000
SAMPFUNCS.asi, 042B0000, 00208000
DDRAW.dll, 046C0000, 000ED000
DCIMAN32.dll, 6D080000, 00007000
bdcam.dll, 58EC0000, 000DD000
DSOUND.dll, 57BE0000, 00089000
clbcatq.dll, 75400000, 00084000
MMDevApi.dll, 6DB20000, 00058000
DEVOBJ.dll, 72B50000, 00022000
PROPSYS.dll, 71F40000, 0014F000
AUDIOSES.DLL, 53B00000, 0007B000
wintypes.dll, 71650000, 000CF000
MSCTF.dll, 76B50000, 00135000
DINPUT8.dll, 0F4A0000, 00036000
HID.DLL, 72DA0000, 0000A000
WINTRUST.dll, 73F70000, 00044000
d3d9.dll, 50420000, 0015F000
nvd3dum.dll, 5CCA0000, 00EA2000
avrt.dll, 72500000, 00009000
wmvcore.dll, 088C0000, 00224000
WMASF.DLL, 0F2E0000, 00044000
mfperfhelper.dll, 08AF0000, 00109000
MFPlat.DLL, 6BA10000, 00113000
RTWorkQ.DLL, 6F120000, 0002A000
mlang.dll, 5B2C0000, 00034000
ondemandconnroutehelper.dll, 65BE0000, 00010000
IPHLPAPI.DLL, 73280000, 0002F000
winhttp.dll, 6FB20000, 000A0000
mswsock.dll, 73470000, 00050000
WINNSI.DLL, 6E0B0000, 00008000
NSI.dll, 74D80000, 00007000
DNSAPI.dll, 732B0000, 0007C000
rasadhlp.dll, 67CB0000, 00008000
fwpuclnt.dll, 6BF00000, 00049000
schannel.DLL, 73210000, 00064000
mskeyprotect.dll, 05140000, 00011000
ncrypt.dll, 73860000, 00020000
NTASN1.dll, 73830000, 0002B000
cryptnet.dll, 6A660000, 00025000
ncryptsslp.dll, 0F350000, 0001B000
napinsp.dll, 634C0000, 00012000
pnrpnsp.dll, 634A0000, 00016000
NLAapi.dll, 6F430000, 00014000
winrnr.dll, 63490000, 0000C000
bdcap32.dll, 19930000, 00ADD000
VCOMP140.DLL, 6D5D0000, 0002E000

[16:00:25] > SCM Thread:
hj 00A903D0 00000000 00A561AD true
noname 00A904B0 00000000 00A56B07 true
intman 00A90590 00000000 00A56FDA true
main 00A90750 00000000 00A56091 true
benzo xy 042A87F8 0B7C0048 0B7C0194 true
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
обновлено.
добавлено событие для входящего RPC 'ENTERVEHICLE'- onPlayerEnterVehicle
добавлены обработчики для входящих пакетов синхронизации:
onPlayerSync, onVehicleSync, onMarkersSync, onAimSync,
onBulletSync, onUnoccupiedSync, onTrailerSync, onPassengerSync
 
  • Нравится
Реакции: Garrus

FYP

Известный
Автор темы
Администратор
1,758
5,722
добавил ссылки на примеры скриптов
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
глобальное обновление.
добавлены и протестированы события для всех известных входящих и исходящих RPC, много исправлений и улучшений.
в связи с большими изменениями могут быть некоторые несовместимости - в некоторых событиях вместо координат в виде отдельных аргументов "x, y, z" и "x, y", теперь используется вектор, который хранит эти значения. в остальном изменений, нарушающих совместимость, нет.
скачать последнюю версию можно на гитхабе, посмотреть список всех эвентов тоже.
мы проебали целых пять дней, чтобы сделать это, так что с вас с каждого по сотке мне и мистеру_гонщику.
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
Я нашел эту функцию: https://github.com/THE-FYP/SAMP.Lua...716bb39daf69183/samp/events/handlers.lua#L503

Как я понял это именно то что мне нужно, но тут-же возникает вопрос:
Как можно "получить" данные из той функций?
добавить событие onCreateObject с аргументами objectId, data и работать с этими данными
 

ynhhoJ

Известный
102
6
добавить событие onCreateObject с аргументами objectId, data и работать с этими данными
Lua:
script_name("os")
script_author("Johhny")
script_version("Beta")
script_version_number(0.1)
script_dependencies("SAMPFUNCS", "SAMP")
script_description("-")

require "lib.sampfuncs"
require "lib.moonloader"
local sampev = require 'lib.samp.events'

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
   
    wait(-1)
end

function OnCreateObject(objectId, data)
    sampAddChatMessage(string.format("ObjectID: %i, Data: %i",objectId, data),0xFFFFFF)
end
Попробовал сделать так, но не работает. Можете объяснить более подробнее?
В LUA я совсем не разбираюсь.
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
@Johhny
Lua:
function sampev.onCreateObject(objectId, data)
   sampAddChatMessage(string.format("ObjectID: %d, Model: %d",objectId, data.modelId),0xFFFFFF)
end
 
  • Нравится
Реакции: ynhhoJ

ynhhoJ

Известный
102
6
@Johhny
Lua:
function sampev.onCreateObject(objectId, data)
   sampAddChatMessage(string.format("ObjectID: %d, Model: %d",objectId, data.modelId),0xFFFFFF)
end
Как можно получить данные из вектора? т.е.
Код:
data.position = read.vector3d(bs)
Я пробовал через %.4f, но выдает ошибку, в гугле ничего про это не написано.
 

romacaddy

Известный
Проверенный
234
206
Как можно получить данные из вектора? т.е.
Код:
data.position = read.vector3d(bs)
Я пробовал через %.4f, но выдает ошибку, в гугле ничего про это не написано.
Код:
print(data.position.x)
print(data.position.y)
print(data.position.z)
 
  • Нравится
Реакции: ynhhoJ

Salik_Davince

Известный
37
3
Я тут понял что можно при чтении RPC - onCreateObject идет и SetObjectMaterial | (text)
https://github.com/THE-FYP/SAMP.Lua...716bb39daf69183/samp/events/handlers.lua#L525
Как можно совместить? Пробовал вызывать data.texturesCount (она вовсе иногда возвращает 0) но как отловить другой RPC внутри тела функции OnCreateObject.
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
Я тут понял что можно при чтении RPC - onCreateObject идет и SetObjectMaterial | (text)
https://github.com/THE-FYP/SAMP.Lua...716bb39daf69183/samp/events/handlers.lua#L525
Как можно совместить? Пробовал вызывать data.texturesCount (она вовсе иногда возвращает 0) но как отловить другой RPC внутри тела функции OnCreateObject.
можно просто вызвать onSetObjectMaterial из onCreateObject
 

Salik_Davince

Известный
37
3
Тупо не выводит никакую информацию
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)