Allow custom paths/home folder paths for cathook data at runtime

This commit is contained in:
TotallyNotElite 2020-03-01 01:21:45 +01:00
parent 450151c44b
commit d90a2bc381
21 changed files with 114 additions and 61 deletions

View File

@ -63,7 +63,7 @@
#include <prediction.hpp>
#include <itemtypes.hpp>
#include <chatstack.hpp>
#include "textfile.hpp"
#include "pathio.hpp"
#include "ipc.hpp"
#include "tfmm.hpp"
#include "hooks/HookedMethods.hpp"

View File

@ -10,6 +10,12 @@
#include <string>
#include <vector>
namespace paths
{
std::string getDataPath(std::string subpath = "");
std::string getConfigPath();
} // namespace paths
class TextFile
{
public:

View File

@ -5,6 +5,7 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/angles.cpp"
"${CMAKE_CURRENT_LIST_DIR}/crits.cpp"
"${CMAKE_CURRENT_LIST_DIR}/entitycache.cpp"
"${CMAKE_CURRENT_LIST_DIR}/entityhitboxcache.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pathio.cpp"
"${CMAKE_CURRENT_LIST_DIR}/globals.cpp"
"${CMAKE_CURRENT_LIST_DIR}/hack.cpp"
"${CMAKE_CURRENT_LIST_DIR}/headshake.cpp"
@ -22,7 +23,6 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/angles.cpp"
"${CMAKE_CURRENT_LIST_DIR}/sconvars.cpp"
"${CMAKE_CURRENT_LIST_DIR}/soundcache.cpp"
"${CMAKE_CURRENT_LIST_DIR}/targethelper.cpp"
"${CMAKE_CURRENT_LIST_DIR}/textfile.cpp"
"${CMAKE_CURRENT_LIST_DIR}/textmode.cpp"
"${CMAKE_CURRENT_LIST_DIR}/tfmm.cpp"
"${CMAKE_CURRENT_LIST_DIR}/trace.cpp"

View File

@ -46,7 +46,9 @@ public:
{
uname = std::string(pw->pw_name);
}
stream.open(DATA_PATH "/chat-" + uname + ".csv", std::ios::out | std::ios::app);
else
uname = "unknown";
stream.open(paths::getDataPath("/chat-" + uname + ".csv"), std::ios::out | std::ios::app);
return stream.good();
}

View File

