AutoSave 1.2.0: autoload, /autosaver load <name>, new-server detection, watcher reinstall
This commit is contained in:
1 parent
b9d0eb6afd
commit
b037722432
1 file changed
+239
-32
+239
-32
@@ -36,6 +36,7 @@ static int gChangeAtStart = 0;
|
|||||||
static int gSavedCount = -1;
|
static int gSavedCount = -1;
|
||||||
static bool gReady = false;
|
static bool gReady = false;
|
||||||
static bool gPreview = true;
|
static bool gPreview = true;
|
||||||
|
static bool gAutoLoad = false;
|
||||||
|
|
||||||
struct Row {
|
struct Row {
|
||||||
ADDR obj;
|
ADDR obj;
|
||||||
@@ -591,8 +592,9 @@ static void prefsToScript()
|
|||||||
"$Pref::Server::AutoSave::Interval = %d;"
|
"$Pref::Server::AutoSave::Interval = %d;"
|
||||||
"$Pref::Server::AutoSave::Chunk = %d;"
|
"$Pref::Server::AutoSave::Chunk = %d;"
|
||||||
"$Pref::Server::AutoSave::Tick = %d;"
|
"$Pref::Server::AutoSave::Tick = %d;"
|
||||||
"$Pref::Server::AutoSave::Preview = %d;",
|
"$Pref::Server::AutoSave::Preview = %d;"
|
||||||
gEnabled ? 1 : 0, gInterval, gChunk, gTickMs, gPreview ? 1 : 0);
|
"$Pref::Server::AutoSave::AutoLoad = %d;",
|
||||||
|
gEnabled ? 1 : 0, gInterval, gChunk, gTickMs, gPreview ? 1 : 0, gAutoLoad ? 1 : 0);
|
||||||
tsf_Eval(code);
|
tsf_Eval(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,6 +616,9 @@ static void prefsFromScript()
|
|||||||
value = varOf("$Pref::Server::AutoSave::Preview");
|
value = varOf("$Pref::Server::AutoSave::Preview");
|
||||||
if (!value.empty())
|
if (!value.empty())
|
||||||
gPreview = truthy(value);
|
gPreview = truthy(value);
|
||||||
|
value = varOf("$Pref::Server::AutoSave::AutoLoad");
|
||||||
|
if (!value.empty())
|
||||||
|
gAutoLoad = truthy(value);
|
||||||
clampPrefs();
|
clampPrefs();
|
||||||
prefsToScript();
|
prefsToScript();
|
||||||
}
|
}
|
||||||
@@ -1592,12 +1597,12 @@ static int clampInterval()
|
|||||||
return gInterval;
|
return gInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gHostSeen = false;
|
static int gServerId = 0;
|
||||||
|
|
||||||
static void reschedule()
|
static void reschedule()
|
||||||
{
|
{
|
||||||
char code[128];
|
char code[128];
|
||||||
int delay = gHostSeen ? clampInterval() * 1000 : 5000;
|
int delay = clampInterval() * 1000;
|
||||||
std::snprintf(code, sizeof(code), "$AutoSave::Schedule = schedule(%d, 0, autoSaveTick);", delay);
|
std::snprintf(code, sizeof(code), "$AutoSave::Schedule = schedule(%d, 0, autoSaveTick);", delay);
|
||||||
tsf_Eval(code);
|
tsf_Eval(code);
|
||||||
}
|
}
|
||||||
@@ -1651,7 +1656,8 @@ function AutoSave_Help(%client)
|
|||||||
AutoSave_Tell(%client, "/autosaver tick <milliseconds, 1-1000>");
|
AutoSave_Tell(%client, "/autosaver tick <milliseconds, 1-1000>");
|
||||||
AutoSave_Tell(%client, "/autosaver screenshot <on or off>");
|
AutoSave_Tell(%client, "/autosaver screenshot <on or off>");
|
||||||
AutoSave_Tell(%client, "/autosaver save");
|
AutoSave_Tell(%client, "/autosaver save");
|
||||||
AutoSave_Tell(%client, "/autosaver load");
|
AutoSave_Tell(%client, "/autosaver load <optional autosave name>");
|
||||||
|
AutoSave_Tell(%client, "/autosaver autoload <on or off>");
|
||||||
}
|
}
|
||||||
function AutoSave_Busy()
|
function AutoSave_Busy()
|
||||||
{
|
{
|
||||||
@@ -1697,19 +1703,74 @@ function AutoSave_ReloadTick()
|
|||||||
$AutoSave::ReloadFile = "";
|
$AutoSave::ReloadFile = "";
|
||||||
serverDirectSaveFileLoad(%file, 3, "", 1, 0);
|
serverDirectSaveFileLoad(%file, 3, "", 1, 0);
|
||||||
}
|
}
|
||||||
function AutoSave_Reload(%client)
|
function AutoSave_AutoLoadStart()
|
||||||
|
{
|
||||||
|
if (isEventPending($AutoSave::AutoLoadSchedule))
|
||||||
|
cancel($AutoSave::AutoLoadSchedule);
|
||||||
|
$AutoSave::AutoLoadTries = 0;
|
||||||
|
AutoSave_AutoLoadWait();
|
||||||
|
}
|
||||||
|
function AutoSave_AutoLoadWait()
|
||||||
|
{
|
||||||
|
if (!$missionRunning || !isObject(mainBrickGroup))
|
||||||
|
{
|
||||||
|
if ($AutoSave::AutoLoadTries++ < 240)
|
||||||
|
$AutoSave::AutoLoadSchedule = schedule(500, 0, AutoSave_AutoLoadWait);
|
||||||
|
else
|
||||||
|
echo("AutoSave: autoload gave up, the mission did not start");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($GameModeArg !$= "")
|
||||||
|
{
|
||||||
|
echo("AutoSave: autoload skipped, a game mode is running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($SaveFileArg !$= "" || AutoSave_Busy() || getBrickCount() > 0)
|
||||||
|
{
|
||||||
|
echo("AutoSave: autoload skipped, the server already has bricks");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
%file = AutoSave_NewestFile();
|
||||||
|
if (%file $= "")
|
||||||
|
{
|
||||||
|
echo("AutoSave: autoload skipped, there is no autosave");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
echo("AutoSave: autoload " @ %file);
|
||||||
|
$AutoSave::AutoLoading = 1;
|
||||||
|
serverDirectSaveFileLoad(%file, 3, "", 1, 0);
|
||||||
|
}
|
||||||
|
function AutoSave_Reload(%client, %wanted)
|
||||||
{
|
{
|
||||||
if ($Game::MissionCleaningUp || AutoSave_Busy() || $AutoSave::ReloadFile !$= "")
|
if ($Game::MissionCleaningUp || AutoSave_Busy() || $AutoSave::ReloadFile !$= "")
|
||||||
{
|
{
|
||||||
AutoSave_Tell(%client, "Bricks are still being cleared or loaded.");
|
AutoSave_Tell(%client, "Bricks are still being cleared or loaded.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
%wanted = trim(%wanted);
|
||||||
|
if (%wanted $= "")
|
||||||
|
{
|
||||||
%file = AutoSave_NewestFile();
|
%file = AutoSave_NewestFile();
|
||||||
if (%file $= "")
|
if (%file $= "")
|
||||||
{
|
{
|
||||||
AutoSave_Tell(%client, "There is no autosave to load.");
|
AutoSave_Tell(%client, "There is no autosave to load.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
%file = autoSaveFind(%wanted);
|
||||||
|
if (getSubStr(%file, 0, 1) $= "*")
|
||||||
|
{
|
||||||
|
AutoSave_Tell(%client, "\c3" @ getSubStr(%file, 1, 10) @ "\c6 autosaves match \c3" @ %wanted @ "\c6. Type more of the name.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (%file $= "")
|
||||||
|
{
|
||||||
|
AutoSave_Tell(%client, "No autosave named \c3" @ %wanted @ "\c6 in saves/autosave/.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
%name = %client.getPlayerName();
|
%name = %client.getPlayerName();
|
||||||
messageAll('', "\c6[\c3AutoSave\c6] \c3" @ %name @ "\c6 is loading \c3saves/autosave/" @ fileName(%file) @ "\c6.");
|
messageAll('', "\c6[\c3AutoSave\c6] \c3" @ %name @ "\c6 is loading \c3saves/autosave/" @ fileName(%file) @ "\c6.");
|
||||||
$AutoSave::ReloadFile = %file;
|
$AutoSave::ReloadFile = %file;
|
||||||
@@ -1734,7 +1795,7 @@ function AutoSave_Command(%client, %cmd, %arg)
|
|||||||
}
|
}
|
||||||
if (%cmd $= "status")
|
if (%cmd $= "status")
|
||||||
{
|
{
|
||||||
AutoSave_Tell(%client, "Enabled \c3" @ ($AutoSave::Enabled ? "on" : "off") @ "\c6, every \c3" @ $AutoSave::Interval @ "\c6 seconds, \c3" @ $AutoSave::Chunk @ "\c6 bricks per slice, \c3" @ $AutoSave::Tick @ "\c6 ms between slices, screenshots \c3" @ ($AutoSave::Preview ? "on" : "off") @ "\c6.");
|
AutoSave_Tell(%client, "Enabled \c3" @ ($AutoSave::Enabled ? "on" : "off") @ "\c6, every \c3" @ $AutoSave::Interval @ "\c6 seconds, \c3" @ $AutoSave::Chunk @ "\c6 bricks per slice, \c3" @ $AutoSave::Tick @ "\c6 ms between slices, screenshots \c3" @ ($AutoSave::Preview ? "on" : "off") @ "\c6, autoload \c3" @ ($AutoSave::AutoLoad ? "on" : "off") @ "\c6.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!AutoSave_Admin(%client))
|
if (!AutoSave_Admin(%client))
|
||||||
@@ -1772,7 +1833,24 @@ function AutoSave_Command(%client, %cmd, %arg)
|
|||||||
}
|
}
|
||||||
if (%cmd $= "load" || %cmd $= "reload")
|
if (%cmd $= "load" || %cmd $= "reload")
|
||||||
{
|
{
|
||||||
AutoSave_Reload(%client);
|
AutoSave_Reload(%client, %arg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (%cmd $= "autoload")
|
||||||
|
{
|
||||||
|
%arg = strlwr(%arg);
|
||||||
|
if (%arg $= "on" || %arg $= "1")
|
||||||
|
%on = 1;
|
||||||
|
else if (%arg $= "off" || %arg $= "0")
|
||||||
|
%on = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AutoSave_Tell(%client, "Use \c3/autosaver autoload on\c6 or \c3/autosaver autoload off\c6.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$AutoSave::AutoLoad = %on;
|
||||||
|
autoSaveApply();
|
||||||
|
messageAll('', "\c6[\c3AutoSave\c6] \c3" @ %name @ "\c6 turned autoload \c3" @ (%on ? "on" : "off") @ "\c6. " @ (%on ? "The newest autosave loads when the server starts." : ""));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (%cmd $= "preview" || %cmd $= "screenshot" || %cmd $= "screenshots")
|
if (%cmd $= "preview" || %cmd $= "screenshot" || %cmd $= "screenshots")
|
||||||
@@ -1834,21 +1912,25 @@ function AutoSave_Command(%client, %cmd, %arg)
|
|||||||
}
|
}
|
||||||
AutoSave_Tell(%client, "Unknown command. Type \c3/autosaver help\c6.");
|
AutoSave_Tell(%client, "Unknown command. Type \c3/autosaver help\c6.");
|
||||||
}
|
}
|
||||||
function serverCmdautosaver(%client, %cmd, %arg)
|
function AutoSave_Join(%a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10)
|
||||||
{
|
{
|
||||||
AutoSave_Command(%client, %cmd, %arg);
|
return trim(%a1 SPC %a2 SPC %a3 SPC %a4 SPC %a5 SPC %a6 SPC %a7 SPC %a8 SPC %a9 SPC %a10);
|
||||||
}
|
}
|
||||||
function serverCmdAutosaver(%client, %cmd, %arg)
|
function serverCmdautosaver(%client, %cmd, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10)
|
||||||
{
|
{
|
||||||
AutoSave_Command(%client, %cmd, %arg);
|
AutoSave_Command(%client, %cmd, AutoSave_Join(%a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10));
|
||||||
}
|
}
|
||||||
function serverCmdAutoSaver(%client, %cmd, %arg)
|
function serverCmdAutosaver(%client, %cmd, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10)
|
||||||
{
|
{
|
||||||
AutoSave_Command(%client, %cmd, %arg);
|
AutoSave_Command(%client, %cmd, AutoSave_Join(%a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10));
|
||||||
}
|
}
|
||||||
function serverCmdAUTOSAVER(%client, %cmd, %arg)
|
function serverCmdAutoSaver(%client, %cmd, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10)
|
||||||
{
|
{
|
||||||
AutoSave_Command(%client, %cmd, %arg);
|
AutoSave_Command(%client, %cmd, AutoSave_Join(%a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10));
|
||||||
|
}
|
||||||
|
function serverCmdAUTOSAVER(%client, %cmd, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10)
|
||||||
|
{
|
||||||
|
AutoSave_Command(%client, %cmd, AutoSave_Join(%a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10));
|
||||||
}
|
}
|
||||||
$AutoSave::ChatInstalled = 1;
|
$AutoSave::ChatInstalled = 1;
|
||||||
)TS";
|
)TS";
|
||||||
@@ -1890,9 +1972,9 @@ package AutoSaveWatch
|
|||||||
{
|
{
|
||||||
%client = findLocalClient();
|
%client = findLocalClient();
|
||||||
if (isObject(%client))
|
if (isObject(%client))
|
||||||
AutoSave_Command(%client, getWord(%body, 1), getWord(%body, 2));
|
AutoSave_Command(%client, getWord(%body, 1), getWords(%body, 2));
|
||||||
else
|
else
|
||||||
commandToServer('autosaver', getWord(%body, 1), getWord(%body, 2));
|
commandToServer('autosaver', getWord(%body, 1), getWords(%body, 2));
|
||||||
Canvas.popDialog(newMessageHud);
|
Canvas.popDialog(newMessageHud);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1918,6 +2000,11 @@ package AutoSaveWatch
|
|||||||
Parent::ServerLoadSaveFile_End();
|
Parent::ServerLoadSaveFile_End();
|
||||||
$AutoSave::Loading = 0;
|
$AutoSave::Loading = 0;
|
||||||
$AutoSave::Change++;
|
$AutoSave::Change++;
|
||||||
|
if ($AutoSave::AutoLoading)
|
||||||
|
{
|
||||||
|
$AutoSave::AutoLoading = 0;
|
||||||
|
autoSaveBaseline();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function serverCmdCancelSaveFileUpload(%client)
|
function serverCmdCancelSaveFileUpload(%client)
|
||||||
{
|
{
|
||||||
@@ -1925,11 +2012,16 @@ package AutoSaveWatch
|
|||||||
if (!isObject($Server_LoadFileObj))
|
if (!isObject($Server_LoadFileObj))
|
||||||
$AutoSave::Loading = 0;
|
$AutoSave::Loading = 0;
|
||||||
$AutoSave::Change++;
|
$AutoSave::Change++;
|
||||||
|
$AutoSave::AutoLoading = 0;
|
||||||
}
|
}
|
||||||
function destroyServer()
|
function destroyServer()
|
||||||
{
|
{
|
||||||
$AutoSave::Loading = 0;
|
$AutoSave::Loading = 0;
|
||||||
|
$AutoSave::AutoLoading = 0;
|
||||||
|
if (isEventPending($AutoSave::AutoLoadSchedule))
|
||||||
|
cancel($AutoSave::AutoLoadSchedule);
|
||||||
Parent::destroyServer();
|
Parent::destroyServer();
|
||||||
|
autoSaveRewatch();
|
||||||
}
|
}
|
||||||
function serverCmdAddEvent(%client, %enabled, %inputEventIdx, %delay, %targetIdx, %NTNameIdx, %outputEventIdx, %par1, %par2, %par3, %par4)
|
function serverCmdAddEvent(%client, %enabled, %inputEventIdx, %delay, %targetIdx, %NTNameIdx, %outputEventIdx, %par1, %par2, %par3, %par4)
|
||||||
{
|
{
|
||||||
@@ -2120,24 +2212,42 @@ static void autoSaveTick(ADDR obj, int argc, const char *argv[])
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
notePreview();
|
notePreview();
|
||||||
if (!hosting()) {
|
if (gServerId != 0 && gEnabled && gPhase == 0 && hosting())
|
||||||
gHostSeen = false;
|
|
||||||
reschedule();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!gHostSeen) {
|
|
||||||
gHostSeen = true;
|
|
||||||
prefsFromScript();
|
|
||||||
BlPrintf("%s: $Pref::Server::AutoSave: %s, every %d seconds, %d bricks per slice, %d ms, preview %s", PROJECT_NAME,
|
|
||||||
gEnabled ? "on" : "off", gInterval, gChunk, gTickMs, gPreview ? "on" : "off");
|
|
||||||
reschedule();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gEnabled && gPhase == 0)
|
|
||||||
beginSave();
|
beginSave();
|
||||||
reschedule();
|
reschedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scheduleHostCheck()
|
||||||
|
{
|
||||||
|
tsf_Eval("if (isEventPending($AutoSave::HostSchedule)) cancel($AutoSave::HostSchedule);"
|
||||||
|
"$AutoSave::HostSchedule = schedule(5000, 0, autoSaveHostCheck);");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each mission creates a new MissionGroup, so its id tells servers apart even
|
||||||
|
when one stops and the next starts between two save intervals. */
|
||||||
|
static void autoSaveHostCheck(ADDR obj, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
(void)obj;
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
ADDR missionGroup = hosting() ? tsf_FindObject("MissionGroup") : 0;
|
||||||
|
int id = missionGroup != 0 ? *(int *)(missionGroup + 0x20) : 0;
|
||||||
|
if (id != 0 && id != gServerId) {
|
||||||
|
gServerId = id;
|
||||||
|
gHaveBaseline = false;
|
||||||
|
prefsFromScript();
|
||||||
|
BlPrintf("%s: $Pref::Server::AutoSave: %s, every %d seconds, %d bricks per slice, %d ms, screenshots %s, autoload %s", PROJECT_NAME,
|
||||||
|
gEnabled ? "on" : "off", gInterval, gChunk, gTickMs, gPreview ? "on" : "off", gAutoLoad ? "on" : "off");
|
||||||
|
if (gAutoLoad && truthy(callFn1("isFunction", "AutoSave_AutoLoadStart")))
|
||||||
|
tsf_Eval("AutoSave_AutoLoadStart();");
|
||||||
|
tsf_Eval("if (isEventPending($AutoSave::Schedule)) cancel($AutoSave::Schedule);");
|
||||||
|
reschedule();
|
||||||
|
} else if (id == 0) {
|
||||||
|
gServerId = 0;
|
||||||
|
}
|
||||||
|
scheduleHostCheck();
|
||||||
|
}
|
||||||
|
|
||||||
static char gReturnText[32];
|
static char gReturnText[32];
|
||||||
|
|
||||||
static const char *autoSaveNow(ADDR obj, int argc, const char *argv[])
|
static const char *autoSaveNow(ADDR obj, int argc, const char *argv[])
|
||||||
@@ -2161,6 +2271,72 @@ static const char *autoSaveNow(ADDR obj, int argc, const char *argv[])
|
|||||||
return gReturnText;
|
return gReturnText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char gFoundPath[MAX_PATH];
|
||||||
|
|
||||||
|
/* Returns saves/autosave/<name>.bls for an exact name (with or without .bls,
|
||||||
|
any case) or for the one file whose name contains the text. "*N" means N
|
||||||
|
files contain it, "" means none. Names cannot leave the folder. */
|
||||||
|
static const char *autoSaveFind(ADDR obj, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
(void)obj;
|
||||||
|
(void)argc;
|
||||||
|
std::string name = argv[1] != 0 ? argv[1] : "";
|
||||||
|
char folder[MAX_PATH];
|
||||||
|
WIN32_FIND_DATAA found;
|
||||||
|
HANDLE handle;
|
||||||
|
std::string match;
|
||||||
|
std::string lowerName;
|
||||||
|
int prefixCount = 0;
|
||||||
|
|
||||||
|
while (!name.empty() && name[0] == ' ')
|
||||||
|
name.erase(0, 1);
|
||||||
|
while (!name.empty() && name[name.size() - 1] == ' ')
|
||||||
|
name.erase(name.size() - 1);
|
||||||
|
if (_strnicmp(name.c_str(), "saves/autosave/", 15) == 0)
|
||||||
|
name.erase(0, 15);
|
||||||
|
if (name.size() >= 4 && _stricmp(name.c_str() + name.size() - 4, ".bls") == 0)
|
||||||
|
name.erase(name.size() - 4);
|
||||||
|
if (name.empty() || name.find_first_of("/\\:*?\"<>|") != std::string::npos || name.find("..") != std::string::npos)
|
||||||
|
return "";
|
||||||
|
if (!gameFile(folder, MAX_PATH, "autosave\\*.bls"))
|
||||||
|
return "";
|
||||||
|
handle = FindFirstFileA(folder, &found);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return "";
|
||||||
|
do {
|
||||||
|
if (found.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
continue;
|
||||||
|
std::string file = found.cFileName;
|
||||||
|
if (file.size() < 4 || _stricmp(file.c_str() + file.size() - 4, ".bls") != 0)
|
||||||
|
continue;
|
||||||
|
std::string base = file.substr(0, file.size() - 4);
|
||||||
|
if (_stricmp(base.c_str(), name.c_str()) == 0) {
|
||||||
|
match = file;
|
||||||
|
prefixCount = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lowerName.empty()) {
|
||||||
|
lowerName = name;
|
||||||
|
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
|
||||||
|
}
|
||||||
|
std::transform(base.begin(), base.end(), base.begin(), ::tolower);
|
||||||
|
if (base.find(lowerName) != std::string::npos) {
|
||||||
|
if (prefixCount == 0)
|
||||||
|
match = file;
|
||||||
|
prefixCount++;
|
||||||
|
}
|
||||||
|
} while (FindNextFileA(handle, &found));
|
||||||
|
FindClose(handle);
|
||||||
|
if (prefixCount == 0)
|
||||||
|
return "";
|
||||||
|
if (prefixCount > 1) {
|
||||||
|
std::snprintf(gFoundPath, sizeof(gFoundPath), "*%d", prefixCount);
|
||||||
|
return gFoundPath;
|
||||||
|
}
|
||||||
|
std::snprintf(gFoundPath, sizeof(gFoundPath), "saves/autosave/%s", match.c_str());
|
||||||
|
return gFoundPath;
|
||||||
|
}
|
||||||
|
|
||||||
static char gNewestPath[MAX_PATH];
|
static char gNewestPath[MAX_PATH];
|
||||||
|
|
||||||
static const char *autoSaveNewest(ADDR obj, int argc, const char *argv[])
|
static const char *autoSaveNewest(ADDR obj, int argc, const char *argv[])
|
||||||
@@ -2213,6 +2389,7 @@ static void deferredInstall()
|
|||||||
if (!gArmed) {
|
if (!gArmed) {
|
||||||
gArmed = true;
|
gArmed = true;
|
||||||
reschedule();
|
reschedule();
|
||||||
|
scheduleHostCheck();
|
||||||
}
|
}
|
||||||
if (!gChat)
|
if (!gChat)
|
||||||
installChat();
|
installChat();
|
||||||
@@ -2237,6 +2414,30 @@ static VOID CALLBACK installTimerProc(HWND hwnd, UINT message, UINT_PTR id, DWOR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* destroyServer deactivates every package activated after the client
|
||||||
|
add-ons, AutoSaveWatch included, so it is installed again afterwards. */
|
||||||
|
static void autoSaveRewatch(ADDR obj, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
(void)obj;
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
gWatching = false;
|
||||||
|
tsf_Eval("$AutoSave::WatchInstalled = 0;");
|
||||||
|
if (gInstallTimer == 0)
|
||||||
|
gInstallTimer = SetTimer(0, 0, 500, installTimerProc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A build that was just loaded from a file matches that file. */
|
||||||
|
static void autoSaveBaseline(ADDR obj, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
(void)obj;
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
gSavedChange = gChange;
|
||||||
|
gSavedCount = brickCount();
|
||||||
|
gHaveBaseline = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool init()
|
bool init()
|
||||||
{
|
{
|
||||||
if (!tsh_InitInternal())
|
if (!tsh_InitInternal())
|
||||||
@@ -2252,14 +2453,19 @@ bool init()
|
|||||||
tsf_AddVar("AutoSave::Change", &gChange);
|
tsf_AddVar("AutoSave::Change", &gChange);
|
||||||
tsf_AddVar("AutoSave::Loading", &gLoading);
|
tsf_AddVar("AutoSave::Loading", &gLoading);
|
||||||
tsf_AddVar("AutoSave::Preview", &gPreview);
|
tsf_AddVar("AutoSave::Preview", &gPreview);
|
||||||
|
tsf_AddVar("AutoSave::AutoLoad", &gAutoLoad);
|
||||||
installPreview();
|
installPreview();
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSaveTick", autoSaveTick, "autoSaveTick() - timed brick save", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSaveTick", autoSaveTick, "autoSaveTick() - timed brick save", 1, 1);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSaveChunk", autoSaveChunk, "autoSaveChunk() - continue a brick save", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSaveChunk", autoSaveChunk, "autoSaveChunk() - continue a brick save", 1, 1);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSaveApply", autoSaveApply, "autoSaveApply() - clamp autosave prefs, write config/server/prefs.cs and reschedule", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSaveApply", autoSaveApply, "autoSaveApply() - clamp autosave prefs, write config/server/prefs.cs and reschedule", 1, 1);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSave", autoSaveNow, "autoSave() - write a dated save in saves/autosave/", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSave", autoSaveNow, "autoSave() - write a dated save in saves/autosave/", 1, 1);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSaveNewest", autoSaveNewest, "autoSaveNewest() - newest file in saves/autosave/", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSaveNewest", autoSaveNewest, "autoSaveNewest() - newest file in saves/autosave/", 1, 1);
|
||||||
|
tsf_AddConsoleFunc(0, 0, "autoSaveFind", autoSaveFind, "autoSaveFind(name) - saves/autosave/ file by name or unique start", 2, 2);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSavePreviewPoll", autoSavePreviewPoll, "autoSavePreviewPoll() - report a finished save screenshot", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSavePreviewPoll", autoSavePreviewPoll, "autoSavePreviewPoll() - report a finished save screenshot", 1, 1);
|
||||||
tsf_AddConsoleFunc(0, 0, "autoSaveTraceStep", autoSaveTraceStep, "autoSaveTraceStep() - trace part of a save screenshot", 1, 1);
|
tsf_AddConsoleFunc(0, 0, "autoSaveTraceStep", autoSaveTraceStep, "autoSaveTraceStep() - trace part of a save screenshot", 1, 1);
|
||||||
|
tsf_AddConsoleFunc(0, 0, "autoSaveHostCheck", autoSaveHostCheck, "autoSaveHostCheck() - notice a new server", 1, 1);
|
||||||
|
tsf_AddConsoleFunc(0, 0, "autoSaveRewatch", autoSaveRewatch, "autoSaveRewatch() - install the change watcher again", 1, 1);
|
||||||
|
tsf_AddConsoleFunc(0, 0, "autoSaveBaseline", autoSaveBaseline, "autoSaveBaseline() - treat the current build as saved", 1, 1);
|
||||||
gInstallTimer = SetTimer(0, 0, 500, installTimerProc);
|
gInstallTimer = SetTimer(0, 0, 500, installTimerProc);
|
||||||
if (gInstallTimer == 0)
|
if (gInstallTimer == 0)
|
||||||
BlPrintf("%s: could not start the install timer", PROJECT_NAME);
|
BlPrintf("%s: could not start the install timer", PROJECT_NAME);
|
||||||
@@ -2279,6 +2485,7 @@ bool deinit()
|
|||||||
tsf_Eval("if (isEventPending($AutoSave::ChunkSchedule)) cancel($AutoSave::ChunkSchedule);");
|
tsf_Eval("if (isEventPending($AutoSave::ChunkSchedule)) cancel($AutoSave::ChunkSchedule);");
|
||||||
tsf_Eval("if (isEventPending($AutoSave::PreviewSchedule)) cancel($AutoSave::PreviewSchedule);");
|
tsf_Eval("if (isEventPending($AutoSave::PreviewSchedule)) cancel($AutoSave::PreviewSchedule);");
|
||||||
tsf_Eval("if (isEventPending($AutoSave::TraceSchedule)) cancel($AutoSave::TraceSchedule);");
|
tsf_Eval("if (isEventPending($AutoSave::TraceSchedule)) cancel($AutoSave::TraceSchedule);");
|
||||||
|
tsf_Eval("if (isEventPending($AutoSave::HostSchedule)) cancel($AutoSave::HostSchedule);");
|
||||||
if (gWatching)
|
if (gWatching)
|
||||||
tsf_Eval("deactivatePackage(AutoSaveWatch);");
|
tsf_Eval("deactivatePackage(AutoSaveWatch);");
|
||||||
clearSave();
|
clearSave();
|
||||||
|
|||||||
Reference in new issue
Block a user