Compare commits

..

No commits in common. "0cd113b33f8c117006509f261488af6e4cabeaa7" and "a3a7b8847c8f42d25526319e9540a535ce2fb348" have entirely different histories.

9 changed files with 42 additions and 182 deletions

3
.gitmodules vendored
View File

@ -29,6 +29,3 @@
[submodule "deps/SQLiteCpp"] [submodule "deps/SQLiteCpp"]
path = deps/SQLiteCpp path = deps/SQLiteCpp
url = https://github.com/SRombauts/SQLiteCpp url = https://github.com/SRombauts/SQLiteCpp
[submodule "deps/plutonium-sdk"]
path = deps/plutonium-sdk
url = https://github.com/plutoniummod/plutonium-sdk.git

View File

@ -9,9 +9,6 @@ Detours and reimplements the entire GSC VM + compiler.
Adds custom GSC functions. Adds custom GSC functions.
# Installation
Move the `t4sp-server-plugin.dll` to `%LOCALAPPDATA%\Plutonium\plugins\`, the plugin will be loaded when you start up a dedicated server for Plutonium T4SP.
## FileIO ## 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. 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.
@ -20,7 +17,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. 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.
* `<bool> FS_TestFile(<filename string>)` Returns `true` if the file exists, `false` otherwise. * `<bool> FS_TestFile(<filename string>)` Returns `true` if the file exists, `false` otherwise.
* `<bool> FS_Remove(<filename string>, <(optional) use_global bool>)` Deletes the file, return `true` if successful, `false` otherwise. `use_global` will use non mod specific folder. * `<bool> FS_Remove(<filename string>)` Deletes the file, return `true` if successful, `false` otherwise.
```gsc ```gsc
// test to see if "scriptdata/test.txt" file exists // 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 if (FS_TestFile("test.txt")) // not a typo, all file io will take place inside the "scriptdata" folder
@ -42,7 +39,7 @@ All files will be closed upon GSC restart (map_restart or fast_restart or missio
FS_FCloseAll(); // close them all FS_FCloseAll(); // close them all
``` ```
* `<int> FS_FOpen(<filename string>, <mode string>, <(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). * `<int> FS_FOpen(<filename string>, <mode string>)` 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_FClose(<filehandle int>)` Closes the file pointed by the filehandle given, which was returned from `FS_FOpen`. * `FS_FClose(<filehandle int>)` Closes the file pointed by the filehandle given, which was returned from `FS_FOpen`.
```gsc ```gsc
// opens "scriptdata/test.txt", all io will take place inside the "scriptdata" folder // opens "scriptdata/test.txt", all io will take place inside the "scriptdata" folder
@ -105,10 +102,9 @@ All files will be closed upon GSC restart (map_restart or fast_restart or missio
filepath = folder + filename; filepath = folder + filename;
} }
``` ```
* `<int> FS_Length(<filehandle int>)` Returns the length in bytes of the open'd file. # Installation
* `<int> FS_GetSeek(<filehandle int>)` Returns the seek of the open'd file (only for reading). 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.
* `<int> FS_Seek(<filehandle int>, <seek int>)` Sets the seek of the open'd file (only for reading).
# Credits # Credits
- momo5502 (https://github.com/momo5502) - momo5502 (https://github.com/momo5502)

1
deps/plutonium-sdk vendored

@ -1 +0,0 @@
Subproject commit 17e9a0a4d5e1133b50f879e3db07e97d1bf92e10

View File

@ -1,18 +0,0 @@
plutonium_sdk = {
source = path.join(dependencies.basePath, "plutonium-sdk"),
}
function plutonium_sdk.import()
plutonium_sdk.includes()
end
function plutonium_sdk.includes()
includedirs {
plutonium_sdk.source,
}
end
function plutonium_sdk.project()
end
table.insert(dependencies, plutonium_sdk)

View File

@ -66,7 +66,7 @@ namespace fileio
return path.starts_with("scriptdata/") ? path : "scriptdata/" + path; return path.starts_with("scriptdata/") ? path : "scriptdata/" + path;
} }
std::filesystem::path build_full_path(const std::string& path, bool use_global) std::filesystem::path build_full_path(const std::string& path)
{ {
static game::dvar_s* fs_localAppData = nullptr; static game::dvar_s* fs_localAppData = nullptr;
static game::dvar_s* fs_gamedir = nullptr; static game::dvar_s* fs_gamedir = nullptr;
@ -81,7 +81,7 @@ namespace fileio
fs_gamedir = game::Dvar_FindVar("fs_game"); fs_gamedir = game::Dvar_FindVar("fs_game");
} }
return std::filesystem::path(fs_localAppData->current.string) / (!use_global && *fs_gamedir->current.string ? fs_gamedir->current.string : "raw") / path; return std::filesystem::path(fs_localAppData->current.string) / (*fs_gamedir->current.string ? fs_gamedir->current.string : "raw") / path;
} }
void free_scr_fh(scr_fh_t& scr_fh) void free_scr_fh(scr_fh_t& scr_fh)
@ -237,7 +237,7 @@ namespace fileio
} }
else if (mode == "write"s || mode == "append"s) else if (mode == "write"s || mode == "append"s)
{ {
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)); auto full_path = build_full_path(fpath);
if (!utils::io::write_file(full_path.string(), "", (mode == "append"s))) if (!utils::io::write_file(full_path.string(), "", (mode == "append"s)))
{ {
@ -384,48 +384,10 @@ namespace fileio
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1); 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", []() gsc::function::add("fs_remove", []()
{ {
auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER)); auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER));
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)); auto full_path = build_full_path(fpath);
if (!utils::io::remove_file(full_path.string())) if (!utils::io::remove_file(full_path.string()))
{ {

View File

@ -1,11 +1,40 @@
#include <stdinc.hpp> #include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "component/signatures.hpp"
PLUTONIUM_API plutonium::sdk::plugin* PLUTONIUM_CALLBACK on_initialize() #include <utils/hook.hpp>
{
return plugin::get();
}
BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD ul_reason_for_call, LPVOID /*reserved_*/) BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD ul_reason_for_call, LPVOID /*reserved_*/)
{ {
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if (game::environment::t4sp())
{
if (!signatures::process())
{
MessageBoxA(NULL,
std::format("This version of t4sp-server-plugin is outdated.\n" \
"Download the latest dll from here: https://github.com/JezuzLizard/T4SP-Server-Plugin/releases\n" \
"'{}' failed", signatures::get_err_reason()).c_str(),
"ERROR", MB_ICONERROR);
return FALSE;
}
if (game::plutonium::printf.get() != nullptr)
{
utils::hook::jump(reinterpret_cast<uintptr_t>(&printf), game::plutonium::printf);
}
component_loader::post_unpack();
}
else
{
MessageBoxA(nullptr, "Unsupported game executable. (t4sp is only supported)", "ERROR, BRO!", 0);
return FALSE;
}
}
return TRUE; return TRUE;
} }

View File

@ -1,73 +0,0 @@
#include <stdinc.hpp>
#include "component/signatures.hpp"
#include <utils/hook.hpp>
#include "loader/component_loader.hpp"
namespace plugin
{
std::uint32_t plugin::plugin_version()
{
return 1;
}
const char* plugin::plugin_name()
{
return "t4sp-server-plugin";
}
bool plugin::is_game_supported(plutonium::sdk::game game)
{
return game == plutonium::sdk::game::t4;
}
void plugin::on_startup(plutonium::sdk::iinterface* interface_ptr, plutonium::sdk::game game)
{
this->interface_ = interface_ptr;
this->game_ = game;
if (!game::environment::t4sp())
{
MessageBoxA(nullptr, "Unsupported game executable. (t4sp is only supported)", "ERROR, BRO!", 0);
return;
}
if (!signatures::process())
{
MessageBoxA(NULL,
std::format("This version of t4sp-server-plugin is outdated.\n" \
"Download the latest dll from here: https://github.com/JezuzLizard/T4SP-Server-Plugin/releases\n" \
"'{}' failed", signatures::get_err_reason()).c_str(),
"ERROR", MB_ICONERROR);
return;
}
if (game::plutonium::printf.get() != nullptr)
{
utils::hook::jump(reinterpret_cast<uintptr_t>(&printf), game::plutonium::printf);
}
component_loader::post_unpack();
}
void plugin::on_shutdown()
{
}
plutonium::sdk::iinterface* plugin::get_interface()
{
return this->interface_;
}
plutonium::sdk::game plugin::get_game()
{
return this->game_;
}
plugin* get()
{
static plugin instance;
return &instance;
}
}

View File

@ -1,30 +0,0 @@
#pragma once
#include <plutonium_sdk.hpp>
namespace plugin
{
class plugin : public plutonium::sdk::plugin
{
public:
~plugin() = default;
std::uint32_t plugin_version() override;
const char* plugin_name() override;
bool is_game_supported(plutonium::sdk::game game) override;
void on_startup(plutonium::sdk::iinterface* interface_ptr, plutonium::sdk::game game) override;
void on_shutdown() override;
plutonium::sdk::iinterface* get_interface();
plutonium::sdk::game get_game();
private:
plutonium::sdk::iinterface* interface_{};
plutonium::sdk::game game_{};
};
plugin* get();
}

View File

@ -71,8 +71,6 @@
#include "game/structs.hpp" #include "game/structs.hpp"
#include "game/symbols.hpp" #include "game/symbols.hpp"
#include "plugin.hpp"
std::string build_gsc_dump(game::scriptInstance_t inst); std::string build_gsc_dump(game::scriptInstance_t inst);
void push_opcode_history(game::scriptInstance_t inst, game::OpcodeVM op); void push_opcode_history(game::scriptInstance_t inst, game::OpcodeVM op);
void push_builtin_history(game::scriptInstance_t inst, int idx); void push_builtin_history(game::scriptInstance_t inst, int idx);