rpg/ui/scene moved to archive/ earlier left a handful of otherwise-generic systems with dead references into them: - asset/loader/chunk existed solely to load rpg overworld map chunks (tile_t, worldpos_t) - deleted outright, along with its ASSET_LOADER_TYPE_CHUNK entry in assetloader.c/h. - save/slot wrapped party_t/storyflagval_t/map-name/cutscene-path, which is 100% rpg save data - deleted outright (save.c/h, savedevice.c/h and the Linux save backend keep their generic settings/device-discovery logic, just lose the slot read/write pieces that only existed for it). - locale/localemanager.c and test/CMakeLists.txt/test/save/* had a few stray includes and test cases that only existed for the now-gone code. Also restores assets/locale/en_US.po (copied back from archive/assets/) - locale init still needs a real locale file to boot into, even with the asset-moving/archiving done separately. Co-Authored-By: Claude Sonnet 5 <[email protected]>
155 lines
4.2 KiB
C
155 lines
4.2 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "save/savedevice.h"
|
|
#include "save/savedevicelinux.h"
|
|
#include "save/settings/savesettings.h"
|
|
#include "save/savejson.h"
|
|
#include "asset/asset.h"
|
|
#include "assert/assert.h"
|
|
#include "util/mkdirp.h"
|
|
#include "util/string.h"
|
|
|
|
errorret_t saveDeviceLinuxInit(savedevice_t *device) {
|
|
assertNotNull(device, "device cannot be null");
|
|
|
|
device->state = SAVE_DEVICE_STATE_UNKNOWN;
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxUpdate(savedevice_t *device) {
|
|
assertNotNull(device, "device cannot be null");
|
|
assertIsMainThread("Invalid thread");
|
|
errorOk();
|
|
}
|
|
|
|
void saveDeviceLinuxCheckAvailability(savedevice_t *device) {
|
|
assertNotNull(device, "device cannot be null");
|
|
assertIsMainThread("Invalid thread");
|
|
assertTrue(
|
|
device->state == SAVE_DEVICE_STATE_CHECKING_AVAILABILITY,
|
|
"Device state incorrect?"
|
|
);
|
|
|
|
// Resolve the save directory - can't actually fail (just a
|
|
// stringFormat), unlike when this derived from $HOME, but this function
|
|
// returns void (via saveDeviceFireCallback below) rather than
|
|
// errorret_t, so there's no return-early errorChain to use here.
|
|
char_t directory[SAVE_DEVICE_LINUX_PATH_MAX];
|
|
errorret_t directoryResult = saveDeviceLinuxGetDirectory(
|
|
directory, sizeof(directory)
|
|
);
|
|
if(errorIsNotOk(directoryResult)) errorCatch(errorPrint(directoryResult));
|
|
|
|
// Mkdirp the save directory.
|
|
int mkdirpResult = mkdirp(directory, 0700);
|
|
if(mkdirpResult != 0) {
|
|
device->state = SAVE_DEVICE_STATE_UNAVAILABLE;
|
|
device->reasonKey = "save.linux.mkdirp_failed";
|
|
return saveDeviceFireCallback(device);
|
|
}
|
|
|
|
// The save device is available.
|
|
device->state = SAVE_DEVICE_STATE_AVAILABLE;
|
|
device->reasonKey = NULL;
|
|
saveDeviceFireCallback(device);
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxGetDirectory(char_t *dest, const size_t destSize) {
|
|
assertNotNull(dest, "dest cannot be null");
|
|
|
|
stringFormat(
|
|
dest, destSize, "%s/%s",
|
|
ASSET.baseDirectory, SAVE_DEVICE_LINUX_SAVES_SUBDIR_NAME
|
|
);
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxGetSettingsPath(
|
|
char_t *dest,
|
|
const size_t destSize
|
|
) {
|
|
assertNotNull(dest, "dest cannot be null");
|
|
|
|
char_t directory[SAVE_DEVICE_LINUX_PATH_MAX];
|
|
errorChain(saveDeviceLinuxGetDirectory(directory, sizeof(directory)));
|
|
|
|
stringFormat(
|
|
dest, destSize, "%s/%s", directory, SAVE_DEVICE_LINUX_SETTINGS_FILENAME
|
|
);
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxSettingsWrite(
|
|
savedevice_t *device,
|
|
savesettings_t *settings
|
|
) {
|
|
assertNotNull(device, "device cannot be null");
|
|
assertNotNull(settings, "settings cannot be null");
|
|
|
|
char_t path[SAVE_DEVICE_LINUX_PATH_MAX];
|
|
errorChain(saveDeviceLinuxGetSettingsPath(path, sizeof(path)));
|
|
|
|
writeInit();
|
|
|
|
errorret_t writeResult = saveSettingsWriteJSON(settings, doc, object);
|
|
if(errorIsNotOk(writeResult)) {
|
|
yyjson_mut_doc_free(doc);
|
|
errorChain(writeResult);
|
|
}
|
|
|
|
yyjson_write_err writeErr;
|
|
bool_t written = yyjson_mut_write_file(path, doc, 0, NULL, &writeErr);
|
|
yyjson_mut_doc_free(doc);
|
|
|
|
if(!written) {
|
|
errorThrow(
|
|
"Failed to write save settings file: %s (%s)", path, writeErr.msg
|
|
);
|
|
}
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxSettingsRead(
|
|
savedevice_t *device,
|
|
savesettings_t *settings
|
|
) {
|
|
assertNotNull(device, "device cannot be null");
|
|
assertNotNull(settings, "settings cannot be null");
|
|
|
|
char_t path[SAVE_DEVICE_LINUX_PATH_MAX];
|
|
errorChain(saveDeviceLinuxGetSettingsPath(path, sizeof(path)));
|
|
|
|
yyjson_read_err readErr;
|
|
yyjson_doc *jsonDoc = yyjson_read_file(path, 0, NULL, &readErr);
|
|
if(jsonDoc == NULL) {
|
|
// No settings file yet, leave settings as-is.
|
|
if(readErr.code == YYJSON_READ_ERROR_FILE_OPEN) errorOk();
|
|
errorThrow(
|
|
"Failed to parse save settings file: %s (%s)", path, readErr.msg
|
|
);
|
|
}
|
|
|
|
yyjson_val *object = yyjson_doc_get_root(jsonDoc);
|
|
if(object == NULL) {
|
|
yyjson_doc_free(jsonDoc);
|
|
errorThrow("Save settings file missing root object: %s", path);
|
|
}
|
|
|
|
errorret_t readResult = saveSettingsReadJSON(settings, object);
|
|
yyjson_doc_free(jsonDoc);
|
|
errorChain(readResult);
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t saveDeviceLinuxDispose(savedevice_t *device) {
|
|
errorOk();
|
|
}
|