Also update binary with updater

This commit is contained in:
fed 2022-01-31 08:48:56 +01:00
parent b2247f7ae3
commit d910ea5df5
6 changed files with 110 additions and 26 deletions

View File

@ -1150,7 +1150,7 @@ namespace ui_scripting::lua
if (result.has_value()) if (result.has_value())
{ {
const auto write = utils::io::write_file(dest, result.value(), false); const auto write = utils::io::write_file(dest, result.value(), false);
event.arguments = {id, write}; event.arguments = {id, true, write};
} }
else else
{ {
@ -1179,6 +1179,12 @@ namespace ui_scripting::lua
return self.get_name(); return self.get_name();
}; };
game_type["relaunch"] = [](const game&)
{
utils::nt::relaunch_self("-singleplayer");
utils::nt::terminate();
};
struct player struct player
{ {
}; };

View File

@ -62,14 +62,27 @@ namespace ui_scripting
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base; state->m_apistack.top = state->m_apistack.base;
game::hks::hksi_lua_pushlstring(state, value, (unsigned int)strlen(value)); game::hks::hksi_lua_pushlstring(state, value, static_cast<unsigned int>(strlen(value)));
obj = state->m_apistack.top[-1];
this->value_ = obj;
}
script_value::script_value(const char* value, unsigned int len)
{
game::hks::HksObject obj{};
const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
game::hks::hksi_lua_pushlstring(state, value, len);
obj = state->m_apistack.top[-1]; obj = state->m_apistack.top[-1];
this->value_ = obj; this->value_ = obj;
} }
script_value::script_value(const std::string& value) script_value::script_value(const std::string& value)
: script_value(value.data()) : script_value(value.data(), static_cast<unsigned int>(value.size()))
{ {
} }

View File

@ -22,6 +22,7 @@ namespace ui_scripting
script_value(double value); script_value(double value);
script_value(const char* value); script_value(const char* value);
script_value(const char* value, unsigned int len);
script_value(const std::string& value); script_value(const std::string& value);
script_value(const lightuserdata& value); script_value(const lightuserdata& value);

View File

