Исходник Гайд Использование неблокирующих WebSocket'ов в LUA

artemizgame

Известный
Автор темы
29
49

В этом гайде я покажу как создать соединение по вебсокету на базе SignalR с клиента LUA.​


update 15.12.23. Теперь доступна библиотека для ванильных вебсокетов (любой сервер). Перейти

P.S В этом гайде будет использовано два языка программирования, поэтому некоторые моменты могут быть не понятны для тех кто кодит исключительно на LUA, но я постараюсь объяснить максимально понятно - как, что и почему. Читать далее или нет решать вам.
P.S.S Гайд будет на примере RakSamp


Что нужно для проекта:
1) Сервер вебсокет, в моем случае я буду использовать фреймворк SignalR от майкрософт.
2) Библиотека С++ для работы с соединением и получением информации.
3) LUA клиент.

Часть 1: Создание сервера​

Я буду использовать C# ASP.NET, потому-что SignalR сервер может работать исключительно на .NET (хотя подсоединиться можно почти через что угодно). Плюс это удобно, в одном сервисе крутится вебсокет и обычный WEB-API (post, get ...).
1)Открываем Visual Studio Installer
2) Находим Visual Studio 2022, жмем изменить
3)
Screenshot_38.png
Открываем Visual Studio, нажимаем создание проекта, выбираем Веб-API ASP.NET CORE,
Screenshot_39.png


Жмем далее, настраиваем как на скрине

Screenshot_40.png


Создаем

Если проект создан по спецификации выше, попадаем на класс Program. Это точка входа в наш веб-сокет сервер. Давайте удалим лишнее, вот такое должно получится:
Отредактированный текст:
var builder = WebApplication.CreateBuilder(args); //Создаем приложение

builder.Services.AddEndpointsApiExplorer(); //Говорим ему, чтобы слушал эндпоинты. Эндпоинт это конечный адрес, допустим есть адрес http://localhost:7229/Weather, эндпоинтом будет в нем Weather

var app = builder.Build(); //Применяем настройки выше

app.Run(); //Запускаем приложение

Изначально ASP.NET не подключает SignalR к проекту, поэтому это сделаем мы:
Подключение SIGNALR к проекту:
using Microsoft.AspNetCore.SignalR; //Добавляем пространство имен SignalR к проекту, после этого
//можем получить классы для работы с ним

var builder = WebApplication.CreateBuilder(args);

//Вообще, приложение ASP.NET состоит из сервисов, каждый отвечает за свою часть
builder.Services.AddEndpointsApiExplorer(); //Уже рассказывал
builder.Services.AddSignalR(); //Добавляем сервис SignalR

var app = builder.Build();

app.Run();

Теперь создадим класс для работы с сообщениями, в SignalR это называется Hub. Hub - принимает и отправляет сообщения, хранит данные о подключениях и т.д. Хабов в приложение может быть сколько угодно, они разделяют логику работы. Допустим в приложении есть чат, это будет ChatHub, и есть хаб уведомлений NotifyHub. У нас же будет
DataRecieverHub. Добавляем этот код в самый конец Program.cs.
DataRecieverHub:
internal class DataRecieverHub : Hub
{
//Тут будут обработчики
}

Хаб создан, хоть он и без каких-либо обработчков, формально он работает.
P.S Вообще на данном этапе я бы порекомендовал новичку изучить основы ООП (или глянуть ролик какой на ютубе). Потому что наш DataRecieverHub наследует (т.е перенимает некоторые свойства (переменные) и методы (функции)) от класса Hub. И уже содержит некоторые обработчики, просто они внутри Hub.

Чтобы приложение начало принимать данные в DataRecieverHub, нужно указать это в конфигурации, добавим эту строчку перед app.Run();
C#:
app.MapHub<DataRecieverHub>("data-reciever-hub");

