载入中...
搜索中...
未找到
BuildingDef.cpp
浏览该文件的文档.
2
3#include "common/Json.h"
4
5#include <algorithm>
6
7namespace eve::building {
8
10
11bool BuildingDefinition::hasTag(const std::string &tag) const {
12 return std::find(tags.begin(), tags.end(), tag) != tags.end();
13}
14
15std::string BuildingDefinition::getExtra(const std::string &key,
16 const std::string &fallback) const {
17 auto it = extra.find(key);
18 return it == extra.end() ? fallback : it->second;
19}
20
21std::string BuildingDefinition::getVisual2d(const std::string &key,
22 const std::string &fallback) const {
23 auto it = visual2d.find(key);
24 return it == visual2d.end() ? fallback : it->second;
25}
26
27std::string BuildingDefinition::getVisual3d(const std::string &key,
28 const std::string &fallback) const {
29 auto it = visual3d.find(key);
30 return it == visual3d.end() ? fallback : it->second;
31}
32
33int BuildingDefinition::getCost(const std::string &resource, int fallback) const {
34 auto it = cost.find(resource);
35 return it == cost.end() ? fallback : it->second;
36}
37
38bool BuildingDefinition::maskAt(int localX, int localY) const {
39 if (localX < 0 || localY < 0 || localX >= footprintW || localY >= footprintH) return false;
40 if (footprintMask.empty()) return true;
41 const size_t idx = size_t(localY) * size_t(footprintW) + size_t(localX);
42 if (idx >= footprintMask.size()) return false;
43 return footprintMask[idx] != 0;
44}
45
46bool PlacedBuilding::hasTag(const std::string &tag) const {
47 return std::find(tags.begin(), tags.end(), tag) != tags.end();
48}
49
50std::string PlacedBuilding::getProp(const std::string &key, const std::string &fallback) const {
51 auto it = props.find(key);
52 return it == props.end() ? fallback : it->second;
53}
54
55void PlacedBuilding::setProp(const std::string &key, const std::string &value) {
56 props[key] = value;
57}
58
59std::unordered_map<std::string, BuildingDefinition> &BuildingRegistry::table() {
60 static std::unordered_map<std::string, BuildingDefinition> t;
61 return t;
62}
63
65 if (def.id.empty()) return;
66 BuildingDefinition copy = def;
67 if (copy.footprintW <= 0) copy.footprintW = 1;
68 if (copy.footprintH <= 0) copy.footprintH = 1;
69 if (copy.displayName.empty()) copy.displayName = copy.id;
70 if (copy.snapMode.empty()) copy.snapMode = "grid";
71 if (copy.rotationMode.empty()) copy.rotationMode = "cardinal";
72 if (copy.validateRule.empty()) copy.validateRule = "default";
73 const size_t expected = size_t(copy.footprintW) * size_t(copy.footprintH);
74 if (!copy.footprintMask.empty() && copy.footprintMask.size() != expected) {
75 copy.footprintMask.clear(); // 长度不匹配时回退实心矩形
76 }
77 table()[copy.id] = std::move(copy);
78}
79
80const BuildingDefinition *BuildingRegistry::find(const std::string &id) {
81 auto &t = table();
82 auto it = t.find(id);
83 return it == t.end() ? nullptr : &it->second;
84}
85
86bool BuildingRegistry::remove(const std::string &id) { return table().erase(id) > 0; }
87
88void BuildingRegistry::clear() { table().clear(); }
89
90int BuildingRegistry::count() { return int(table().size()); }
91
92namespace {
93
94BuildingDefinition parseBuildingObject(Value o) {
96 if (!o.isObject()) return def;
97 def.id = o.getString("id");
98 def.displayName = o.getString("displayName", def.id);
99 def.category = o.getString("category");
100 def.channel = o.getString("channel");
101 def.renderMode = o.getString("renderMode");
102 def.footprintW = o.getInt("footprintW", 1);
103 def.footprintH = o.getInt("footprintH", 1);
104 def.snapMode = o.getString("snapMode", "grid");
105 def.rotationMode = o.getString("rotationMode", "cardinal");
106 def.validateRule = o.getString("validateRule", "default");
107 def.tags = o.getStringArray("tags");
108 def.requireTerrain = o.getIntArray("requireTerrain");
109 def.forbidTerrain = o.getIntArray("forbidTerrain");
110 def.requireAdjacentTag = o.getString("requireAdjacentTag");
111 def.requireAdjacentTerrain = o.getInt("requireAdjacentTerrain", -1);
112 def.cost = o.getIntMap("cost");
113 def.extra = o.getStringMap("extra");
114 def.visual2d = o.getStringMap("visual2d");
115 def.visual3d = o.getStringMap("visual3d");
116
117 const Value mask = o.get("footprintMask");
118 def.footprintMask.reserve(mask.size());
119 for (size_t i = 0; i < mask.size(); ++i)
120 def.footprintMask.push_back(uint8_t(mask.at(i).asInt(0) != 0 ? 1 : 0));
121 return def;
122}
123
124} // namespace
125
126int BuildingRegistry::loadFromJson(const std::string &json, std::string *error) {
127 std::string err;
128 const eve::json::Document doc = eve::json::Document::parse(json, &err);
129 if (!doc.valid()) {
130 if (error) *error = err.empty() ? "invalid json" : err;
131 return 0;
132 }
133
134 const Value root = doc.root();
135 int n = 0;
136 if (root.isArray()) {
137 for (size_t i = 0; i < root.size(); ++i) {
138 BuildingDefinition def = parseBuildingObject(root.at(i));
139 if (def.id.empty()) continue;
140 registerBuilding(def);
141 ++n;
142 }
143 } else if (root.isObject()) {
144 BuildingDefinition def = parseBuildingObject(root);
145 if (!def.id.empty()) {
146 registerBuilding(def);
147 ++n;
148 }
149 }
150 return n;
151}
152
153} // namespace eve::building
std::string value
glm::vec3 n
Definition Grass.cpp:64
std::string error
int idx
static void registerBuilding(const BuildingDefinition &def)
static int loadFromJson(const std::string &json, std::string *error=nullptr)
从 JSON 数组或单对象批量注册,返回成功数量。 元素形如: { "id": "house.wood", "displayName": "木屋", "category": "housing",...
static const BuildingDefinition * find(const std::string &id)
static bool remove(const std::string &id)
bool valid() const
Definition Json.h:111
static Document parse(const std::string &text, std::string *error=nullptr)
Definition Json.cpp:449
Value root() const
Definition Json.h:112
bool isObject() const
Definition Json.cpp:296
Value get(const char *key) const
Definition Json.cpp:301
size_t size() const
Definition Json.cpp:316
bool isArray() const
Definition Json.cpp:297
Value at(size_t index) const
Definition Json.cpp:323
int getInt(const char *key, int fallback=0) const
Definition Json.cpp:385
std::string getString(const char *key, const std::string &fallback={}) const
Definition Json.cpp:390
int asInt(int fallback=0) const
Definition Json.cpp:355
std::vector< std::string > getStringArray(const char *key) const
Definition Json.cpp:402
std::unordered_map< std::string, int > getIntMap(const char *key) const
Definition Json.cpp:432
std::unordered_map< std::string, std::string > getStringMap(const char *key) const
Definition Json.cpp:424
std::vector< int > getIntArray(const char *key) const
Definition Json.cpp:406
建筑放置模块入口:定义 / 放置世界 / 鬼影 / 变更事件的脚本绑定点。 设计文档:docs/dev/建筑放置系统设计.md
Definition Building.cpp:7
建筑模板(进程级注册表中的定义)。
std::unordered_map< std::string, std::string > visual2d
std::unordered_map< std::string, int > cost
std::unordered_map< std::string, std::string > visual3d
std::string channel
占地格子尺寸。
bool maskAt(int localX, int localY) const
占地掩码在局部坐标 (localX, localY) 处是否占用。
std::unordered_map< std::string, std::string > extra
std::string requireAdjacentTag
非空:邻格需有带该 tag 的建筑。
std::vector< int > requireTerrain
空 = 不限制地形语义。
std::string getVisual2d(const std::string &key, const std::string &fallback={}) const
std::string rotationMode
none | cardinal | free。
std::string validateRule
default | boundsOnly | overlapOk | 自定义。
int getCost(const std::string &resource, int fallback=0) const
std::string getExtra(const std::string &key, const std::string &fallback={}) const
std::string snapMode
grid | cell | free | 自定义。
std::vector< uint8_t > footprintMask
可选占地掩码,长度 footprintW*footprintH;空表示实心矩形。行主序、原点在最小 x/y。
bool hasTag(const std::string &tag) const
查询辅助。
std::vector< std::string > tags
int requireAdjacentTerrain
>=0:邻格地形语义;-1 = 不限。
std::string getVisual3d(const std::string &key, const std::string &fallback={}) const
std::vector< std::string > tags
void setProp(const std::string &key, const std::string &value)
std::string getProp(const std::string &key, const std::string &fallback={}) const
std::unordered_map< std::string, std::string > props
bool hasTag(const std::string &tag) const