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/concurrency.hpp>
|
||||
|
||||
#include "game/utils.hpp"
|
||||
|
||||
#include "steam/interface.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
@ -252,7 +254,7 @@ namespace steam_proxy
|
||||
return client_friends.invoke<const char*>("GetPersonaName");
|
||||
}
|
||||
|
||||
return "boiii";
|
||||
return "";
|
||||
}
|
||||
|
||||
void update_subscribed_items()
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
namespace steam_proxy
|
||||
{
|
||||
const utils::nt::library& get_overlay_module();
|
||||
|
@ -3,6 +3,8 @@
|
||||
enum class component_priority
|
||||
{
|
||||
min = 0,
|
||||
// must run after the steam_proxy
|
||||
name,
|
||||
// must run after the updater
|
||||
steam_proxy,
|
||||
updater,
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
#include "component/steam_proxy.hpp"
|
||||
#include "component/name.hpp"
|
||||
|
||||
namespace steam
|
||||
{
|
||||
const char* friends::GetPersonaName()
|
||||
{
|
||||
return steam_proxy::get_player_name();
|
||||
return name::get_player_name();
|
||||
}
|
||||
|
||||
unsigned long long friends::SetPersonaName(const char* pchPersonaName)
|
||||
|
@ -380,13 +380,13 @@ namespace updater
|
||||
legal_files.reserve(files.size());
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const auto is_file = std::filesystem::is_regular_file(file);
|
||||
|
@ -39,6 +39,12 @@ namespace utils::concurrency
|
||||
T& get_raw() { return object_; }
|
||||
const T& get_raw() const { return object_; }
|
||||
|
||||
T copy() const
|
||||
{
|
||||
std::unique_lock<MutexType> lock{mutex_};
|
||||
return object_;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable MutexType mutex_{};
|
||||
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