Этой строкой мы говорим: если какой либо из клиентов пытается соединиться по ссылке http://localhost:7229/data-reciever-hub, значит отправляем его соединение в класс DataRecieverHub.

Добавим методы в DataRecieverHub. Обработчик подключения и отключения клиента:
Новые методы:
internal class DataRecieverHub : Hub
{
    //Подключение, этот метод будет вызываться при подключении любого клиента
    public override async Task<Task> OnConnectedAsync()
    {
        //Вызововем клиентский метод PendingMessage, на всех подключенных клиентах (включая того кто только подключился)
        await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
        //Базовый метод для подключения из Hub, вызываем его, если интересно можно почитать про полиморфизм в ООП
        return base.OnConnectedAsync();
    }
    //Аналогично, только отключение
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
    }
}

Часть 2: Подключаемся к серверу​

Как указано выше, я буду подключаться к серверу через раксамп, однако весь этот гайд так же подойдет для любых клиентов если там используется LUA5.1.

Скачиваем библиотеку-прокладку из приложенного архива.
P.S
Для нормальной работы чистого луа не хватит, вообще основная причина написания этого гайда, то что готовыми библиотеками для вебсокетов (например lua websocket) обойтись в случае сампа скорее всего не получится. Мне пришлось создать библиотеку на С++ для луа, которая служит прокладкой между LUA и официальной библиотекой SignalR от майкрософт, она работает асинхронно, поэтому ничего блокировано не будет, о библиотеке-прокладке я расскажу в 3 части. Пока условимся что моя библиотека уже скачана и находится в папке /scripts/libs. Открытый код я так-же приложу далее.


Напишем простейший скрипт на LUA для подключения к нашему вебсокету:


Код подключения:
--Подключение библиотеки прокладки
require("WebS")
require("addon")

local encoding = require "encoding"

--Вызывается после успешной загрузки этого скрипта раксампом
function onLoad()
    --Подключение к нашему эндпоинту
    WebS.Connect("http://localhost:5056/data-reciever-hub");
 
    --Бексконечный цикл получения сообщений с вебсокета.
    newTask(function()
        while true do
            --Получаем последнее сообщение из очереди.
            local output = WebS.GetMessage()
            --Сообщение не пустое?
            if output ~= '' then
                print(output)
            end
            wait(100)
        end
    end)
end

function onDisconnect()
    WebS.Disconnect()
end
Это всё. Запустим проект ASP.NET в Visual Studio. Далее запустим ракбота, увидим следующий текст:
Screenshot_41.png


Значит соединение прошло успешно. Боту присвоен уникальный идентификатор.
Теперь сделаем отправку сообщений на сервер из клиента LUA:
Добавим обработчик события onConnect в скрипт:
Отправка никнейма на сервер после подключения к серверу самп:
function onConnect()
    local table = { getBotNick() }
    WebS.SendMessage("BotConnected", table) -- BotConnect это имя метода (функции) из класса хаба ASP.NET, у нас его нет, поэтому добавим его
end

Добавим обработчик сообщения BotConnected для ASP.NET
Новые метод BotConnect:
internal class DataRecieverHub : Hub
{
    public override async Task<Task> OnConnectedAsync()
    {
        await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
        return base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
    }
 
    //Добавленный метод
    public async Task BotConnected(string botNick)
    {
        await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server");
    }
}

Хотелось бы уточнить как именно передаются данные из LUA на сервер, как видно метод WebS.SendMessage() принимает первым аргументом название метода из хаба который будет вызван, а вторым аргументом таблицу содержащую коллекцию строк (именно строк, не чисел и т.д)
Если бы мы хотели передавать помимо никнейма еще и пинг при подключении, надо сделать так:
ASP.NET:
C#:
public async Task BotConnected(string botNick, string ping)
{
  await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server with ping {ping}");
}
LUA:
Lua:
function onConnect()
    local table = { getBotNick(), tostring(getBotPing())}
    WebS.SendMessage("BotConnected", table)
end

Часть 3: Библиотека-прокладка​

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

Конец​

Полный проект (РакСамп (https://www.blast.hk/threads/108052/) + ASP.NET) из гайда прикладываю в виде архива: Скачать

P.S Иногда библиотеки .dll надо положить в КОРЕНЬ раксампа (или гта са), т.е рядом с .exe.
P.S.S если ошибка осталась, и у тебя обычная гта с мунлоадером, положи WebS.dll в папку moonloader/lib, а содержимое папки sampwebsocket из архива, положи в корневую папки ГТА
 

Вложения

  • sampsocket.rar
    2.2 MB · Просмотры: 58
Последнее редактирование:

artemizgame

Известный
Автор темы
29
49
Поступило пара просьб о создании библиотеки для подключения к ванильным вебсокетам, поэтому решил сделать еще одну библу-прокладку.
За основу взята либа IXWebSocket.

Установка для раксамп:
1) Содержимое архива в /scripts/libs
Установка для moonloader:
1) Содержимое архива в /moonloader/lib

Методы:
Код:
ConnectWS("URL") - подключение к вебсокету
SendMessageWS("TEXT") - отправить сообщение на сервер
GetMessageWS() - получить сообщение
DisconnectWS() - отключиться от вебсокета
GetConnectionStatus() - получить статус подключения (строка) -
{
    CONNECTING,
    OPEN,
    CLOSING,
    CLOSED
}


Использование похожее:
Мунлоадер:

Пример для мунлоадера:
local ws = require("websocketsamp")

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

    sampRegisterChatCommand("send", sendMsg)

    ws.Connect("wss://socketsbay.com/wss/v2/1/demo/");

    lua_thread.create(function()
        while true do
            local output = ws.GetMessage()
            if output ~= '' then
                sampAddChatMessage(output, 0x00DD00)
            end
            wait(100)
        end
        return true
    end)

end

function sendMsg(arg)
    ws.SendMessage(arg)
end


function onQuitGame()
    ws.Disconnect()
end

Раксамп:
Пример раксамп:
local ws = require("websocketsamp")
require("addon")

function onLoad()
    ws.Connect("wss://socketsbay.com/wss/v2/1/demo/");

    newTask(function()
        while true do
            if ws.GetConnectionStatus() == "OPEN" then
                local output = ws.GetMessage()
                if output ~= '' then
                    print(output)
                end
            end
            wait(100)
        end
    end)
end

function onRunCommand(cmd)
    if cmd:find("^!sendWs %d+$") then
        ws.SendMessage(cmd:match("%d+"))
        return false
    end
end

function onDisconnect()
    WebS.Disconnect()
end


P.S Иногда библу .dll надо положить в КОРЕНЬ раксампа (или гта са), т.е рядом с .exe.
 

Вложения

  • websocketsamp.rar
    270.8 KB · Просмотры: 60
Последнее редактирование:

tripple sixx

Активный
107
49
Автору этой темы огромное спасибо!
Кому интерестно, можете почитать что я придумал:
значит заебали меня эти ваши помойные подключения тг ботов к раксампу, и я сделал ахуенный коннект между aiogram (python) и websocket (lua).

raksamp lua:
local encoding = require("encoding")
local u8 = encoding.UTF8
encoding.default = "CP1251"

local ws = require("websocketsamp")
require("addon")

last_message = ""

function onLoad()
    newTask(function()
        while true do
            if ws.GetConnectionStatus() == "OPEN" then
                local output = ws.GetMessage()
                if output ~= '' and output ~= last_message then
                    print(u8:decode(output))
                end
            else
                ws.Connect("ws://localhost:8765");
            end
            wait(100)
        end
    end)
end

function onRunCommand(cmd)
    if cmd:find("!send (.+)") then
        last_message = cmd:match("!send (.+)")
        ws.SendMessage(u8:encode(last_message))
        return false
    end
end

