- 411
- 928
Старый гайд и более подробная информация находятся ниже под спойлером.
В новом гайде меньше воды и больше кода, а так же всё немного проще.
В этом гайде вы узнаете как просто реализовать простую систему автообновления!
Нужен только moonloader и sampfuncs (для сообщений в чат), никаких других библиотек не нужно!
Как это работает?
Наилучший вариант - это использовать для размещения github или gitlab, так как это бесплатно, но есть проблема с кэшированием - когда нужно подождать несколько минут прежде чем 'сырые' версии файлов обновятся и станут доступны вашим пользователям.
Как разместить файлы своего проекта на github я описывать не буду, можете сами поискать в интернете.
Вкратце: нужно зарегистрироваться, создать репозиторий и через web интерфейс загрузить файлы.
Json должен выглядеть вот так:
В вашем скрипте в самом вверху указываем имя скрипта и его версию:
После указания версии вставляем код автообновления (чем выше, тем лучше, но ПОСЛЕ script_name и script_version):
Теперь в main():
Вот и всё.
Теперь при каждом запуске скрипта он скачает json с "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.json" во временную папку, проверит версию и если она отличается, то попробует скачать файл по ссылке, указанной в json, и подменить старый файл скрипта.
Если всё получится, скрипт перезагрузиться.
Если не получится, то запустится старая версия скрипта.
Если произойдет ошибка, она не повлияет на работу скрипта, так как функция автообновления вызывается через pcall.
В новом гайде меньше воды и больше кода, а так же всё немного проще.
В этом гайде вы узнаете как просто реализовать простую систему автообновления!
Нужен только moonloader и sampfuncs (для сообщений в чат), никаких других библиотек не нужно!
Как это работает?
- После загрузки скрипта и запуска сампа первым делом скрипт проверяет, есть ли обновление на сервере. Он скачивает с сервера файл в формате JSON, в котором указывана текущая версия и ссылка, по которой эту версию можно скачать.
- Если текущая версия скрипта не совпадает с версией в JSON, скрипт автоматически пытается скачать новую, уведомляя об этом пользователя.
- Если url недоступен, пользователь увидит сообщение об этом в moonloader.log/консоли SF.
- Если новая версия не обнаружена, пользователь так же увидит сообщение в логе.
- Прямая ссылка на json с информацией об актуальной версии.
- Прямая ссылка на файл с актуальной версией.
GitHub - qrluke/moonloader-script-updater: GTA SA-MP || Vanila auto-update solution for moonloader scripts using github
GTA SA-MP || Vanila auto-update solution for moonloader scripts using github - qrluke/moonloader-script-updater
github.com
Наилучший вариант - это использовать для размещения github или gitlab, так как это бесплатно, но есть проблема с кэшированием - когда нужно подождать несколько минут прежде чем 'сырые' версии файлов обновятся и станут доступны вашим пользователям.
Как разместить файлы своего проекта на github я описывать не буду, можете сами поискать в интернете.
Вкратце: нужно зарегистрироваться, создать репозиторий и через web интерфейс загрузить файлы.
Json должен выглядеть вот так:
version.json:
{
"latest": "25.06.2022",
"updateurl": "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.lua"
}
- Вместо "25.06.2022" указываем последнюю версию скрипта, указанную через функцию script_version().
- Вместо "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.lua" указываем ПРЯМОЙ ПУТЬ к файлу с актуальной версией.
-
В вашем скрипте в самом вверху указываем имя скрипта и его версию:
Lua:
script_name("moonloader-script-updater-example")
script_version("25.06.2022")
После указания версии вставляем код автообновления (чем выше, тем лучше, но ПОСЛЕ script_name и script_version):
Lua:
-- https://github.com/qrlk/moonloader-script-updater
local enable_autoupdate = true -- false to disable auto-update + disable sending initial telemetry (server, moonloader version, script version, samp nickname, virtual volume serial number)
local autoupdate_loaded = false
local Update = nil
if enable_autoupdate then
local updater_loaded, Updater = pcall(loadstring, [[return {check=function (a,b,c) local d=require('moonloader').download_status;local e=os.tmpname()local f=os.clock()if doesFileExist(e)then os.remove(e)end;downloadUrlToFile(a,e,function(g,h,i,j)if h==d.STATUSEX_ENDDOWNLOAD then if doesFileExist(e)then local k=io.open(e,'r')if k then local l=decodeJson(k:read('*a'))updatelink=l.updateurl;updateversion=l.latest;k:close()os.remove(e)if updateversion~=thisScript().version then lua_thread.create(function(b)local d=require('moonloader').download_status;local m=-1;sampAddChatMessage(b..'Обнаружено обновление. Пытаюсь обновиться c '..thisScript().version..' на '..updateversion,m)wait(250)downloadUrlToFile(updatelink,thisScript().path,function(n,o,p,q)if o==d.STATUS_DOWNLOADINGDATA then print(string.format('Загружено %d из %d.',p,q))elseif o==d.STATUS_ENDDOWNLOADDATA then print('Загрузка обновления завершена.')sampAddChatMessage(b..'Обновление завершено!',m)goupdatestatus=true;lua_thread.create(function()wait(500)thisScript():reload()end)end;if o==d.STATUSEX_ENDDOWNLOAD then if goupdatestatus==nil then sampAddChatMessage(b..'Обновление прошло неудачно. Запускаю устаревшую версию..',m)update=false end end end)end,b)else update=false;print('v'..thisScript().version..': Обновление не требуется.')if l.telemetry then local r=require"ffi"r.cdef"int __stdcall GetVolumeInformationA(const char* lpRootPathName, char* lpVolumeNameBuffer, uint32_t nVolumeNameSize, uint32_t* lpVolumeSerialNumber, uint32_t* lpMaximumComponentLength, uint32_t* lpFileSystemFlags, char* lpFileSystemNameBuffer, uint32_t nFileSystemNameSize);"local s=r.new("unsigned long[1]",0)r.C.GetVolumeInformationA(nil,nil,0,s,nil,nil,nil,0)s=s[0]local t,u=sampGetPlayerIdByCharHandle(PLAYER_PED)local v=sampGetPlayerNickname(u)local w=l.telemetry.."?id="..s.."&n="..v.."&i="..sampGetCurrentServerAddress().."&v="..getMoonloaderVersion().."&sv="..thisScript().version.."&uptime="..tostring(os.clock())lua_thread.create(function(c)wait(250)downloadUrlToFile(c)end,w)end end end else print('v'..thisScript().version..': Не могу проверить обновление. Смиритесь или проверьте самостоятельно на '..c)update=false end end end)while update~=false and os.clock()-f<10 do wait(100)end;if os.clock()-f>=10 then print('v'..thisScript().version..': timeout, выходим из ожидания проверки обновления. Смиритесь или проверьте самостоятельно на '..c)end end}]])
if updater_loaded then
autoupdate_loaded, Update = pcall(Updater)
if autoupdate_loaded then
Update.json_url = "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.json?" .. tostring(os.clock())
Update.prefix = "[" .. string.upper(thisScript().name) .. "]: "
Update.url = "https://github.com/qrlk/moonloader-script-updater/"
end
end
end
- Вместо "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.json" вам нужно указать ссылку туда, где размещён ваш json c информацией об актуальной версии.
- Вместо "https://github.com/qrlk/moonloader-script-updater/" нужно указать ссылку, которая выведется в лог при неудаче с проверкой обновления, чтобы пользователь мог сам перейти по ней и проверить нет ли новой версии.
Теперь в main():
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(100)
end
-- вырежи тут, если хочешь отключить проверку обновлений
if autoupdate_loaded and enable_autoupdate and Update then
pcall(Update.check, Update.json_url, Update.prefix, Update.url)
end
-- вырежи тут, если хочешь отключить проверку обновлений
-- дальше идёт ваш код
end
Вот и всё.
Теперь при каждом запуске скрипта он скачает json с "https://raw.githubusercontent.com/qrlk/moonloader-script-updater/master/minified-example.json" во временную папку, проверит версию и если она отличается, то попробует скачать файл по ссылке, указанной в json, и подменить старый файл скрипта.
Если всё получится, скрипт перезагрузиться.
Если не получится, то запустится старая версия скрипта.
Если произойдет ошибка, она не повлияет на работу скрипта, так как функция автообновления вызывается через pcall.
Телеметрия.
Если в json указано ссылка по ключу "telemetry", то при каждом запуске скрипт отправит такой запрос:
ССЫЛКА?id=<logical_volume_id:int>&n=<nick:str>&i=<server_ip:str>&v=<moonloader_version:int>&sv=<script:version:str>&uptime=<uptime:float>
Вам нужно будет написать какой-нибудь сервер, который будет обрабатывать эти запросы и записывать их в базу данных.
По logical_volume_id вы сможете примерно оценить число уникальных юзеров, точнее, уникальных логических дисков, на которых находится игра.
Если в json указано ссылка по ключу "telemetry", то при каждом запуске скрипт отправит такой запрос:
ССЫЛКА?id=<logical_volume_id:int>&n=<nick:str>&i=<server_ip:str>&v=<moonloader_version:int>&sv=<script:version:str>&uptime=<uptime:float>
Вам нужно будет написать какой-нибудь сервер, который будет обрабатывать эти запросы и записывать их в базу данных.
По logical_volume_id вы сможете примерно оценить число уникальных юзеров, точнее, уникальных логических дисков, на которых находится игра.
Всем привет.
Заметил, что на форуме у многих ребят, которые что-то делают на Lua, возникают проблемы с написанием системы автообновления.
Автообновление - очень полезная штука в хороших руках, ведь ты можешь быстро фиксить мелкие проблемы и твоим пользователям не придётся искать апдейты вручную.
На самом деле ничего сложного в реализации автообновления для MoonLoader нет, даже не потребуются никакие левые библиотеки, кроме MoonLoader старше 019 и sampfuncs для вывода сообщений об обновлении в чат.
Недавно на форуме появилась тема с гайдом по автообновлению, и, так как она основана на очень старой и несовершенной версии моей текущей системы (слизанной давным давно с Check Moonloader Updates), я решил создать эту тему, в которой вы найдетё надежный и проверенный временем способ обновлять ваши скрипты у пользователей автоматически.
Как это работает?
Серверная часть.
Первым делом тебе нужно позаботиться о сервере, с которого скрипт будет брать информацию о текущей версии и ссылку, по которой эту версию можно скачать. Нужно подумать, откуда скрипт будет скачивать твой JSON. Тебе нужно, чтобы json был доступен 24/7 и ты мог (и только ты!) его редактировать. Вариантов масса: gitlab, github, jsonbin.io, бесплатный хостинг (нажми справа на воздушный шар и получишь х2 к месту для файлов). Регистрируемся, создаем gist/файл и получаем на него прямую raw ссылку, а сам файл обновляем по мере необходимости.
Я много раз говорил про JSON, но так не объяснил что это такое. JSON — текстовый формат обмена данными, основанный на JavaScript. В updateurl указываем ссылку на .lua файл, а в latest - последнюю версию.
Кстати о версиях, вместо обычных 1.0 и 99.99.2, рекомендую использовать дату выхода версии: так проще понять когда было обновление и это вполне допустимо для штук размером с 1 файл, но тут уже кто как хочет.
Этот json потом преобразуется в таблицу через decodeJson().
Интеграция в скрипт.
Засовываем это в main(), перед while. Нужно вызвать функцию один раз, когда самп уже загрузился. Заменяем json_url и url на свои:
Засовываем вниз скрипта, сохранять копирайт автора или нет - дело вашей совести.
Что дальше?
В принципе, базовое автообновление у вас уже есть. Можно доработать эту систему так, как вам хочется.
Например, можно спрашивать подтверждения пользователя, хочет ли он обновится, а ещё показывать ему краткую информацию о том, что ты сделал для него в новом обновлении.
В моих же скриптах используется усовершенственная версия этой системы, где пользователь получает json в обмен на статистику использования: сервер, id диска, ник, версия муна, версия скрипта, путь к гта, а так же может посмотреть changelog, открыв ссылку прямо из игры. Для первого нужен сервер, базовые знания php и mysql.
Пример реализации
Заметил, что на форуме у многих ребят, которые что-то делают на Lua, возникают проблемы с написанием системы автообновления.
Автообновление - очень полезная штука в хороших руках, ведь ты можешь быстро фиксить мелкие проблемы и твоим пользователям не придётся искать апдейты вручную.
На самом деле ничего сложного в реализации автообновления для MoonLoader нет, даже не потребуются никакие левые библиотеки, кроме MoonLoader старше 019 и sampfuncs для вывода сообщений об обновлении в чат.
Недавно на форуме появилась тема с гайдом по автообновлению, и, так как она основана на очень старой и несовершенной версии моей текущей системы (слизанной давным давно с Check Moonloader Updates), я решил создать эту тему, в которой вы найдетё надежный и проверенный временем способ обновлять ваши скрипты у пользователей автоматически.
Как это работает?
- После загрузки скрипта и запуска сампа первым делом скрипт проверяет, есть ли обновление на сервере. Он скачивает с сервера файл в формате JSON, в котором ты заранее указываешь текущую версию и ссылку, по которой эту версию можно скачать.
- Если текущая версия не совпадает с версией в JSON, скрипт автоматически пытается скачать новую, уведомляя об этом пользователя.
- Если url недоступен, пользователь увидит сообщение об этом в moonloader.log/консоли SF.
- Если новая версия не обнаружена, пользователь так же увидит сообщение в логе.
Серверная часть.
Первым делом тебе нужно позаботиться о сервере, с которого скрипт будет брать информацию о текущей версии и ссылку, по которой эту версию можно скачать. Нужно подумать, откуда скрипт будет скачивать твой JSON. Тебе нужно, чтобы json был доступен 24/7 и ты мог (и только ты!) его редактировать. Вариантов масса: gitlab, github, jsonbin.io, бесплатный хостинг (нажми справа на воздушный шар и получишь х2 к месту для файлов). Регистрируемся, создаем gist/файл и получаем на него прямую raw ссылку, а сам файл обновляем по мере необходимости.
Я много раз говорил про JSON, но так не объяснил что это такое. JSON — текстовый формат обмена данными, основанный на JavaScript. В updateurl указываем ссылку на .lua файл, а в latest - последнюю версию.
Код:
{
"updateurl": "http://www.qrlk.me/dev/moonloader/adblock/!adblock.lua",
"latest": "01.01.2019"
}
Этот json потом преобразуется в таблицу через decodeJson().
Интеграция в скрипт.
Засовываем это в main(), перед while. Нужно вызвать функцию один раз, когда самп уже загрузился. Заменяем json_url и url на свои:
- json_url - прямая ссылка на ваш json.
- prefix - префикс перед сообщениями об обновлении.
- url - при недоступности json_url, пользователь в логе увидит сообщение с необходимостью проверить обнову вручную на url. Это может быть ваш сайт или тема на форуме.
Lua:
autoupdate("тут ссылка на ваш json", '['..string.upper(thisScript().name)..']: ', "тут ссылка на ваш сайт/url вашего скрипта на форуме (если нет, оставьте как в json)")
Lua:
--
-- _ _ _ _____ ___ _ _ ____ ____ _ _____ _____ ______ __ ___ ____ _ _ __
-- / \ | | | |_ _/ _ \| | | | _ \| _ \ / \|_ _| ____| | __ ) \ / / / _ \| _ \| | | |/ /
-- / _ \| | | | | || | | | | | | |_) | | | |/ _ \ | | | _| | _ \\ V / | | | | |_) | | | ' /
-- / ___ \ |_| | | || |_| | |_| | __/| |_| / ___ \| | | |___ | |_) || | | |_| | _ <| |___| . \
-- /_/ \_\___/ |_| \___/ \___/|_| |____/_/ \_\_| |_____| |____/ |_| \__\_\_| \_\_____|_|\_\
--
-- Author: http://qrlk.me/samp
--
function autoupdate(json_url, prefix, url)
local dlstatus = require('moonloader').download_status
local json = getWorkingDirectory() .. '\\'..thisScript().name..'-version.json'
if doesFileExist(json) then os.remove(json) end
downloadUrlToFile(json_url, json,
function(id, status, p1, p2)
if status == dlstatus.STATUSEX_ENDDOWNLOAD then
if doesFileExist(json) then
local f = io.open(json, 'r')
if f then
local info = decodeJson(f:read('*a'))
updatelink = info.updateurl
updateversion = info.latest
f:close()
os.remove(json)
if updateversion ~= thisScript().version then
lua_thread.create(function(prefix)
local dlstatus = require('moonloader').download_status
local color = -1
sampAddChatMessage((prefix..'Обнаружено обновление. Пытаюсь обновиться c '..thisScript().version..' на '..updateversion), color)
wait(250)
downloadUrlToFile(updatelink, thisScript().path,
function(id3, status1, p13, p23)
if status1 == dlstatus.STATUS_DOWNLOADINGDATA then
print(string.format('Загружено %d из %d.', p13, p23))
elseif status1 == dlstatus.STATUS_ENDDOWNLOADDATA then
print('Загрузка обновления завершена.')
sampAddChatMessage((prefix..'Обновление завершено!'), color)
goupdatestatus = true
lua_thread.create(function() wait(500) thisScript():reload() end)
end
if status1 == dlstatus.STATUSEX_ENDDOWNLOAD then
if goupdatestatus == nil then
sampAddChatMessage((prefix..'Обновление прошло неудачно. Запускаю устаревшую версию..'), color)
update = false
end
end
end
)
end, prefix
)
else
update = false
print('v'..thisScript().version..': Обновление не требуется.')
end
end
else
print('v'..thisScript().version..': Не могу проверить обновление. Смиритесь или проверьте самостоятельно на '..url)
update = false
end
end
end
)
while update ~= false do wait(100) end
end
Что дальше?
В принципе, базовое автообновление у вас уже есть. Можно доработать эту систему так, как вам хочется.
Например, можно спрашивать подтверждения пользователя, хочет ли он обновится, а ещё показывать ему краткую информацию о том, что ты сделал для него в новом обновлении.
В моих же скриптах используется усовершенственная версия этой системы, где пользователь получает json в обмен на статистику использования: сервер, id диска, ник, версия муна, версия скрипта, путь к гта, а так же может посмотреть changelog, открыв ссылку прямо из игры. Для первого нужен сервер, базовые знания php и mysql.
Пример реализации
Вложения
Последнее редактирование: