diff --git a/README.md b/README.md index 7d533b1..8d694f4 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Detours and reimplements the entire GSC VM + compiler. Adds custom GSC functions. +# Installation +Move the `t4sp-server-plugin.dll` to `%LOCALAPPDATA%\Plutonium\storage\t4\plugins\`, the plugin will be loaded when you start up a dedicated server for Plutonium T4SP. + ## FileIO This plugin provides FileIO interface to GSC for reading and writing files, this is exact to [CoD4x's](https://github.com/callofduty4x/CoD4x_Server/blob/master/scriptdocumentation/script_functions_reference.md#file-operations) interface. @@ -17,7 +20,7 @@ However, all reads and writes will take place strictly and only in the `scriptda All files will be closed upon GSC restart (map_restart or fast_restart or missionfailed, etc), only a maximum of 10 files may be opened at once. * ` FS_TestFile()` Returns `true` if the file exists, `false` otherwise. -* ` FS_Remove()` Deletes the file, return `true` if successful, `false` otherwise. +* ` FS_Remove(, <(optional) use_global bool>)` Deletes the file, return `true` if successful, `false` otherwise. `use_global` will use non mod specific folder. ```gsc // test to see if "scriptdata/test.txt" file exists if (FS_TestFile("test.txt")) // not a typo, all file io will take place inside the "scriptdata" folder @@ -39,7 +42,7 @@ All files will be closed upon GSC restart (map_restart or fast_restart or missio FS_FCloseAll(); // close them all ``` -* ` FS_FOpen(, )` Tries to open the file, mode must be one of `read`, `write` (clears the file), `append` (appends to the file), returns the filehandle. Will return `0` if failed to open. +* ` FS_FOpen(, , <(optional) use_global bool>)` Tries to open the file, mode must be one of `read`, `write` (clears the file), `append` (appends to the file), returns the filehandle. Will return `0` if failed to open. `use_global` will use non mod specific folder (only applies to `write` mode). * `FS_FClose()` Closes the file pointed by the filehandle given, which was returned from `FS_FOpen`. ```gsc // opens "scriptdata/test.txt", all io will take place inside the "scriptdata" folder @@ -101,11 +104,12 @@ All files will be closed upon GSC restart (map_restart or fast_restart or missio // do something with the filename filepath = folder + filename; } + +* ` FS_Length()` Returns the length in bytes of the open'd file. +* ` FS_GetSeek()` Returns the seek of the open'd file (only for reading). +* ` FS_Seek(, )` Sets the seek of the open'd file (only for reading). ``` -# Installation -Move the `t4sp-server-plugin.dll` to `%LOCALAPPDATA%\Plutonium\storage\t4\plugins\`, the plugin will be loaded when you start up a dedicated server for Plutonium T4SP. - # Credits - momo5502 (https://github.com/momo5502) - xensik (https://github.com/xensik/gsc-tool) diff --git a/src/component/fileio.cpp b/src/component/fileio.cpp index 6ca4134..f107aca 100644 --- a/src/component/fileio.cpp +++ b/src/component/fileio.cpp @@ -66,7 +66,7 @@ namespace fileio return path.starts_with("scriptdata/") ? path : "scriptdata/" + path; } - std::filesystem::path build_full_path(const std::string& path) + std::filesystem::path build_full_path(const std::string& path, bool use_global) { static game::dvar_s* fs_localAppData = nullptr; static game::dvar_s* fs_gamedir = nullptr; @@ -81,7 +81,7 @@ namespace fileio fs_gamedir = game::Dvar_FindVar("fs_game"); } - return std::filesystem::path(fs_localAppData->current.string) / (*fs_gamedir->current.string ? fs_gamedir->current.string : "raw") / path; + return std::filesystem::path(fs_localAppData->current.string) / (!use_global && *fs_gamedir->current.string ? fs_gamedir->current.string : "raw") / path; } void free_scr_fh(scr_fh_t& scr_fh) @@ -237,7 +237,7 @@ namespace fileio } else if (mode == "write"s || mode == "append"s) { - auto full_path = build_full_path(fpath); + auto full_path = build_full_path(fpath, game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 3 && game::Scr_GetType(game::SCRIPTINSTANCE_SERVER, 2) == game::VAR_INTEGER && game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 2)); if (!utils::io::write_file(full_path.string(), "", (mode == "append"s))) { @@ -384,10 +384,48 @@ namespace fileio game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1); }); + gsc::function::add("fs_length", []() + { + auto fh = scr_get_fh(); + + if (scr_fhs[fh].type == scr_fh_type_e::UNUSED) + { + game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened"); + } + + game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, scr_fhs[fh].file_length); + }); + + gsc::function::add("fs_getseek", []() + { + auto fh = scr_get_fh(); + + // write seek would require completely redoing how we write files... + if (scr_fhs[fh].type != scr_fh_type_e::READ) + { + game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading"); + } + + game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, scr_fhs[fh].seek); + }); + + gsc::function::add("fs_seek", []() + { + auto fh = scr_get_fh(); + + if (scr_fhs[fh].type != scr_fh_type_e::READ) + { + game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading"); + } + + scr_fhs[fh].seek = std::clamp(game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 1), 0, scr_fhs[fh].file_length); + game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1); + }); + gsc::function::add("fs_remove", []() { auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER)); - auto full_path = build_full_path(fpath); + auto full_path = build_full_path(fpath, game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 2 && game::Scr_GetType(game::SCRIPTINSTANCE_SERVER, 1) == game::VAR_INTEGER && game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 1)); if (!utils::io::remove_file(full_path.string())) {