@ -96,7 +96,6 @@ LUI.addmenubutton("pc_controls", {
stack = {} stack = {}
LUI.MenuBuilder.m_types_build["generic_waiting_popup_"] = function (menu, event) LUI.MenuBuilder.m_types_build["generic_waiting_popup_"] = function (menu, event)
local oncancel = stack.oncancel local oncancel = stack.oncancel
local popup = LUI.MenuBuilder.BuildRegisteredType("waiting_popup", { local popup = LUI.MenuBuilder.BuildRegisteredType("waiting_popup", {
message_text = stack.text, message_text = stack.text,
isLiveWithCancel = true, isLiveWithCancel = true,
@ -115,13 +114,10 @@ LUI.MenuBuilder.m_types_build["generic_waiting_popup_"] = function (menu, event)
end end
LUI.MenuBuilder.m_types_build["generic_yes_no_popup_"] = function() LUI.MenuBuilder.m_types_build["generic_yes_no_popup_"] = function()
local title = stack.title
local text = stack.text
local callback = stack.callback local callback = stack.callback
local popup = LUI.MenuBuilder.BuildRegisteredType("generic_yesno_popup", { local popup = LUI.MenuBuilder.BuildRegisteredType("generic_yesno_popup", {
popup_title = title, popup_title = stack.title,
message_text = text, message_text = stack.text,
yes_action = function() yes_action = function()
callback(true) callback(true)
end, end,
@ -137,6 +133,22 @@ LUI.MenuBuilder.m_types_build["generic_yes_no_popup_"] = function()
return popup return popup
end end
LUI.MenuBuilder.m_types_build["generic_confirmation_popup_"] = function()
local popup = LUI.MenuBuilder.BuildRegisteredType( "generic_confirmation_popup", {
cancel_will_close = false,
popup_title = stack.title,
message_text = stack.text,
button_text = stack.buttontext,
confirmation_action = stack.callback
})
stack = {
ret = popup
}
return stack.ret
end
LUI.yesnopopup = function(data) LUI.yesnopopup = function(data)
for k, v in luiglobals.next, data do for k, v in luiglobals.next, data do
stack[k] = v stack[k] = v
@ -145,6 +157,14 @@ LUI.yesnopopup = function(data)
return stack.ret return stack.ret
end end
LUI.confirmationpopup = function(data)
for k, v in luiglobals.next, data do
stack[k] = v
end
LUI.FlowManager.RequestPopupMenu(nil, "generic_confirmation_popup_")
return stack.ret
end
function updaterpopup(oncancel) function updaterpopup(oncancel)
return LUI.openpopupmenu("generic_waiting_popup_", { return LUI.openpopupmenu("generic_waiting_popup_", {
oncancel = oncancel, oncancel = oncancel,
@ -155,16 +175,22 @@ end
function verifyfiles(files) function verifyfiles(files)
local needed = {} local needed = {}
local needtoupdatebinary = false
local binaryname = game:binaryname() local binaryname = game:binaryname()
for i = 1, #files do for i = 1, #files do
local name = files[i][1] local name = files[i][1]
if (name ~= binaryname and (not io.fileexists(files[i][1]) or game:sha(io.readfile(files[i][1])) ~= files[i][3])) then
if (not io.fileexists(name) or game:sha(io.readfile(name)) ~= files[i][3]) then
if (name == game:binaryname()) then
needtoupdatebinary = true
end
table.insert(needed, files[i]) table.insert(needed, files[i])
end end
end end
return needed return needed, needtoupdatebinary
end end
local canceled = false local canceled = false
@ -193,18 +219,24 @@ function downloadfiles(popup, files, callback)
return return
end end
local url = "https://master.fed0001.xyz/" .. folder .. "/" .. files[index][1] local filename = files[index][1]
text:setText(string.format("Downloading file [%i/%i]\n%s", index, #files, files[index][1]))
httprequest(url, function(valid, data) local url = "https://master.fed0001.xyz/" .. folder .. "/" .. filename
text:setText(string.format("Downloading file [%i/%i]\n%s", index, #files, filename))
if (filename == game:binaryname()) then
io.movefile(filename, filename .. ".old")
end
httprequesttofile(url, filename, function(valid, success)
if (not valid) then if (not valid) then
callback(false, "Invalid server response") callback(false, "Invalid server response")
stop = true stop = true
return return
end end
if (not io.writefile(files[index][1], data, false)) then if (not success) then
callback(false, "Failed to write file " .. files[index][1]) callback(false, "Failed to write file " .. filename)
stop = true stop = true
return return
end end
@ -251,7 +283,7 @@ function tryupdate(autoclose)
local valid = pcall(function() local valid = pcall(function()
local files = json.decode(data) local files = json.decode(data)
local needed = verifyfiles(files) local needed, updatebinary = verifyfiles(files)
if (#needed == 0) then if (#needed == 0) then
text:setText("No updates available") text:setText("No updates available")
@ -270,15 +302,28 @@ function tryupdate(autoclose)
gotresult = true gotresult = true
if (result and #needed > 0) then
game:executecommand("lui_restart")
end
if (not result) then if (not result) then
text:setText("Update failed: " .. error) text:setText("Update failed: " .. error)
return return
end end
if (updatebinary) then
LUI.confirmationpopup({
title = "RESTART REQUIRED",
text = "Update requires restart, relaunch now?",
buttontext = "RESTART",
callback = function()
game:relaunch()
end
})
return
end
if (result and #needed > 0) then
game:executecommand("lui_restart")
return
end
text:setText("Update successful!") text:setText("Update successful!")
if (autoclose) then if (autoclose) then
@ -327,6 +372,19 @@ function httprequest(url, callback)
end) end)
end end
function httprequesttofile(url, dest, callback)
local request = game:httpgettofile(url, dest)
local listener = nil
listener = game:onnotify("http_request_done", function(id, valid, success)
if (id ~= request) then
return
end
listener:clear()
callback(valid, success)
end)
end
local localize = Engine.Localize local localize = Engine.Localize
Engine.Localize = function(...) Engine.Localize = function(...)
local args = {...} local args = {...}

View File

@ -1,4 +1,5 @@
#include "nt.hpp" #include "nt.hpp"
#include "string.hpp"
namespace utils::nt namespace utils::nt
{ {
@ -225,7 +226,7 @@ namespace utils::nt
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res)); return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
} }
void relaunch_self() void relaunch_self(const std::string& extra_command_line)
{ {
const utils::nt::library self; const utils::nt::library self;
@ -238,9 +239,14 @@ namespace utils::nt
char current_dir[MAX_PATH]; char current_dir[MAX_PATH];
GetCurrentDirectoryA(sizeof(current_dir), current_dir); GetCurrentDirectoryA(sizeof(current_dir), current_dir);
auto* const command_line = GetCommandLineA();
CreateProcessA(self.get_path().data(), command_line, nullptr, nullptr, false, NULL, nullptr, current_dir, std::string command_line = GetCommandLineA();
if (!extra_command_line.empty())
{
command_line += " " + extra_command_line;
}
CreateProcessA(self.get_path().data(), command_line.data(), nullptr, nullptr, false, NULL, nullptr, current_dir,
&startup_info, &process_info); &startup_info, &process_info);
if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread); if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread);

View File

@ -105,6 +105,6 @@ namespace utils::nt
__declspec(noreturn) void raise_hard_exception(); __declspec(noreturn) void raise_hard_exception();
std::string load_resource(int id); std::string load_resource(int id);
void relaunch_self(); void relaunch_self(const std::string& extra_command_line = "");
__declspec(noreturn) void terminate(uint32_t code = 0); __declspec(noreturn) void terminate(uint32_t code = 0);
} }