Sign in Sign up
kretrod/lodestone-cpp Public
Branches
main
51 lines (43 loc) · 1.7 KB Raw
// Where the client reads and writes, and how it says what it is doing.
//
// Everything lives beside the DLL rather than the game, so the pair can be
// dropped anywhere and still find each other. The log is reopened per line: it
// is low volume, and it means an external `Move-Item` on the file (which the
// deploy script does to rotate it) is picked up immediately instead of writing
// into a handle pointing at the old inode.
#pragma once

#include <windows.h>

#include <cstdio>
#include <string>

namespace lodestone {

/// Set once in DllMain; the module we were loaded as.
inline HMODULE g_module = nullptr;

/// The folder this DLL was loaded from.
inline std::string client_dir() {
    wchar_t wide[MAX_PATH * 2] = {};
    DWORD n = GetModuleFileNameW(g_module, wide, static_cast<DWORD>(std::size(wide)));
    if (n == 0) return ".";
    // Trim back to the last separator.
    while (n > 0 && wide[n - 1] != L'\\' && wide[n - 1] != L'/') --n;
    int bytes = WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(n), nullptr, 0, nullptr, nullptr);
    std::string out(static_cast<size_t>(bytes), '\0');
    WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(n), out.data(), bytes, nullptr, nullptr);
    if (out.empty()) return ".";
    return out;
}

inline void log(const std::string& message) {
    std::string path = client_dir() + "lodestone.log";
    if (FILE* f = std::fopen(path.c_str(), "a")) {
        std::fputs(message.c_str(), f);
        std::fputc('\n', f);
        std::fclose(f);
    }
}

/// printf-style, because most log lines want a value in them.
template <typename... Args>
inline void logf(const char* fmt, Args... args) {
    char buf[1024];
    std::snprintf(buf, sizeof(buf), fmt, args...);
    log(buf);
}

}  // namespace lodestone