Porytiles
Loading...
Searching...
No Matches
decompile_primary_tileset.cpp
Go to the documentation of this file.
2
3#include <memory>
4#include <string>
5
9
10namespace porytiles {
11
12ChainableResult<void> DecompilePrimaryTileset::decompile(const std::string &tileset_name) const
13{
14 // 1. Check if the primary tileset exists and is Porytiles-managed. If not, abort with error.
15 if (!metadata_provider_->exists(tileset_name)) {
16 return FormattableError{"Tileset '{}' does not exist.", FormatParam{tileset_name, Style::bold}};
17 }
18 if (!tileset_manager_->is_porytiles_managed(tileset_name)) {
19 return FormattableError{
20 "Tileset '{}' exists but is not Porytiles-managed.", FormatParam{tileset_name, Style::bold}};
21 }
22
23 // 2. Load the tileset into a `Tileset` aggregate.
25 tileset,
26 tileset_repo_->load(tileset_name),
27 void,
28 diag_->formatter().format("Failed to load tileset '{}'.", FormatParam(tileset_name, Style::bold)));
29
30 PT_UNWRAP_TILESET_CONFIG_PTR(app_config_, verify_checksums, tileset_name, void);
31 if (!tileset_repo_->checksum_provider().cached_checksums_exist(tileset_name) && verify_checksums) {
32 std::vector<std::string> err_msg{};
33 err_msg.emplace_back(diag_->formatter().format(
34 "No cached checksums found for tileset '{}'.", FormatParam{tileset_name, Style::bold}));
35 err_msg.emplace_back(diag_->formatter().format(
36 "Expected to find file '{}'.",
37 FormatParam{"porytiles/tilesets/" + tileset_name + "/tileset.cache.json", Style::bold}));
38 err_msg.emplace_back("Checksum verification requested via configuration.");
39 err_msg.append_range(format_config_note_with_separator(diag_->formatter(), verify_checksums));
40
42 }
43
44 // 3. If `PorytilesTilesetComponent` is not empty, compare with cached checksums in `tileset.cache.json`.
45 // If any differ, bail with the message "uncompiled changes present in Porytiles asset X."
46
47 // Only perform the checksum checks if: 1) cached checksums exist and 2) the user is requesting checksum validation
48 if (tileset_repo_->checksum_provider().cached_checksums_exist(tileset_name) && verify_checksums.value()) {
49 if (!tileset->porytiles_component().is_empty()) {
51 porytiles_keys,
52 tileset_repo_->key_provider().get_porytiles_artifact_keys(tileset_name),
53 void,
54 "Failed to get Porytiles artifact keys.");
55 const auto mismatched_keys =
56 tileset_repo_->checksum_provider().find_unsynced_tileset_artifacts(tileset_name, porytiles_keys);
57 if (!mismatched_keys.empty()) {
58 std::vector<std::string> err_msg{};
59 err_msg.emplace_back("Changes present in Porytiles assets:");
60 for (const auto &key : mismatched_keys) {
61 err_msg.emplace_back(diag_->formatter().format(" {}", FormatParam{key.key(), Style::bold}));
62 }
63 err_msg.emplace_back("");
64 err_msg.emplace_back("Decompiling now would clobber your Porytiles asset changes.");
65 err_msg.emplace_back("To resolve:");
66 err_msg.emplace_back(diag_->formatter().format(
67 " - Run '{} {}' to synchronize assets.",
68 FormatParam{"compile-tileset", Style::bold},
69 FormatParam{tileset_name, Style::bold}));
70 err_msg.emplace_back(diag_->formatter().format(
71 " - {} disable checksum verification to allow the clobber.", FormatParam{"OR", Style::bold}));
72 err_msg.emplace_back(diag_->formatter().format(
73 " - {} delete '{}' cache file.",
75 FormatParam{"porytiles/tilesets/" + tileset_name + "/tileset.cache.json", Style::bold}));
76 err_msg.append_range(format_config_note_with_separator(diag_->formatter(), verify_checksums));
78 }
79 }
80
81 // 4. If all `PorymapTilesetComponent` checksums match those cached in `tileset.cache.json`, bail with the
82 // message "nothing to do."
84 porymap_keys,
85 tileset_repo_->key_provider().get_porymap_artifact_keys(tileset_name),
86 void,
87 "Failed to get Porymap artifact keys.");
88 if (tileset_repo_->checksum_provider().all_checksums_tileset_match(tileset_name, porymap_keys)) {
89 diag_->warning(
90 "nothing-to-do",
91 "Skipping decompilation for '{}', no changes found.",
92 FormatParam{tileset_name, Style::bold});
93 return {};
94 }
95 }
96
97 // 5. Decompile the `PorymapTilesetComponent`, generating a new `PorytilesTilesetComponent`.
99 decompiled_tileset,
100 decompiler_->decompile(*tileset),
101 void,
102 "Import job failed for '{}'.",
103 FormatParam(tileset_name, Style::bold));
104
105 // 6. Persist the `Tileset` (which also caches the checksums).
107 tileset_repo_->save(*decompiled_tileset),
108 void,
109 "Tileset save job failed for '{}'.",
110 FormatParam(tileset_name, Style::bold));
111
112 // 7. Handle animation code wiring
113 if (!decompiled_tileset->porytiles_component().anims().empty()) {
114 // Tileset has animations - wire the generated code
116 tileset_manager_->wire_anim_code(tileset_name, /*is_secondary=*/false),
117 void,
118 "Failed to wire animation code for '{}'.",
119 FormatParam(tileset_name, Style::bold));
120 }
121 else {
122 // Tileset has no animations - remove any stale wiring
124 tileset_manager_->remove_wired_anim_code(tileset_name, /*is_secondary=*/false),
125 void,
126 "Failed to remove wired animation code for '{}'.",
127 FormatParam(tileset_name, Style::bold));
128 }
129
130 return {};
131}
132
133} // namespace porytiles
#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type,...)
Unwraps a ChainableResult, chaining a new error message on failure.
#define PT_TRY_CALL_CHAIN_ERR(expr, return_type,...)
Unwraps a void ChainableResult, chaining a new error message on failure.
bool all_checksums_tileset_match(const std::string &name, const std::vector< ArtifactKey > &artifact_keys) const
Checks if all artifact checksums for the given Tileset match their cached values.
std::vector< ArtifactKey > find_unsynced_tileset_artifacts(const std::string &name, const std::vector< ArtifactKey > &keys_to_check) const
Finds all artifacts for the given Tileset with unsynced changes compared to cached checksums.
bool cached_checksums_exist(const std::string &name) const
Check if any cached checksums exist for the given tileset.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
ChainableResult< void > decompile(const std::string &tileset_name) const
Decompiles the primary Tileset with the given tileset name.
A text parameter with associated styling for formatted output.
General-purpose error implementation with formatted message support.
Definition error.hpp:63
virtual ChainableResult< void > wire_anim_code(const std::string &tileset_name, bool is_secondary) const =0
Wires animation code for a tileset that already has its manifest persisted.
virtual bool is_porytiles_managed(const std::string &tileset_name) const =0
Checks whether a tileset is managed by Porytiles.
virtual ChainableResult< void > remove_wired_anim_code(const std::string &tileset_name, bool is_secondary) const =0
Removes wired animation code for a tileset from the project.
ChainableResult< std::unique_ptr< Tileset > > decompile(const Tileset &tileset) const
static const Style bold
Bold text formatting.
virtual std::string format(const std::string &format_str, const std::vector< FormatParam > &params) const
Formats a string with styled parameters using fmtlib syntax.
virtual ChainableResult< std::vector< ArtifactKey > > get_porytiles_artifact_keys(const std::string &tileset_name) const
Gets the keys for all Porytiles artifacts present in the given Tileset.
virtual ChainableResult< std::vector< ArtifactKey > > get_porymap_artifact_keys(const std::string &tileset_name) const
Gets the keys for all Porymap artifacts present in the given Tileset.
virtual bool exists(const std::string &tileset_name) const =0
Checks whether a tileset exists in the backing store for the given tileset name.
ChainableResult< void > save(const Tileset &tileset) const
Persists a given Tileset and caches new artifact checksums.
ChainableResult< std::unique_ptr< Tileset > > load(const std::string &name) const
Loads an existing Tileset from storage.
const TilesetArtifactKeyProvider & key_provider() const
Gets a reference to the TilesetArtifactKeyProvider for this repo.
const ArtifactChecksumProvider & checksum_provider() const
Gets a reference to the ArtifactChecksumProvider for this repo.
const TextFormatter & formatter() const
virtual void warning(const std::string &tag, const std::vector< std::string > &lines) const =0
Display a tagged warning message.
std::vector< std::string > format_config_note_with_separator(const TextFormatter &format, const ConfigValue< T > &config)
Format a ConfigValue into diagnostic note lines with a separator.
@ tileset
Configuration scoped to a specific tileset.
#define PT_UNWRAP_TILESET_CONFIG_PTR(ptr, config, tileset_name, return_type)
Unwraps a tileset-scoped config value via pointer access, returning early if the value is not availab...