Skip to content

Commit

Permalink
feat: add save and load functionality to player ban list
Browse files Browse the repository at this point in the history
  • Loading branch information
wu-vincent committed Nov 27, 2024
1 parent edaf586 commit 6515913
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 8 deletions.
3 changes: 3 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class EndstoneRecipe(ConanFile):
"capstone/*:tms320c64x": False,
"capstone/*:m680x": False,
"capstone/*:evm": False,
"date/*:header_only": True,
}

exports_sources = "CMakeLists.txt", "src/*", "include/*", "tests/*"
Expand Down Expand Up @@ -112,6 +113,7 @@ def requirements(self):
self.requires("boost/1.85.0")
self.requires("concurrentqueue/1.0.4")
self.requires("cpptrace/0.7.1")
self.requires("date/3.0.3")
self.requires("entt/3.14.0")
self.requires("expected-lite/0.8.0")
self.requires("fmt/[~10]", transitive_headers=True, transitive_libs=True)
Expand Down Expand Up @@ -177,6 +179,7 @@ def package_info(self):
"boost::boost",
"concurrentqueue::concurrentqueue",
"cpptrace::cpptrace",
"date::date",
"entt::entt",
"glm::glm",
"magic_enum::magic_enum",
Expand Down
2 changes: 1 addition & 1 deletion include/endstone/ban/ban_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class BanEntry {
*
* @return the source of the ban
*/
[[nodiscard]] std::string getSource()
[[nodiscard]] std::string getSource() const
{
return source_;
}
Expand Down
5 changes: 3 additions & 2 deletions include/endstone/detail/ban/player_ban_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ class EndstonePlayerBanList : public PlayerBanList {
void removeBan(std::string name) override;
void removeBan(std::string name, std::optional<UUID> uuid, std::optional<std::string> xuid) override;

void save();
void load();

private:
static bool match(const PlayerBanEntry &entry, const std::string &name, const std::optional<UUID> &uuid,
const std::optional<std::string> &xuid);

void save();
void load();
void removeExpired();

std::vector<PlayerBanEntry> entries_;
Expand Down
19 changes: 16 additions & 3 deletions src/endstone_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ find_package(base64 REQUIRED)
find_package(Boost REQUIRED)
find_package(concurrentqueue REQUIRED)
find_package(cpptrace REQUIRED)
find_package(date REQUIRED)
find_package(EnTT REQUIRED)
find_package(glm REQUIRED)
find_package(magic_enum REQUIRED)
Expand Down Expand Up @@ -80,9 +81,21 @@ add_library(endstone_core
server.cpp
)
add_library(endstone::core ALIAS endstone_core)
target_link_libraries(endstone_core PUBLIC endstone::headers aklomp::base64 boost::boost concurrentqueue::concurrentqueue
cpptrace::cpptrace EnTT::EnTT glm::glm magic_enum::magic_enum Microsoft.GSL::GSL nlohmann_json::nlohmann_json
pybind11::module spdlog::spdlog tomlplusplus::tomlplusplus)
target_link_libraries(endstone_core PUBLIC
endstone::headers
aklomp::base64
boost::boost
concurrentqueue::concurrentqueue
cpptrace::cpptrace
date::date
EnTT::EnTT
glm::glm
magic_enum::magic_enum
Microsoft.GSL::GSL
nlohmann_json::nlohmann_json
pybind11::module
spdlog::spdlog
tomlplusplus::tomlplusplus)
if (UNIX)
target_link_libraries(endstone_core PUBLIC ${CMAKE_DL_LIBS})
target_compile_definitions(endstone_core PUBLIC ENDSTONE_DISABLE_DEVTOOLS)
Expand Down
105 changes: 104 additions & 1 deletion src/endstone_core/ban/player_ban_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@

#include "endstone/detail/ban/player_ban_list.h"

#include <fstream>

#include <boost/uuid/string_generator.hpp>
#include <date/date.h>
#include <entt/entt.hpp>
#include <fmt/format.h>
#include <nlohmann/json.hpp>

#include "endstone/detail/server.h"

namespace endstone::detail {

const PlayerBanEntry *EndstonePlayerBanList::getBanEntry(std::string name) const
Expand Down Expand Up @@ -70,7 +80,7 @@ PlayerBanEntry &EndstonePlayerBanList::addBan(std::string name, std::optional<UU
if (source.has_value()) {
new_entry.setSource(source.value());
}
entries_.push_back(std::move(new_entry));
entries_.emplace_back(new_entry);
entry = &entries_.back();
}

Expand Down Expand Up @@ -154,6 +164,99 @@ bool EndstonePlayerBanList::match(const PlayerBanEntry &entry, const std::string
return name_match && uuid_match && xuid_match;
}

void EndstonePlayerBanList::save()
{
nlohmann::json array = nlohmann::json::array();
for (const auto &entry : entries_) {
nlohmann::json json;
json["name"] = entry.getName();
if (entry.getUniqueId().has_value()) {
json["uuid"] = entry.getUniqueId().value().str();
}
if (entry.getXuid().has_value()) {
json["xuid"] = entry.getXuid().value();
}
json["created"] = date::format("%F %T Z", entry.getCreated());
json["source"] = entry.getSource();
if (entry.getExpiration().has_value()) {
json["expires"] = date::format("%F %T Z", entry.getExpiration().value());
}
else {
json["expires"] = "forever";
}
json["reason"] = entry.getReason();
array.push_back(json);
}

auto &server = entt::locator<EndstoneServer>::value();
std::ofstream writer(file_, std::ofstream::out | std::ofstream::trunc);
try {
writer << array;
}
catch (const std::exception &e) {
server.getLogger().error("Unable to write file '{}': {}", file_, e.what());
}
}

void EndstonePlayerBanList::load()
{
if (!exists(file_)) {
return;
}

entries_.clear();

auto &server = entt::locator<EndstoneServer>::value();
std::ifstream file(file_, std::ifstream::in);
try {
auto array = nlohmann::json::parse(file);
std::string name = array["name"];
std::optional<UUID> uuid;
std::optional<std::string> xuid = std::nullopt;
if (array.contains("uuid")) {
try {
boost::uuids::string_generator gen;
boost::uuids::uuid u1 = gen(std::string(array["uuid"]));
UUID u2;
std::memcpy(u2.data, u1.data, u1.size());
uuid = u2;
}
catch (std::exception &) {
uuid = std::nullopt;
}
}
if (array.contains("xuid")) {
xuid = array["xuid"];
}
PlayerBanEntry entry{name, uuid, xuid};
if (array.contains("created")) {
std::string created = array["created"];
std::istringstream in{created};
BanEntry::Date date;
in >> date::parse("%FT%TZ", date);
if (!in.fail()) {
entry.setCreated(date);
}
}
if (array.contains("source")) {
entry.setSource(array["source"]);
}
if (array.contains("expires")) {
std::string expires = array["expires"];
std::istringstream in{expires};
BanEntry::Date date;
in >> date::parse("%FT%TZ", date);
if (!in.fail()) {
entry.setExpiration(date);
}
}
entries_.emplace_back(entry);
}
catch (const std::exception &e) {
server.getLogger().error("Unable to read file '{}': {}", file_, e.what());
}
}

void EndstonePlayerBanList::removeExpired()
{
auto it = entries_.begin();
Expand Down
1 change: 0 additions & 1 deletion src/endstone_core/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

#include "endstone/detail/player.h"

#include <boost/uuid/string_generator.hpp>
#include <magic_enum/magic_enum.hpp>

#include "bedrock/certificates/extended_certificate.h"
Expand Down

0 comments on commit 6515913

Please sign in to comment.