function onDisconnect()
    WebS.Disconnect()
end


питон:
from aiogram import executor, Dispatcher, Bot, types
import websockets
import asyncio

bot = Bot('токен', parse_mode='HTML')
dp = Dispatcher(bot)

connected_clients = set()
id = ваш тг айди

async def handle_client(websocket, path):
    connected_clients.add(websocket)
    try:
        async for message in websocket:
            await bot.send_message(id, f'<b>📫 Новое сообщение:</b>\n<pre>{message}</pre>')
            await asyncio.gather(*[client.send(message) for client in connected_clients])
    except websockets.exceptions.ConnectionClosedError:
        pass
    finally:
        connected_clients.remove(websocket)

async def send_websocket_message(message):
    if connected_clients:
        await asyncio.gather(*[client.send(message) for client in connected_clients])
    else:
        print("Нет подключенных клиентов.")

@dp.message_handler(commands=['send'])
async def cmd_send(message: types.Message):
    text = message.get_args()
    await message.answer(f'<b>🛫 Отправляю сообщение:</b>\n<pre>{text}</pre>')
    await send_websocket_message(text)

async def main():
    try:
        start_server = websockets.serve(handle_client, "localhost", 8765)
        await asyncio.gather(start_server)
    except Exception as e:
        print(f"Возникла ошибка при запуске: {e}")

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.create_task(main())
    loop.run_until_complete(executor.start_polling(dp, loop=loop))
ps: сделано под эту библиотеку https://www.blast.hk/threads/197405/post-1424989
 
Последнее редактирование:

Rezbirp

Известный
64
68

В этом гайде я покажу как создать соединение по вебсокету на базе SignalR с клиента LUA.​


update 15.12.23. Теперь доступна библиотека для ванильных вебсокетов (любой сервер). Перейти

P.S В этом гайде будет использовано два языка программирования, поэтому некоторые моменты могут быть не понятны для тех кто кодит исключительно на LUA, но я постараюсь объяснить максимально понятно - как, что и почему. Читать далее или нет решать вам.
P.S.S Гайд будет на примере RakSamp

Что нужно для проекта:
1) Сервер вебсокет, в моем случае я буду использовать фреймворк SignalR от майкрософт.
2) Библиотека С++ для работы с соединением и получением информации.
3) LUA клиент.

Часть 1: Создание сервера​

Я буду использовать C# ASP.NET, потому-что SignalR сервер может работать исключительно на .NET (хотя подсоединиться можно почти через что угодно). Плюс это удобно, в одном сервисе крутится вебсокет и обычный WEB-API (post, get ...).
1)Открываем Visual Studio Installer
2) Находим Visual Studio 2022, жмем изменить
3) Посмотреть вложение 224352
Открываем Visual Studio, нажимаем создание проекта, выбираем Веб-API ASP.NET CORE,
Посмотреть вложение 224353

Жмем далее, настраиваем как на скрине

Посмотреть вложение 224354

Создаем

Если проект создан по спецификации выше, попадаем на класс Program. Это точка входа в наш веб-сокет сервер. Давайте удалим лишнее, вот такое должно получится:
Отредактированный текст:
var builder = WebApplication.CreateBuilder(args); //Создаем приложение

builder.Services.AddEndpointsApiExplorer(); //Говорим ему, чтобы слушал эндпоинты. Эндпоинт это конечный адрес, допустим есть адрес http://localhost:7229/Weather, эндпоинтом будет в нем Weather

var app = builder.Build(); //Применяем настройки выше

app.Run(); //Запускаем приложение

Изначально ASP.NET не подключает SignalR к проекту, поэтому это сделаем мы:
Подключение SIGNALR к проекту:
using Microsoft.AspNetCore.SignalR; //Добавляем пространство имен SignalR к проекту, после этого
//можем получить классы для работы с ним

var builder = WebApplication.CreateBuilder(args);

