Porytiles
Loading...
Searching...
No Matches
command_create_tileset.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4
5#include "CLI/CLI.hpp"
6
13
14#include "command.hpp"
15#include "option.hpp"
17
18class CreateTilesetCommand final : public Command {
19 public:
20 explicit CreateTilesetCommand(CLI::App &parent_app) : Command{parent_app, command_name, command_desc, command_group}
21 {
22 CLI::App &cmd = get_app();
23 cmd.add_option("<tileset-name>", tileset_name_, "Name of the tileset to create (e.g., gTileset_MyTileset)")
24 ->required();
25 cmd.add_flag("--secondary", secondary_, "Create a secondary tileset instead of a primary.");
26 project_root_opt_.RegisterOpt(cmd);
27 porytiles::register_config_options(cmd, cli_storage_);
28 }
29
30 private:
31 void Run() override
32 {
33 using namespace porytiles;
34
35 TilesetCommandEnv env{project_root_opt_.project_root(), cli_storage_};
36
37 // Env initialization and schema resolution can fail, so they run first and their failures chain and report
38 // through the unfiltered stderr diagnostics.
39 const auto env_result = env.initialize(tileset_name_);
40 if (!env_result.has_value()) {
41 const auto env_fail_result = ChainableResult<void>{
42 FormattableError{"Failed to create tileset '{}'.", FormatParam{tileset_name_, Style::bold}},
43 env_result};
44 env.stderr_diag.fatal(env_fail_result);
45 throw CLI::RuntimeError{1};
46 }
47
48 auto attribute_context = resolve_attribute_context(env, tileset_name_);
49 if (!attribute_context.has_value()) {
50 const auto fail_result = ChainableResult<void>{
51 FormattableError{"Failed to create tileset '{}'.", FormatParam{tileset_name_, Style::bold}},
52 attribute_context};
53 env.diag->fatal(fail_result);
54 throw CLI::RuntimeError{1};
55 }
56 TilesetCommandServices services{env, std::move(attribute_context).value()};
57
58 // Setup creator. The creator seeds its sample art with a behavior constant name, so it needs the
59 // behavior field's provider. A schema without a provider-backed behavior field cannot support creation, so fail
60 // fast here rather than letting the creator resolve names against nothing.
61 const auto behavior_provider_it = services.provider_map.find(attribute::field_behavior);
62 if (behavior_provider_it == services.provider_map.end()) {
63 const auto no_behavior_err = ChainableResult<void>{FormattableError{
64 "Cannot create a tileset: the resolved attribute schema has no provider-backed '{}' field.",
65 FormatParam{std::string{attribute::field_behavior}, Style::bold}}};
66 env.diag->fatal(no_behavior_err);
67 throw CLI::RuntimeError{1};
68 }
69 TilesetCreator creator{&env.config, behavior_provider_it->second.get()};
70
71 // Create and run the appropriate use case based on --secondary flag
72 ChainableResult<void> create_result;
73 if (secondary_) {
74 CreateSecondaryTileset create_use_case{
75 &creator,
76 &services.compiler,
77 &services.repo,
78 &services.metadata_provider,
79 &services.layout_metadata_provider,
80 &services.tileset_manager,
81 &env.config,
82 &env.config,
83 env.diag.get()};
84 create_result = create_use_case.create(tileset_name_);
85 }
86 else {
87 CreatePrimaryTileset create_use_case{
88 &creator,
89 &services.compiler,
90 &services.repo,
91 &services.metadata_provider,
92 &services.tileset_manager,
93 &env.config,
94 &env.config,
95 env.diag.get()};
96 create_result = create_use_case.create(tileset_name_);
97 }
98 if (!create_result.has_value()) {
99 const auto fail_result = ChainableResult<void>{
100 FormattableError{"Failed to create tileset '{}'.", FormatParam{tileset_name_, Style::bold}},
101 create_result};
102 env.diag->fatal(fail_result);
103 throw CLI::RuntimeError{1};
104 }
105 }
106
107 static constexpr auto command_name = "create-tileset";
108 static constexpr auto command_desc = "Create a new Porytiles-managed tileset from scratch.";
109 static constexpr auto command_group = "COMMANDS";
110 std::string tileset_name_;
111 bool secondary_ = false;
112 OptProjectRoot project_root_opt_;
113 porytiles::CliOptionStorage cli_storage_;
114};
Command is an abstract class that provides basic command functionality for the Porytiles CLI driver.
Definition command.hpp:16
CLI::App & get_app() const
Definition command.hpp:42
CreateTilesetCommand(CLI::App &parent_app)
std::filesystem::path project_root() const
Definition option.hpp:58
void RegisterOpt(CLI::App &app) override
Definition option.hpp:46
A result type that maintains a chainable sequence of errors for debugging and error reporting.
bool has_value() const
Checks whether the result contains a success value.
Use case for creating a new primary Tileset from scratch.
Use case for creating a new secondary Tileset from scratch.
A text parameter with associated styling for formatted output.
General-purpose error implementation with formatted message support.
Definition error.hpp:57
Bootstrap class so every tileset command can share common config and diagnostic setup.
The schema-driven service graph shared by the compile, create, import, and decompile commands.
Domain service for creating new tilesets from scratch.
void register_config_options(CLI::App &app, CliOptionStorage &storage)
Registers all config options with a CLI11 App.
ChainableResult< ResolvedAttributeContext > resolve_attribute_context(TilesetCommandEnv &env, const std::string &tileset_name)
Resolves the invocation's metatile attribute schema and builds the provider map for its fields.
Storage struct for CLI option values.