mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
124 lines
3.8 KiB
C++
124 lines
3.8 KiB
C++
#include "Cubed/gameplay/hitbox_manager.hpp"
|
|
|
|
#include "Cubed/tools/cubed_assert.hpp"
|
|
#include "Cubed/tools/log.hpp"
|
|
#include "Cubed/tools/resource_location.hpp"
|
|
|
|
#include <rapidjson/document.h>
|
|
#include <rapidjson/istreamwrapper.h>
|
|
namespace fs = std::filesystem;
|
|
using namespace rapidjson;
|
|
namespace Cubed {
|
|
HitboxManager::HitboxManager() { HitboxMap::accessor a; }
|
|
|
|
HitboxManager::~HitboxManager() {}
|
|
|
|
HitboxManager& HitboxManager::instance() {
|
|
static HitboxManager inst;
|
|
return inst;
|
|
}
|
|
|
|
HitboxManager::Handle HitboxManager::hitbox(const std::string& key) {
|
|
return instance().get_hitbox(key);
|
|
}
|
|
|
|
HitboxManager::Handle HitboxManager::hitbox(HitboxID id) {
|
|
return instance().get_hitbox(id);
|
|
}
|
|
HitboxID HitboxManager::get_hitbox_id(const std::string& name) {
|
|
IDMap::const_accessor cacc;
|
|
if (m_id_map.find(cacc, name)) {
|
|
return cacc->second;
|
|
}
|
|
return load(name).id;
|
|
}
|
|
const std::string& HitboxManager::get_hitbox_name(HitboxID id) {
|
|
NameMap::const_accessor cacc;
|
|
if (m_name_map.find(cacc, id)) {
|
|
return cacc->second;
|
|
}
|
|
ASSERT_MSG(false, std::format("ModelManager: Can't find {}", id));
|
|
static std::string n = "";
|
|
return n;
|
|
}
|
|
|
|
HitboxManager::Handle HitboxManager::get_hitbox(HitboxID id) {
|
|
{
|
|
HitboxMap::const_accessor c;
|
|
if (m_hitboxes.find(c, id)) {
|
|
return {c->second, c->first};
|
|
}
|
|
}
|
|
|
|
return load(get_hitbox_name(id));
|
|
}
|
|
HitboxManager::Handle HitboxManager::get_hitbox(const std::string& name) {
|
|
return get_hitbox(get_hitbox_id(name));
|
|
}
|
|
HitboxManager::Handle HitboxManager::load(std::string_view name) {
|
|
|
|
auto space = ResourceLocation::parse(name);
|
|
if (!space) {
|
|
Logger::error("Can't load hitbox {}", name);
|
|
ASSERT(false);
|
|
}
|
|
fs::path p;
|
|
if (space->ns == "cubed") {
|
|
p = std::format("{}model/creature/{}/collision.json", ASSETS_PATH,
|
|
space->path);
|
|
} else {
|
|
p = std::format("{}/model/creature/{}/collision.json", space->ns,
|
|
space->path);
|
|
}
|
|
|
|
try {
|
|
glm::vec3 center;
|
|
glm::vec3 half;
|
|
std::ifstream s{p};
|
|
IStreamWrapper isw(s);
|
|
Document doc;
|
|
doc.ParseStream(isw);
|
|
if (doc.HasParseError()) {
|
|
auto code = doc.GetParseError();
|
|
|
|
throw std::runtime_error(
|
|
std::format("Parse {} failed, error code {}", p.string(),
|
|
static_cast<int>(code)));
|
|
}
|
|
if (doc.HasMember("boxes")) {
|
|
const Value& box = doc["boxes"];
|
|
if (box.IsArray()) {
|
|
const Value& b = box[0];
|
|
if (b.HasMember("center")) {
|
|
center.x = b["center"][0].GetFloat();
|
|
center.y = b["center"][1].GetFloat();
|
|
center.z = b["center"][2].GetFloat();
|
|
}
|
|
if (b.HasMember("half")) {
|
|
half.x = b["half"][0].GetFloat();
|
|
half.y = b["half"][1].GetFloat();
|
|
half.z = b["half"][2].GetFloat();
|
|
}
|
|
}
|
|
}
|
|
{
|
|
HitboxMap::accessor a;
|
|
if (m_hitboxes.insert(a, std::pair<HitboxID, Hitbox>{
|
|
m_next++, Hitbox{center, half}})) {
|
|
m_name_map.emplace(a->first, name);
|
|
m_id_map.emplace(name, a->first);
|
|
return {a->second, a->first};
|
|
}
|
|
}
|
|
HitboxMap::const_accessor cacc;
|
|
if (m_hitboxes.find(cacc, get_hitbox_id(std::string(name)))) {
|
|
return {cacc->second, cacc->first};
|
|
}
|
|
} catch (const std::exception& e) {
|
|
Logger::error("Load Hitbox error {}", e.what());
|
|
}
|
|
Logger::error("Load hitbox {} Failed", name);
|
|
return {Hitbox{glm::vec3(0.0f), glm::vec3(0.0f)}, 0};
|
|
}
|
|
|
|
} // namespace Cubed
|