//Вообще, приложение ASP.NET состоит из сервисов, каждый отвечает за свою часть
builder.Services.AddEndpointsApiExplorer(); //Уже рассказывал
builder.Services.AddSignalR(); //Добавляем сервис SignalR

var app = builder.Build();

app.Run();

Теперь создадим класс для работы с сообщениями, в SignalR это называется Hub. Hub - принимает и отправляет сообщения, хранит данные о подключениях и т.д. Хабов в приложение может быть сколько угодно, они разделяют логику работы. Допустим в приложении есть чат, это будет ChatHub, и есть хаб уведомлений NotifyHub. У нас же будет
DataRecieverHub. Добавляем этот код в самый конец Program.cs.
DataRecieverHub:
internal class DataRecieverHub : Hub
{
//Тут будут обработчики
}

Хаб создан, хоть он и без каких-либо обработчков, формально он работает.
P.S Вообще на данном этапе я бы порекомендовал новичку изучить основы ООП (или глянуть ролик какой на ютубе). Потому что наш DataRecieverHub наследует (т.е перенимает некоторые свойства (переменные) и методы (функции)) от класса Hub. И уже содержит некоторые обработчики, просто они внутри Hub.

Чтобы приложение начало принимать данные в DataRecieverHub, нужно указать это в конфигурации, добавим эту строчку перед app.Run();
C#:
app.MapHub<DataRecieverHub>("data-reciever-hub");

Этой строкой мы говорим: если какой либо из клиентов пытается соединиться по ссылке http://localhost:7229/data-reciever-hub, значит отправляем его соединение в класс DataRecieverHub.

Добавим методы в DataRecieverHub. Обработчик подключения и отключения клиента:
Новые методы:
internal class DataRecieverHub : Hub
{
    //Подключение, этот метод будет вызываться при подключении любого клиента
    public override async Task<Task> OnConnectedAsync()
    {
        //Вызововем клиентский метод PendingMessage, на всех подключенных клиентах (включая того кто только подключился)
        await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
        //Базовый метод для подключения из Hub, вызываем его, если интересно можно почитать про полиморфизм в ООП
        return base.OnConnectedAsync();
    }
    //Аналогично, только отключение
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
    }
}

Часть 2: Подключаемся к серверу​

Как указано выше, я буду подключаться к серверу через раксамп, однако весь этот гайд так же подойдет для любых клиентов если там используется LUA5.1.

Скачиваем библиотеку-прокладку из приложенного архива.
P.S
Для нормальной работы чистого луа не хватит, вообще основная причина написания этого гайда, то что готовыми библиотеками для вебсокетов (например lua websocket) обойтись в случае сампа скорее всего не получится. Мне пришлось создать библиотеку на С++ для луа, которая служит прокладкой между LUA и официальной библиотекой SignalR от майкрософт, она работает асинхронно, поэтому ничего блокировано не будет, о библиотеке-прокладке я расскажу в 3 части. Пока условимся что моя библиотека уже скачана и находится в папке /scripts/libs. Открытый код я так-же приложу далее.


Напишем простейший скрипт на LUA для подключения к нашему вебсокету:


Код подключения:
--Подключение библиотеки прокладки
require("WebS")
require("addon")

local encoding = require "encoding"

--Вызывается после успешной загрузки этого скрипта раксампом
function onLoad()
    --Подключение к нашему эндпоинту
    WebS.Connect("http://localhost:5056/data-reciever-hub");
 
    --Бексконечный цикл получения сообщений с вебсокета.
    newTask(function()
        while true do
            --Получаем последнее сообщение из очереди.
            local output = WebS.GetMessage()
            --Сообщение не пустое?
            if output ~= '' then
                print(output)
            end
            wait(100)
        end
    end)
end

function onDisconnect()
    WebS.Disconnect()
end
Это всё. Запустим проект ASP.NET в Visual Studio. Далее запустим ракбота, увидим следующий текст:
Посмотреть вложение 224357