@ -306,7 +306,7 @@ free(logname);*/
std::vector<std::string> essential = { "fonts/tf2build.ttf" };
for (const auto &s : essential)
{
std::ifstream exists(DATA_PATH "/" + s, std::ios::in);
std::ifstream exists(paths::getDataPath("/" + s), std::ios::in);
if (not exists)
{
Error(("Missing essential file: " + s +

View File

@ -44,7 +44,7 @@ void playsound(const std::string &sound)
{
// yes
char command[128];
snprintf(command, 128, "aplay %s/sound/%s &", DATA_PATH, sound.c_str());
snprintf(command, 128, "aplay %s/sound/%s &", paths::getDataPath().c_str(), sound.c_str());
logging::Info("system(%s)", command);
system(command);
// g_ISurface->PlaySound(std::string("announcer/" + sound).c_str());

View File

@ -84,7 +84,7 @@ bool hasEnding(std::string const &fullString, std::string const &ending)
std::vector<std::string> config_list(std::string in)
{
std::string complete_in = format(DATA_PATH, "/configs/", in);
std::string complete_in = paths::getConfigPath() + "/" + in;
if (!hasEnding(complete_in, ".conf"))
complete_in = complete_in + ".conf";
std::vector<std::string> config_vec;
@ -120,7 +120,7 @@ std::vector<std::string> config_list(std::string in)
for (i = 0; i < results.gl_pathc; i++)
// /configs/ is 9 extra chars i have to remove
config_vec.push_back(std::string(results.gl_pathv[i]).substr(std::string(DATA_PATH).length() + 9));
config_vec.push_back(std::string(results.gl_pathv[i]).substr(paths::getDataPath().length() + 9));
globfree(&results);
return config_vec;

View File

@ -32,7 +32,7 @@ struct ChatCommand
}
bool readFile(std::string filename)
{
auto stream = std::ifstream(DATA_PATH "/chatcommands/" + filename);
auto stream = std::ifstream(paths::getDataPath("/chatcommands/" + filename));
if (!stream)
return false;
for (std::string line; getline(stream, line);)
@ -117,10 +117,10 @@ static CatCommand chatcommands_add("chatcommands_add", "chatcommands_add <chat c
chatcomamnd.addcommand(command);
});
static CatCommand chatcommands_file("chatcommands_file", "chatcommands_add <chat command> <filename in " DATA_PATH "/chatcommands>", [](const CCommand &args) {
static CatCommand chatcommands_file("chatcommands_file", "chatcommands_add <chat command> <filename in " + paths::getDataPath() + "/chatcommands>", [](const CCommand &args) {
if (args.ArgC() != 3)
{
g_ICvar->ConsoleColorPrintf(MENU_COLOR, "usage: chatcommands_add <chat command> <filename in " DATA_PATH "/chatcommands>\n");
g_ICvar->ConsoleColorPrintf(MENU_COLOR, ("usage: chatcommands_add <chat command> <filename in " + paths::getDataPath() + "/chatcommands>\n").c_str());
return;
}
std::string prefix = args.Arg(1);

View File

@ -293,8 +293,8 @@ static void cm()
}
}
static draw::Texture atlas{ DATA_PATH "/textures/atlas.png" };
static draw::Texture idspec{ DATA_PATH "/textures/idspec.png" };
static draw::Texture atlas{ paths::getDataPath("/textures/atlas.png") };
static draw::Texture idspec{ paths::getDataPath("/textures/idspec.png") };
Timer retry{};
void Init()

View File

@ -438,7 +438,7 @@ void generate_schema()
{
std::ifstream in("tf/scripts/items/items_game.txt");
std::string outS((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
std::ofstream out(DATA_PATH "/items_game.txt");
std::ofstream out(paths::getDataPath("/items_game.txt"));
std::regex a("\"equip_regions?\".*?\".*?\"");
std::regex b("\"equip_regions?\"\\s*?\\n\\s*?\\{[\\s\\S\\n]*?\\}");
outS = std::regex_replace(outS, a, "");
@ -455,7 +455,7 @@ void Schema_Reload()
static auto BInitTextBuffer = reinterpret_cast<bool (*)(void *, CUtlBuffer &, int)>(gSignatures.GetClientSignature("55 89 E5 57 56 53 8D 9D ? ? ? ? 81 EC ? ? ? ? 8B 7D ? 89 1C 24 "));
void *schema = (void *) ((unsigned) GetItemSchema() + 0x4);
FILE *file = fopen(DATA_PATH "/items_game.txt", "r");
FILE *file = fopen(paths::getDataPath("/items_game.txt").c_str(), "r");
if (!file || ferror(file) != 0)
{
logging::Info("Error loading file");

View File

@ -318,17 +318,17 @@ void DrawText()
void Save(std::string filename)
{
DIR *cathook_directory = opendir(DATA_PATH "/skinchanger");
DIR *cathook_directory = opendir(paths::getDataPath("/skinchanger").c_str());
if (!cathook_directory)
{
logging::Info("Skinchanger directory doesn't exist, creating one!");
mkdir(DATA_PATH "/skinchanger", S_IRWXU | S_IRWXG);
mkdir(paths::getDataPath("/skinchanger").c_str(), S_IRWXU | S_IRWXG);
}
else
closedir(cathook_directory);
try
{
std::ofstream file(DATA_PATH "/skinchanger/" + filename, std::ios::out | std::ios::binary);
std::ofstream file(paths::getDataPath("/skinchanger/" + filename), std::ios::out | std::ios::binary);
BINARY_FILE_WRITE(file, SERIALIZE_VERSION);
size_t size = modifier_map.size();
BINARY_FILE_WRITE(file, size);
@ -358,17 +358,17 @@ void Save(std::string filename)
void Load(std::string filename, bool merge)
{
DIR *cathook_directory = opendir(DATA_PATH "/skinchanger");
DIR *cathook_directory = opendir(paths::getDataPath("/skinchanger").c_str());
if (!cathook_directory)
{
logging::Info("Skinchanger directory doesn't exist, creating one!");
mkdir(DATA_PATH "/skinchanger", S_IRWXU | S_IRWXG);
mkdir(paths::getDataPath("/skinchanger").c_str(), S_IRWXU | S_IRWXG);
}
else
closedir(cathook_directory);
try
{
std::ifstream file(DATA_PATH "/skinchanger/" + filename, std::ios::in | std::ios::binary);
std::ifstream file(paths::getDataPath("/skinchanger/" + filename), std::ios::in | std::ios::binary);
unsigned file_serialize = 0;
BINARY_FILE_READ(file, file_serialize);
if (file_serialize != SERIALIZE_VERSION)

View File

@ -287,16 +287,16 @@ void Save(std::string filename)
return;
}
{
DIR *walkbot_dir = opendir(DATA_PATH "/walkbot");
DIR *walkbot_dir = opendir(paths::getDataPath("/walkbot").c_str());
if (!walkbot_dir)
{
logging::Info("Walkbot directory doesn't exist, creating one!");
mkdir(DATA_PATH "/walkbot", S_IRWXU | S_IRWXG);
mkdir(paths::getDataPath("/walkbot").c_str(), S_IRWXU | S_IRWXG);
}
else
closedir(walkbot_dir);
}
std::string path = format(DATA_PATH "/walkbot/", GetLevelName());
std::string path = paths::getDataPath("/walkbot/" + GetLevelName());
{
DIR *level_dir = opendir(path.c_str());
if (!level_dir)
@ -340,7 +340,7 @@ void Save(std::string filename)
bool Load(std::string filename)
{
{
DIR *walkbot_dir = opendir(DATA_PATH "/walkbot");
DIR *walkbot_dir = opendir(paths::getDataPath("/walkbot").c_str());
if (!walkbot_dir)
{
logging::Info("Walkbot directory doesn't exist!");
@ -349,7 +349,7 @@ bool Load(std::string filename)
else
closedir(walkbot_dir);
}
std::string path = format(DATA_PATH "/walkbot/", GetLevelName());
std::string path = paths::getDataPath("/walkbot/" + GetLevelName());
{
DIR *level_dir = opendir(path.c_str());
if (!level_dir)

View File

@ -8,7 +8,48 @@
#include "common.hpp"
#include <stdio.h>
#include <filesystem>
// Cached data path
std::optional<std::string> cached_data_path;
namespace paths
{
// Example: getDataPath("/foo") -> "/opt/bar/data/foo"
std::string getDataPath(std::string subpath)
{
if (!cached_data_path)
{
if (std::getenv("CH_DATA_PATH"))
{
cached_data_path = std::getenv("CH_DATA_PATH");
}
else if (std::filesystem::exists(DATA_PATH))
{
cached_data_path = DATA_PATH;
}
else
{
std::string xdg_data_dir;
if (std::getenv("XDG_DATA_HOME"))
xdg_data_dir = std::getenv("XDG_DATA_HOME");
else if (std::getenv("HOME"))
xdg_data_dir = std::string(std::getenv("HOME")) + "/.local/share";
else
xdg_data_dir = DATA_PATH;
cached_data_path = xdg_data_dir + "/cathook/data";
logging::Info("Data path: %s", cached_data_path->c_str());
}
}
return *cached_data_path + subpath;
}
std::string getConfigPath()
{
return getDataPath("/configs");
}
} // namespace paths
// Textfile class functions
TextFile::TextFile() : lines{}
{
}
@ -63,3 +104,4 @@ const std::string &TextFile::Line(size_t id) const
{
return lines.at(id);
}
// Textfile class functions end

View File

@ -35,7 +35,7 @@ bool ShouldSave(const userdata &data)
void Save()
{
DIR *cathook_directory = opendir(DATA_PATH);
DIR *cathook_directory = opendir(paths::getDataPath().c_str());
if (!cathook_directory)
{
logging::Info("[ERROR] cathook data directory doesn't exist! How did "
@ -46,7 +46,7 @@ void Save()
closedir(cathook_directory);
try
{
std::ofstream file(DATA_PATH "/plist", std::ios::out | std::ios::binary);
std::ofstream file(paths::getDataPath("/plist"), std::ios::out | std::ios::binary);
file.write(reinterpret_cast<const char *>(&SERIALIZE_VERSION), sizeof(SERIALIZE_VERSION));
int size = 0;
for (const auto &item : data)
@ -74,7 +74,7 @@ void Save()
void Load()
{
data.clear();
DIR *cathook_directory = opendir(DATA_PATH);
DIR *cathook_directory = opendir(paths::getDataPath().c_str());
if (!cathook_directory)
{
logging::Info("[ERROR] cathook data directory doesn't exist! How did "
@ -85,7 +85,7 @@ void Load()
closedir(cathook_directory);
try
{
std::ifstream file(DATA_PATH "/plist", std::ios::in | std::ios::binary);
std::ifstream file(paths::getDataPath("/plist"), std::ios::in | std::ios::binary);
int file_serialize = 0;
file.read(reinterpret_cast<char *>(&file_serialize), sizeof(file_serialize));
if (file_serialize != SERIALIZE_VERSION)

View File

@ -34,25 +34,25 @@ static std::string getAutoSaveConfigPath()
time_info = localtime(&current_time);
strftime(timeString, sizeof(timeString), "%Y-%m-%d %H:%M", time_info);
DIR *config_directory = opendir(DATA_PATH "/configs");
DIR *config_directory = opendir(paths::getConfigPath().c_str());
if (!config_directory)
{
logging::Info("Configs directory doesn't exist, creating one!");
mkdir(DATA_PATH "/configs", S_IRWXU | S_IRWXG);
mkdir(paths::getConfigPath().c_str(), S_IRWXU | S_IRWXG);
}
else
closedir(config_directory);
config_directory = opendir(DATA_PATH "/configs/autosaves");
config_directory = opendir((paths::getConfigPath() + "/autosaves").c_str());
if (!config_directory)
{
logging::Info("Autosave directory doesn't exist, creating one!");
mkdir(DATA_PATH "/configs/autosaves", S_IRWXU | S_IRWXG);
mkdir((paths::getConfigPath() + "/autosaves").c_str(), S_IRWXU | S_IRWXG);
}
else
closedir(config_directory);
return path = std::string(DATA_PATH "/configs/autosaves/") + timeString + ".conf";
return path = paths::getConfigPath() + "/autosaves/" + timeString + ".conf";
}
static CatCommand cat("cat", "", [](const CCommand &args) {
@ -126,20 +126,20 @@ static CatCommand toggle("toggle", "", [](const CCommand &args) {
static CatCommand save("save", "", [](const CCommand &args) {
settings::SettingsWriter writer{ settings::Manager::instance() };
DIR *config_directory = opendir(DATA_PATH "/configs");
DIR *config_directory = opendir(paths::getConfigPath().c_str());
if (!config_directory)
{
logging::Info("Configs directory doesn't exist, creating one!");
mkdir(DATA_PATH "/configs", S_IRWXU | S_IRWXG);
mkdir(paths::getConfigPath().c_str(), S_IRWXU | S_IRWXG);
}
if (args.ArgC() == 1)
{
writer.saveTo(DATA_PATH "/configs/default.conf");
writer.saveTo((paths::getConfigPath() + "/default.conf").c_str());
}
else
{
writer.saveTo(std::string(DATA_PATH "/configs/") + args.Arg(1) + ".conf");
writer.saveTo(paths::getConfigPath() + "/" + args.Arg(1) + ".conf");
}
logging::Info("cat_save: Sorting configs...");
getAndSortAllConfigs();
@ -151,11 +151,11 @@ static CatCommand load("load", "", [](const CCommand &args) {
settings::SettingsReader loader{ settings::Manager::instance() };
if (args.ArgC() == 1)
{
loader.loadFrom(DATA_PATH "/configs/default.conf");
loader.loadFrom((paths::getConfigPath() + "/default.conf").c_str());
}
else
{
loader.loadFrom(std::string(DATA_PATH "/configs/") + args.Arg(1) + ".conf");
loader.loadFrom(paths::getConfigPath() + "/" + args.Arg(1) + ".conf");
}
});
@ -190,7 +190,7 @@ std::vector<std::string> sortedConfigs{};
static void getAndSortAllConfigs()
{
DIR *config_directory = opendir(DATA_PATH "/configs");
DIR *config_directory = opendir(paths::getConfigPath().c_str());
if (!config_directory)
{
logging::Info("Config directoy does not exist.");

View File

@ -29,7 +29,7 @@ sprite texture_atlas::create_sprite(float x, float y, float sx, float sy)
texture_atlas &atlas()
{
static texture_atlas object{ DATA_PATH "/textures/atlas.png", 1024, 512 };
static texture_atlas object{ paths::getDataPath("/textures/atlas.png"), 1024, 512 };
return object;
}
} // namespace textures

View File

@ -172,7 +172,7 @@ static InitRoutine font_size([]() {
{
#if ENABLE_GLEZ_DRAWING
fonts::esp->unload();
fonts::esp.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", after));
fonts::esp.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), after));
#else
fonts::esp->changeSize(after);
#endif
@ -183,7 +183,7 @@ static InitRoutine font_size([]() {
{
#if ENABLE_GLEZ_DRAWING
fonts::center_screen->unload();
fonts::center_screen.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", after));
fonts::center_screen.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), after));
#else
fonts::center_screen->changeSize(after);
#endif
@ -203,17 +203,17 @@ void Initialize()
}
#if ENABLE_GLEZ_DRAWING
glez::preInit();
fonts::menu.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 10));
fonts::esp.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 10));
fonts::center_screen.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 12));
fonts::menu.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 10));
fonts::esp.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 10));
fonts::center_screen.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 12));
#elif ENABLE_ENGINE_DRAWING
fonts::menu.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 10, true));
fonts::esp.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 10, true));
fonts::center_screen.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 12, true));
fonts::menu.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 10, true));
fonts::esp.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 10, true));
fonts::center_screen.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 12, true));
#elif ENABLE_IMGUI_DRAWING
fonts::menu.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 13, true));
fonts::esp.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 13, true));
fonts::center_screen.reset(new fonts::font(DATA_PATH "/fonts/megasans.ttf", 14, true));
fonts::menu.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 13, true));
fonts::esp.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 13, true));
fonts::center_screen.reset(new fonts::font(paths::getDataPath("/fonts/megasans.ttf"), 14, true));
#endif
#if ENABLE_ENGINE_DRAWING
texture_white = g_ISurface->CreateNewTextureID();

