载入中...
搜索中...
未找到
ModuleAssembly.cpp
浏览该文件的文档.
59const ModuleDefinition* findDefinition(const std::vector<ModuleDefinition>& definitions, const std::string& id) {
61 std::find_if(definitions.begin(), definitions.end(), [&](const auto& item) { return item.id == id; });
65std::vector<Voxel> occupiedVoxels(const ModuleDefinition& definition, const ModulePlacement& placement) {
67 result.reserve(static_cast<size_t>(definition.widthCells) * definition.depthCells * definition.heightLevels);
73 result.push_back({placement.cellX + local.x, placement.cellZ + local.z, placement.level + local.level});
87std::vector<WorldConnector> worldConnectors(const ModuleDefinition& definition, const ModulePlacement& placement) {
91 const Voxel local = rotateCell(connector.cellX, connector.cellZ, connector.levelOffset, definition.widthCells,
93 result.push_back({placement.cellX + local.x, placement.cellZ + local.z, placement.level + local.level,
118 if (!encoded || *encoded < std::numeric_limits<int>::min() || *encoded > std::numeric_limits<int>::max())
125 static constexpr std::array<const char*, 6> names{"north", "east", "south", "west", "up", "down"};
132ModuleAssemblyPlan::ModuleAssemblyPlan(ModuleAssemblyConstraints constraints) : constraints_(std::move(constraints)) {}
134Result<void> ModuleAssemblyPlan::configure(float cellSize, float floorHeight, int minCellX, int maxCellX, int minCellZ,
139 if (!std::isfinite(cellSize) || cellSize <= 0.f || !std::isfinite(floorHeight) || floorHeight <= 0.f ||
141 return reject(DiagnosticCode::InvalidArgument, "assembly dimensions and bounds must be valid", "constraints");
154Result<void> ModuleAssemblyPlan::setAllowedQuarterTurns(bool turn0, bool turn90, bool turn180, bool turn270) {
159 return reject(DiagnosticCode::InvalidArgument, "at least one module rotation must be allowed", "constraints");
169 return reject(DiagnosticCode::InvalidArgument, "minimum support ratio must be between zero and one",
177 return reject(DiagnosticCode::PreconditionViolation, "JSON configuration requires an empty plan", "config");
179 return reject(DiagnosticCode::InvalidArgument, "assembly configuration exceeds 1 MiB", "config");
184 return reject(DiagnosticCode::InvalidArgument, "assembly configuration root fields are invalid", "config");
190 if (!schema || *schema != "eve.procgen.module-assembly" || !version || *version != 1 || !unknown ||
191 *unknown != "reject" || !constraints || !modules || modules->empty() || modules->size() > 4096 ||
194 return reject(DiagnosticCode::InvalidArgument, "assembly configuration schema is invalid", "config");
196 const auto *cellSize = number(constraints->at("cellSize")), *floorHeight = number(constraints->at("floorHeight")),
202 if (!cellSize || !floorHeight || !support || !bounds || !turns || turns->size() != 4 || !requireConnection ||
205 return reject(DiagnosticCode::InvalidArgument, "assembly constraint fields are invalid", "constraints");
212 return reject(DiagnosticCode::InvalidArgument, "rotation entries must be booleans", "constraints");
215 if (!bounded || !integer(bounds->at("minCellX"), minX) || !integer(bounds->at("maxCellX"), maxX) ||
217 return reject(DiagnosticCode::InvalidArgument, "assembly bounds are invalid", "constraints.bounds");
220 auto configured = candidate.configure(float(*cellSize), float(*floorHeight), minX, maxX, minZ, maxZ, maxLevels,
223 auto rotations = candidate.setAllowedQuarterTurns(allowed[0], allowed[1], allowed[2], allowed[3]);
229 if (!module || !exact(*module, {"id", "widthCells", "depthCells", "heightLevels", "connectors"}))
234 if (!id || !connectors || connectors->size() > 16384 || !integer(module->at("widthCells"), width) ||
258Result<void> ModuleAssemblyPlan::registerModuleType(std::string id, int widthCells, int depthCells) {
262Result<void> ModuleAssemblyPlan::registerVolumeModuleType(std::string id, int widthCells, int depthCells,
269Result<void> ModuleAssemblyPlan::addConnector(const std::string& moduleId, int cellX, int cellZ, int facing,
271 return addVolumeConnector(moduleId, cellX, cellZ, 0, facing, std::move(tag), std::move(accepts));
274Result<void> ModuleAssemblyPlan::addVolumeConnector(const std::string& moduleId, int cellX, int cellZ, int levelOffset,
277 std::find_if(definitions_.begin(), definitions_.end(), [&](const auto& item) { return item.id == moduleId; });
285 cellZ >= definition->depthCells || levelOffset < 0 || levelOffset >= definition->heightLevels || tag.empty() ||
287 return reject(DiagnosticCode::InvalidArgument, "connector fields are outside the module contract", moduleId);
289 {cellX, cellZ, static_cast<ModuleFacing>(facing), std::move(tag), std::move(accepts), levelOffset});
294 if (definition.id.empty()) return reject(DiagnosticCode::InvalidArgument, "module id must not be empty", "id");
296 return reject(DiagnosticCode::InvalidArgument, "module volume dimensions must be positive", definition.id);
302 connector.levelOffset >= definition.heightLevels || connector.tag.empty() || connector.accepts.empty())
303 return reject(DiagnosticCode::InvalidArgument, "connector must reference a volume cell and typed tags",
312 if (!definition) return reject(DiagnosticCode::NotFound, "module definition is not registered", placement.moduleId);
315 return reject(DiagnosticCode::PreconditionViolation, "module rotation is disabled by the assembly constraints",
317 if (placement.level < 0 || int64_t(placement.level) + definition->heightLevels > constraints_.maxLevels)
318 return reject(DiagnosticCode::PreconditionViolation, "module level is outside the configured range",
349 if (cell.x < constraints_.minCellX || cell.x > constraints_.maxCellX || cell.z < constraints_.minCellZ ||
351 return reject(DiagnosticCode::PreconditionViolation, "module footprint crosses assembly bounds",
365 static_cast<size_t>(std::ceil(double(constraints_.minimumSupportRatio) * double(bottomCellCount)));
384 const auto own = std::find_if(connectors.begin(), connectors.end(), [&](const auto& connector) {
390 return connector.x == neighborX && connector.z == neighborZ && connector.level == neighborLevel &&
394 return reject(DiagnosticCode::Conflict, "touching module edges do not expose compatible connectors",
400 return reject(DiagnosticCode::PreconditionViolation, "module is disconnected from the existing assembly",
Owning, renderer-independent dynamic values.
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
static Result< Value > fromJson(std::string_view json)
Parse one strict JSON value into an owning Value.
Definition Value.cpp:57
Deterministic owner of a validated modular assembly plan.
Definition ModuleAssembly.h:69
Result< void > registerVolumeModuleType(std::string id, int widthCells, int depthCells, int heightLevels)
Register a three-dimensional module volume using scalar script-friendly fields.
Definition ModuleAssembly.cpp:262
std::string getPlacementModule(int index) const
Return one accepted placement's module id, or empty text for an invalid index.
Definition ModuleAssembly.cpp:406
const ModuleAssemblyConstraints & constraints() const noexcept
Return the immutable constraint configuration.
Definition ModuleAssembly.h:139
Result< void > place(ModulePlacement placement)
Validate and atomically append one placement. @cost Linear in existing occupied cells and connectors.
Definition ModuleAssembly.cpp:310
Result< void > applyConfigJson(const std::string &json)
Atomically replace an empty plan's constraints and module definitions from strict JSON....
Definition ModuleAssembly.cpp:175
Result< void > setAllowedQuarterTurns(bool turn0, bool turn90, bool turn180, bool turn270)
Configure the four permitted quarter-turn rotations before registration or placement.
Definition ModuleAssembly.cpp:154
Result< void > addConnector(const std::string &moduleId, int cellX, int cellZ, int facing, std::string tag, std::string accepts)
Append a typed connector to a registered, not-yet-placed module.
Definition ModuleAssembly.cpp:269
float getPlacementY(int index) const noexcept
Return one placement's world Y coordinate, or zero for an invalid index.
Definition ModuleAssembly.cpp:418
Result< void > registerModuleType(std::string id, int widthCells, int depthCells)
Register a module footprint using scalar script-friendly fields.
Definition ModuleAssembly.cpp:258
ModuleAssemblyPlan()=default
Construct an empty plan with default constraints.
float getPlacementX(int index) const noexcept
Return one placement's world X coordinate, or zero for an invalid index.
Definition ModuleAssembly.cpp:412
float getPlacementZ(int index) const noexcept
Return one placement's world Z coordinate, or zero for an invalid index.
Definition ModuleAssembly.cpp:424
Result< void > configure(float cellSize, float floorHeight, int minCellX, int maxCellX, int minCellZ, int maxCellZ, int maxLevels, bool bounded, bool requireConnection)
Configure an empty plan before definitions or placements are added.
Definition ModuleAssembly.cpp:134
Result< void > addVolumeConnector(const std::string &moduleId, int cellX, int cellZ, int levelOffset, int facing, std::string tag, std::string accepts)
Append a typed connector to one face of a cell in a module volume.
Definition ModuleAssembly.cpp:274
float getPlacementYawDegrees(int index) const noexcept
Return one placement's yaw in degrees, or zero for an invalid index.
Definition ModuleAssembly.cpp:430
Result< void > registerModule(ModuleDefinition definition)
Register one module definition before it is placed.
Definition ModuleAssembly.cpp:293
Result< void > setMinimumSupportRatio(float ratio)
Require this fraction of an elevated module's bottom cells to be supported from below.
Definition ModuleAssembly.cpp:164
constexpr HexDirection opposite(HexDirection d) noexcept
The direction opposite to d.
Definition HexMetrics.h:65
const EditorValue * field(const EditorValue &value, const char *name)
Definition RoadNetworkEditTarget.cpp:15
Definition EvpackPointGraphLoader.h:12
ModuleFacing
Horizontal or vertical face used by grid-module connection constraints.
Definition ModuleAssembly.h:13
@ InvalidArgument
@ NotFound
@ PreconditionViolation
@ AlreadyExists
@ Conflict
@ Applied
Definition Container.h:602
Configurable limits shared by automatic modular-map generators.
Definition ModuleAssembly.h:44
std::array< bool, 4 > allowedQuarterTurns
Definition ModuleAssembly.h:52
float minimumSupportRatio
Definition ModuleAssembly.h:55
bool requireConnection
Definition ModuleAssembly.h:54
Immutable footprint and connection contract for one modular asset.
Definition ModuleAssembly.h:26
World-grid placement accepted by a ModuleAssemblyPlan.
Definition ModuleAssembly.h:35