Значит соединение прошло успешно. Боту присвоен уникальный идентификатор.
Теперь сделаем отправку сообщений на сервер из клиента LUA:
Добавим обработчик события onConnect в скрипт:
Отправка никнейма на сервер после подключения к серверу самп:
function onConnect()
    local table = { getBotNick() }
    WebS.SendMessage("BotConnected", table) -- BotConnect это имя метода (функции) из класса хаба ASP.NET, у нас его нет, поэтому добавим его
end

Добавим обработчик сообщения BotConnected для ASP.NET
Новые метод BotConnect:
internal class DataRecieverHub : Hub
{
    public override async Task<Task> OnConnectedAsync()
    {
        await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
        return base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
    }
 
    //Добавленный метод
    public async Task BotConnected(string botNick)
    {
        await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server");
    }
}

Хотелось бы уточнить как именно передаются данные из LUA на сервер, как видно метод WebS.SendMessage() принимает первым аргументом название метода из хаба который будет вызван, а вторым аргументом таблицу содержащую коллекцию строк (именно строк, не чисел и т.д)
Если бы мы хотели передавать помимо никнейма еще и пинг при подключении, надо сделать так:
ASP.NET:
C#:
public async Task BotConnected(string botNick, string ping)
{
  await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server with ping {ping}");
}
LUA:
Lua:
function onConnect()
    local table = { getBotNick(), tostring(getBotPing())}
    WebS.SendMessage("BotConnected", table)
end

Часть 3: Библиотека-прокладка​

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

Конец​