View File

@ -6,6 +6,8 @@
#include "visual/imgui/imgui_freetype.h"
#include <GL/gl.h>
#include "pathio.hpp"
static Uint64 g_Time = 0;
static bool g_MousePressed[3] = { false, false, false };
static SDL_Cursor *g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
@ -282,7 +284,7 @@ bool ImGui_ImplSdl_Init()
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
io.Fonts->AddFontFromFileTTF(DATA_PATH "/fonts/tf2build.ttf", 13, NULL, io.Fonts->GetGlyphRangesDefault());
io.Fonts->AddFontFromFileTTF(paths::getDataPath("/fonts/tf2build.ttf").c_str(), 13, NULL, io.Fonts->GetGlyphRangesDefault());
ImGuiFreeType::BuildFontAtlas(io.Fonts, 0x0);
ImGui_Impl_CreateFontsTexture(io.Fonts);

View File

@ -119,7 +119,7 @@ static void initPlayerlist()
static void load()
{
zerokernel::Menu::instance->loadFromFile(DATA_PATH "/menu", "menu.xml");
zerokernel::Menu::instance->loadFromFile(paths::getDataPath("/menu"), "menu.xml");
zerokernel::Container *sv = dynamic_cast<zerokernel::Container *>(zerokernel::Menu::instance->wm->getElementById("special-variables"));
if (sv)

View File

@ -19,6 +19,7 @@
#include <menu/menu/Menu.hpp>
#include <config.h>
#include <core/logging.hpp>
#include "pathio.hpp"
static void recursiveXmlResolveIncludes(const std::string &directory, tinyxml2::XMLElement *element)
{
@ -78,11 +79,11 @@ namespace resource::font
{
// FIXME dynamic font change..
#if ENABLE_IMGUI_DRAWING
fonts::font base{ DATA_PATH "/menu/Verdana.ttf", 12 };
fonts::font bold{ DATA_PATH "/menu/VerdanaBold.ttf", 11 };
fonts::font base{ paths::getDataPath("/menu/Verdana.ttf"), 12 };
fonts::font bold{ paths::getDataPath("/menu/VerdanaBold.ttf"), 11 };
#else
fonts::font base{ DATA_PATH "/menu/Verdana.ttf", 10 };
fonts::font bold{ DATA_PATH "/menu/VerdanaBold.ttf", 9 };
fonts::font base{ paths::getDataPath("/menu/Verdana.ttf"), 10 };
fonts::font bold{ paths::getDataPath("/menu/VerdanaBold.ttf"), 9 };
#endif
} // namespace resource::font

View File

@ -2,7 +2,7 @@
#include <menu/wm/WindowCloseButton.hpp>
#include <menu/wm/WMWindow.hpp>
#include <config.h>
#include "pathio.hpp"
#include "drawing.hpp"
/*
@ -11,7 +11,7 @@
namespace zerokernel_windowclosebutton
{
static draw::Texture cross{ DATA_PATH "/menu/cross.png" };
static draw::Texture cross{ paths::getDataPath( "/menu/cross.png") };
static settings::RVariable<rgba_t> background_hover{ "zk.style.window-close-button.color.background-hover", "ff0000" };
static settings::RVariable<rgba_t> color_border{ "zk.style.window-close-button.color.border", "446498ff" };
} // namespace zerokernel_windowclosebutton