parent
73f9859eed
commit
81d4cc47b4
103
src/client/component/name.cpp
Normal file
103
src/client/component/name.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "name.hpp"
|
||||||
|
#include "steam_proxy.hpp"
|
||||||
|
#include "command.hpp"
|
||||||
|
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/properties.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
namespace name
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::concurrency::container<std::string> player_name{};
|
||||||
|
|
||||||
|
void store_player_name(const std::string& name)
|
||||||
|
{
|
||||||
|
utils::properties::store("playerName", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate_player_name(std::string new_name)
|
||||||
|
{
|
||||||
|
player_name.access([&](std::string& name)
|
||||||
|
{
|
||||||
|
name = std::move(new_name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_player_name(const std::string& new_name)
|
||||||
|
{
|
||||||
|
store_player_name(new_name);
|
||||||
|
activate_player_name(new_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_player_name()
|
||||||
|
{
|
||||||
|
std::string initial_name = steam_proxy::get_player_name();
|
||||||
|
|
||||||
|
if (initial_name.empty())
|
||||||
|
{
|
||||||
|
initial_name = utils::nt::get_user_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initial_name.empty())
|
||||||
|
{
|
||||||
|
initial_name = "Unknown Soldier";
|
||||||
|
}
|
||||||
|
|
||||||
|
update_player_name(initial_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_player_name()
|
||||||
|
{
|
||||||
|
const auto stored_name = utils::properties::load("playerName");
|
||||||
|
|
||||||
|
if (stored_name)
|
||||||
|
{
|
||||||
|
activate_player_name(*stored_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setup_player_name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct component final : client_component
|
||||||
|
{
|
||||||
|
void post_load() override
|
||||||
|
{
|
||||||
|
load_player_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
command::add("name", [](const command::params& params)
|
||||||
|
{
|
||||||
|
if (params.size() != 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_player_name(params[1]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
component_priority priority() const override
|
||||||
|
{
|
||||||
|
return component_priority::name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* get_player_name()
|
||||||
|
{
|
||||||
|
const auto name = player_name.copy();
|
||||||
|
return utils::string::va("%.*s", static_cast<int>(name.size()), name.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(name::component)
|
6
src/client/component/name.hpp
Normal file
6
src/client/component/name.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace name
|
||||||
|
{
|
||||||
|
const char* get_player_name();
|
||||||
|
}
|
@ -7,6 +7,8 @@
|
|||||||
#include <utils/finally.hpp>
|
#include <utils/finally.hpp>
|
||||||
#include <utils/concurrency.hpp>
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
#include "game/utils.hpp"
|
||||||
|
|
||||||
#include "steam/interface.hpp"
|
#include "steam/interface.hpp"
|
||||||
#include "steam/steam.hpp"
|
#include "steam/steam.hpp"
|
||||||
|
|
||||||
@ -252,7 +254,7 @@ namespace steam_proxy
|
|||||||
return client_friends.invoke<const char*>("GetPersonaName");
|
return client_friends.invoke<const char*>("GetPersonaName");
|
||||||
}
|
}
|
||||||
|
|
||||||
return "boiii";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_subscribed_items()
|
void update_subscribed_items()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
namespace steam_proxy
|
namespace steam_proxy
|
||||||
{
|
{
|
||||||
const utils::nt::library& get_overlay_module();
|
const utils::nt::library& get_overlay_module();
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
enum class component_priority
|
enum class component_priority
|
||||||
{
|
{
|
||||||
min = 0,
|
min = 0,
|
||||||
|
// must run after the steam_proxy
|
||||||
|
name,
|
||||||
// must run after the updater
|
// must run after the updater
|
||||||
steam_proxy,
|
steam_proxy,
|
||||||
updater,
|
updater,
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
#include <utils/nt.hpp>
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
#include "component/steam_proxy.hpp"
|
#include "component/name.hpp"
|
||||||
|
|
||||||
namespace steam
|
namespace steam
|
||||||
{
|
{
|
||||||
const char* friends::GetPersonaName()
|
const char* friends::GetPersonaName()
|
||||||
{
|
{
|
||||||
return steam_proxy::get_player_name();
|
return name::get_player_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long friends::SetPersonaName(const char* pchPersonaName)
|
unsigned long long friends::SetPersonaName(const char* pchPersonaName)
|
||||||
|
@ -380,13 +380,13 @@ namespace updater
|
|||||||
legal_files.reserve(files.size());
|
legal_files.reserve(files.size());
|
||||||
for (const auto& file : files)
|
for (const auto& file : files)
|
||||||
{
|
{
|
||||||
if (file.name != UPDATE_HOST_BINARY)
|
if (file.name.starts_with("data"))
|
||||||
{
|
{
|
||||||
legal_files.emplace_back(std::filesystem::absolute(base / file.name));
|
legal_files.emplace_back(std::filesystem::absolute(base / file.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto existing_files = utils::io::list_files(base.string(), true);
|
const auto existing_files = utils::io::list_files(base / "data", true);
|
||||||
for (auto& file : existing_files)
|
for (auto& file : existing_files)
|
||||||
{
|
{
|
||||||
const auto is_file = std::filesystem::is_regular_file(file);
|
const auto is_file = std::filesystem::is_regular_file(file);
|
||||||
|
@ -39,6 +39,12 @@ namespace utils::concurrency
|
|||||||
T& get_raw() { return object_; }
|
T& get_raw() { return object_; }
|
||||||
const T& get_raw() const { return object_; }
|
const T& get_raw() const { return object_; }
|
||||||
|
|
||||||
|
T copy() const
|
||||||
|
{
|
||||||
|
std::unique_lock<MutexType> lock{mutex_};
|
||||||
|
return object_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable MutexType mutex_{};
|
mutable MutexType mutex_{};
|
||||||
T object_{};
|
T object_{};
|
||||||
|
44
src/common/utils/named_mutex.cpp
Normal file
44
src/common/utils/named_mutex.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "named_mutex.hpp"
|
||||||
|
#include "nt.hpp"
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
named_mutex::named_mutex(const std::string& name)
|
||||||
|
{
|
||||||
|
this->handle_ = CreateMutexA(nullptr, FALSE, name.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
named_mutex::~named_mutex()
|
||||||
|
{
|
||||||
|
if (this->handle_)
|
||||||
|
{
|
||||||
|
CloseHandle(this->handle_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void named_mutex::lock() const
|
||||||
|
{
|
||||||
|
if (this->handle_)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(this->handle_, INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool named_mutex::try_lock(const std::chrono::milliseconds timeout) const
|
||||||
|
{
|
||||||
|
if (this->handle_)
|
||||||
|
{
|
||||||
|
return WAIT_OBJECT_0 == WaitForSingleObject(this->handle_, static_cast<DWORD>(timeout.count()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void named_mutex::unlock() const noexcept
|
||||||
|
{
|
||||||
|
if (this->handle_)
|
||||||
|
{
|
||||||
|
ReleaseMutex(this->handle_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/common/utils/named_mutex.hpp
Normal file
26
src/common/utils/named_mutex.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
class named_mutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
named_mutex(const std::string& name);
|
||||||
|
~named_mutex();
|
||||||
|
|
||||||
|
named_mutex(named_mutex&&) = delete;
|
||||||
|
named_mutex(const named_mutex&) = delete;
|
||||||
|
named_mutex& operator=(named_mutex&&) = delete;
|
||||||
|
named_mutex& operator=(const named_mutex&) = delete;
|
||||||
|
|
||||||
|
void lock() const;
|
||||||
|
bool try_lock(std::chrono::milliseconds timeout = std::chrono::milliseconds{0}) const;
|
||||||
|
void unlock() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* handle_{};
|
||||||
|
};
|
||||||
|
}
|
172
src/common/utils/properties.cpp
Normal file
172
src/common/utils/properties.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#include "properties.hpp"
|
||||||
|
|
||||||
|
#include "finally.hpp"
|
||||||
|
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <rapidjson/prettywriter.h>
|
||||||
|
#include "rapidjson/filereadstream.h"
|
||||||
|
#include "rapidjson/filewritestream.h"
|
||||||
|
#include "rapidjson/encodedstream.h"
|
||||||
|
|
||||||
|
#include "io.hpp"
|
||||||
|
#include "com.hpp"
|
||||||
|
#include "string.hpp"
|
||||||
|
|
||||||
|
namespace utils::properties
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
typedef rapidjson::GenericDocument<rapidjson::UTF16LE<>> WDocument;
|
||||||
|
typedef rapidjson::GenericValue<rapidjson::UTF16LE<>> WValue;
|
||||||
|
|
||||||
|
typedef rapidjson::EncodedOutputStream<rapidjson::UTF16LE<>, rapidjson::FileWriteStream> OutputStream;
|
||||||
|
typedef rapidjson::EncodedInputStream<rapidjson::UTF16LE<>, rapidjson::FileReadStream> InputStream;
|
||||||
|
|
||||||
|
std::filesystem::path get_properties_folder()
|
||||||
|
{
|
||||||
|
static auto props = get_appdata_path() / "user";
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path get_properties_file()
|
||||||
|
{
|
||||||
|
static auto props = get_properties_folder() / "properties.json";
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
WDocument load_properties()
|
||||||
|
{
|
||||||
|
WDocument default_doc{};
|
||||||
|
default_doc.SetObject();
|
||||||
|
|
||||||
|
char read_buffer[256]; // Raw buffer for reading
|
||||||
|
|
||||||
|
const std::wstring& props = get_properties_file();
|
||||||
|
|
||||||
|
FILE* fp;
|
||||||
|
auto err = _wfopen_s(&fp, props.data(), L"rb");
|
||||||
|
if (err || !fp)
|
||||||
|
{
|
||||||
|
return default_doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will handle the BOM
|
||||||
|
rapidjson::FileReadStream bis(fp, read_buffer, sizeof(read_buffer));
|
||||||
|
InputStream eis(bis);
|
||||||
|
|
||||||
|
WDocument doc{};
|
||||||
|
const rapidjson::ParseResult result = doc.ParseStream<rapidjson::kParseNoFlags, rapidjson::UTF16LE<>>(eis);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (!result || !doc.IsObject())
|
||||||
|
{
|
||||||
|
return default_doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_properties(const WDocument& doc)
|
||||||
|
{
|
||||||
|
char write_buffer[256]; // Raw buffer for writing
|
||||||
|
|
||||||
|
const std::wstring& props = get_properties_file();
|
||||||
|
io::create_directory(get_properties_folder());
|
||||||
|
|
||||||
|
FILE* fp;
|
||||||
|
auto err = _wfopen_s(&fp, props.data(), L"wb");
|
||||||
|
if (err || !fp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::FileWriteStream bos(fp, write_buffer, sizeof(write_buffer));
|
||||||
|
OutputStream eos(bos, true); // Write BOM
|
||||||
|
|
||||||
|
rapidjson::Writer<OutputStream, rapidjson::UTF16LE<>, rapidjson::UTF16LE<>> writer(eos);
|
||||||
|
doc.Accept(writer);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path get_appdata_path()
|
||||||
|
{
|
||||||
|
PWSTR path;
|
||||||
|
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &path)))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to read APPDATA path!");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto _ = utils::finally([&path]
|
||||||
|
{
|
||||||
|
CoTaskMemFree(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
static auto appdata = std::filesystem::path(path) / "boiii";
|
||||||
|
return appdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<named_mutex> lock()
|
||||||
|
{
|
||||||
|
static named_mutex mutex{"boiii-properties-lock"};
|
||||||
|
return std::unique_lock{mutex};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::wstring> load(const std::wstring& name)
|
||||||
|
{
|
||||||
|
const auto _ = lock();
|
||||||
|
const auto doc = load_properties();
|
||||||
|
|
||||||
|
if (!doc.HasMember(name))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& value = doc[name];
|
||||||
|
if (!value.IsString())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {std::wstring{value.GetString()}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> load(const std::string& name)
|
||||||
|
{
|
||||||
|
const auto result = load(string::convert(name));
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {string::convert(*result)};
|
||||||
|
}
|
||||||
|
|
||||||
|
void store(const std::wstring& name, const std::wstring& value)
|
||||||
|
{
|
||||||
|
const auto _ = lock();
|
||||||
|
auto doc = load_properties();
|
||||||
|
|
||||||
|
while (doc.HasMember(name))
|
||||||
|
{
|
||||||
|
doc.RemoveMember(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
WValue key{};
|
||||||
|
key.SetString(name, doc.GetAllocator());
|
||||||
|
|
||||||
|
WValue member{};
|
||||||
|
member.SetString(value, doc.GetAllocator());
|
||||||
|
|
||||||
|
doc.AddMember(key, member, doc.GetAllocator());
|
||||||
|
|
||||||
|
store_properties(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void store(const std::string& name, const std::string& value)
|
||||||
|
{
|
||||||
|
store(string::convert(name), string::convert(value));
|
||||||
|
}
|
||||||
|
}
|
19
src/common/utils/properties.hpp
Normal file
19
src/common/utils/properties.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "named_mutex.hpp"
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace utils::properties
|
||||||
|
{
|
||||||
|
std::filesystem::path get_appdata_path();
|
||||||
|
|
||||||
|
std::unique_lock<named_mutex> lock();
|
||||||
|
|
||||||
|
std::optional<std::wstring> load(const std::wstring& name);
|
||||||
|
std::optional<std::string> load(const std::string& name);
|
||||||
|
|
||||||
|
void store(const std::wstring& name, const std::wstring& value);
|
||||||
|
void store(const std::string& name, const std::string& value);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user