Полный проект (РакСамп (https://www.blast.hk/threads/108052/) + ASP.NET) из гайда прикладываю в виде архива: Скачать

P.S Иногда библиотеки .dll надо положить в КОРЕНЬ раксампа (или гта са), т.е рядом с .exe.
Приветствую, нужно ли, что-то ещё помимо библиотеки? Так-как столкнулся с ошибкою:

"[ML] (error) client.lua: error loading module 'WebS' from file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS.dll':
The specified module could not be found.

stack traceback:
[C]: in ?
[C]: in function 'require'
C:\Program Files (x86)\GTA SA\moonloader\client.lua:1: in main chunk
[ML] (error) client.lua: Script died due to an error. (01BBF504)"

Такую ошибку получил и на RakSamp Lite:

"[15:01:14] [LUA] error loading module 'WebS' from file 'D:\Project\RakBotGuide\scripts\libs\WebS.dll':
The specified module could not be found.


stack traceback:
[C]: in ?
[C]: in function 'require'
D:\Project\RakBotGuide\scripts\guide.lua:1: in main chunk"
 
  • Нравится
Реакции: .chazari

artemizgame

Известный
Автор темы
29
49
Приветствую, нужно ли, что-то ещё помимо библиотеки? Так-как столкнулся с ошибкою:

"[ML] (error) client.lua: error loading module 'WebS' from file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS.dll':
The specified module could not be found.

stack traceback:
[C]: in ?
[C]: in function 'require'
C:\Program Files (x86)\GTA SA\moonloader\client.lua:1: in main chunk
[ML] (error) client.lua: Script died due to an error. (01BBF504)"

Такую ошибку получил и на RakSamp Lite:

"[15:01:14] [LUA] error loading module 'WebS' from file 'D:\Project\RakBotGuide\scripts\libs\WebS.dll':
The specified module could not be found.


stack traceback:
[C]: in ?
[C]: in function 'require'
D:\Project\RakBotGuide\scripts\guide.lua:1: in main chunk"


Просто закинь все DLL в корневую папку, рядом с .exe, а не в папку библиотек.


Я уверен что есть способ указать путь до длл, чтобы избежать засорения корневой папки, но пробовал по разному и у меня не получилось (на дедике столкнулся с этой проблемой когда впервые загрузил туда ракбота). Хотя у меня на компе все работает в папке с либами.

Может кто из опытных форумчан шарит почему не подключаются dll из папки либ?
 

Rezbirp

Известный
64
68
Просто закинь все DLL в корневую папку, рядом с .exe, а не в папку библиотек.


Я уверен что есть способ указать путь до длл, чтобы избежать засорения корневой папки, но пробовал по разному и у меня не получилось (на дедике столкнулся с этой проблемой когда впервые загрузил туда ракбота). Хотя у меня на компе все работает в папке с либами.

Может кто из опытных форумчан шарит почему не подключаются dll из папки либ?

.dll видит, если б не нашло, была б другая ошибка:​


"[ML] (error) client.lua: C:\Program Files (x86)\GTA SA\moonloader\client.lua:1: module 'WebS' not found:
no field package.preload['WebS']
no file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS.lua'
no file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS\init.lua'
no file 'C:\Program Files (x86)\GTA SA\moonloader\WebS.lua'
no file 'C:\Program Files (x86)\GTA SA\moonloader\WebS\init.lua'
no file '.\WebS.lua'
no file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS.luac'
no file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS\init.luac'
no file 'C:\Program Files (x86)\GTA SA\moonloader\WebS.luac'
no file 'C:\Program Files (x86)\GTA SA\moonloader\WebS\init.luac'
no file '.\WebS.luac'
no file 'C:\Program Files (x86)\GTA SA\moonloader\lib\WebS.dll'
stack traceback:
[C]: in function 'require'
C:\Program Files (x86)\GTA SA\moonloader\client.lua:1: in main chunk
[ML] (error) client.lua: Script died due to an error. (0BB15EB4)"

В этом случаи .dll в корневой папке GTA SA (возле gta_sa.exe)​

 
  • Нравится
Реакции: .chazari

returnbool

Новичок
13
1
websocketsamp.zip: после выгрузки скрипта просто происходит краш самого процесса (если сокет был открыт), вне зависимости закрыл я сокет или нет.
 

chromiusj

Известный
Модератор
5,653
3,955
1722329028353.png

спасибо автору за такую прекрасную библиотеку! очень удобно делать прослойку между луашкой и сервером, в частности взаимодействие обоих
1722329071557.png
 
  • Нравится
Реакции: tripple sixx и artemizgame

Ejik_Letchik

Участник
12
25
Прикольно, но было бы неплохо прокинуть не только строковый GetMessage в c++ библиотеке, а то сейчас приходится на стороне API костылить. И не совсем разобрался как работать передачей JSON запросов. Допустим мне нужно передать на хост JSON такого вида:
Структура ожидаемых данных:
arguments :
[0] : 
{
    userName : "string"
    userVal : "string"
    userData : "string"
    userType : "string"
}
Как правильно это сделать через либу? Пробовал разными способами, ни один не сработал:
Как я передавал 1.:
local table =
{
    userName = tostring(settings.userName),
    userVal = tostring(settings.userVal),
    userData = tostring(data),
    userType = "lua"
}
WebS.SendMessage("JoinFunc", table)

Как я передавал 2.:
local table =
{
    ['userName'] = tostring(settings.userName),
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
WebS.SendMessage("JoinFunc", table)

Как я передавал 3.:
local table =
{
    ['userName'] = settings.userName,
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
local jsonOutput = json.encode(table)
WebS.SendMessage("JoinFunc", {jsonOutput})--Тут функция принимает только таблицы, поэтому костыльнул

Как я передавал 4.:
local table =
{
    ['userName'] = tostring(settings.userName),
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
local jsonOutput = dkjson.encode(table)
WebS.SendMessage("JoinFunc", {jsonOutput})

Пробовал и в одну строку записать:
local table = {string.format('[{"userName":"%s"}, {"userVal":"%s"}, {"userData":"%s"}, {"userType":"lua"}]', settings.userName, settings.userVal, data)}
WebS.SendMessage("JoinFunc", table)

Ну и тому подобное, не вижу смысла всю огромную простыню неудачных попыток писать
 

artemizgame

Известный
Автор темы
29
49
R
Прикольно, но было бы неплохо прокинуть не только строковый GetMessage в c++ библиотеке, а то сейчас приходится на стороне API костылить. И не совсем разобрался как работать передачей JSON запросов. Допустим мне нужно передать на хост JSON такого вида:
Структура ожидаемых данных:
arguments :
[0] :
{
    userName : "string"
    userVal : "string"
    userData : "string"
    userType : "string"
}
Как правильно это сделать через либу? Пробовал разными способами, ни один не сработал:
Как я передавал 1.:
local table =
{
    userName = tostring(settings.userName),
    userVal = tostring(settings.userVal),
    userData = tostring(data),
    userType = "lua"
}
WebS.SendMessage("JoinFunc", table)

Как я передавал 2.:
local table =
{
    ['userName'] = tostring(settings.userName),
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
WebS.SendMessage("JoinFunc", table)

Как я передавал 3.:
local table =
{
    ['userName'] = settings.userName,
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
local jsonOutput = json.encode(table)
WebS.SendMessage("JoinFunc", {jsonOutput})--Тут функция принимает только таблицы, поэтому костыльнул

Как я передавал 4.:
local table =
{
    ['userName'] = tostring(settings.userName),
    ['userVal'] = tostring(settings.userVal),
    ['userData'] = tostring(data),
    ['userType'] = "lua"
}
local jsonOutput = dkjson.encode(table)
WebS.SendMessage("JoinFunc", {jsonOutput})

Пробовал и в одну строку записать:
local table = {string.format('[{"userName":"%s"}, {"userVal":"%s"}, {"userData":"%s"}, {"userType":"lua"}]', settings.userName, settings.userVal, data)}
WebS.SendMessage("JoinFunc", table)

Ну и тому подобное, не вижу смысла всю огромную простыню неудачных попыток писать

Если это SignalR либа, то json передача не нужна, твоя таблица сериализуется в json на стороне с++ библиотеки. Передавай сразу значения ключей. Без их имени
local table = { getBotNick(), 'еще что-то' }.
 
  • Нравится
Реакции: Ejik_Letchik

Ejik_Letchik

Участник
12
25
R


Если это SignalR либа, то json передача не нужна, твоя таблица сериализуется в json на стороне с++ библиотеки. Передавай сразу значения ключей. Без их имени
local table = { getBotNick(), 'еще что-то' }.
Да, SignalR, теперь получилось, спасибо!
 

qwertySKIP

Новичок
2
0
Добрый день. Пишет такую ерунду на дедике:
[18:50:45] [LUA] error loading module 'websocketsamp' from file 'C:\Users\Администратор\Desktop\raksamp-ferma\bot\scripts\libs\websocketsamp.dll':
%1 не является приложением Win32.

Помогите пожалуйста)
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,798
2,659
Добрый день. Пишет такую ерунду на дедике:
[18:50:45] [LUA] error loading module 'websocketsamp' from file 'C:\Users\Администратор\Desktop\raksamp-ferma\bot\scripts\libs\websocketsamp.dll':
%1 не является приложением Win32.

Помогите пожалуйста)
у тебя дедик x32 архитектуру, а дллка собрана под x64 скорее всего
 

qwertySKIP

Новичок
2
0
у тебя дедик x32 архитектуру, а дллка собрана под x64 скорее всего
Серверный винда 2022 поставлена, x64.
При первом запуске выдает: %1 не является приложением Win32.
При повторном запуске раксампа: Не удается найти модуль.
 

artemizgame

Известный
Автор темы
29
49
Серверный винда 2022 поставлена, x64.
При первом запуске выдает: %1 не является приложением Win32.
При повторном запуске раксампа: Не удается найти модуль.
Попробуй положить dll-ки рядом с exe раксампа