Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
ResourceRuntime.cpp
Go to the documentation of this file.
1#include "ResourceRuntime.hpp"
2
3#include <utility>
4
5namespace monopoly::data
6{
7 std::vector<DataError> inspectResourceInstallation(
8 const ResourcePaths& paths, ResourceContext context,
9 ArchiveOpenOptions options)
10 {
11 std::vector<DataError> issues;
12 if (context.board != BoardEdition::Usa &&
13 context.board != BoardEdition::Europe)
14 {
16 std::nullopt, "board edition must be USA or Europe"});
17 return issues;
18 }
19 const auto* language = findLanguageBankTriplet(context.language);
20 if (!language)
21 {
23 std::nullopt, "language ID must be in the source-defined range 1..10"});
24 return issues;
25 }
26
27 const auto inspect = [&](const BankDefinition& bank)
28 {
29 const auto path = paths.resolve(bank.legacyPath);
30 if (!path)
31 {
32 auto error = path.error();
33 error.detail = std::string(bank.legacyPath) + ": " + error.detail;
34 issues.push_back(std::move(error));
35 return;
36 }
37 const auto archive = LegacyDataArchive::open(
38 *path, legacyGroupValue(bank.group), options);
39 if (!archive)
40 {
41 auto error = archive.error();
42 error.detail = std::string(bank.legacyPath) + ": " + error.detail;
43 issues.push_back(std::move(error));
44 }
45 };
46 for (const auto& bank : coreBanks(context.board)) inspect(bank);
47 for (const auto* bank :
48 {&language->text, &language->graphics, &language->dialog})
49 inspect(*bank);
50
51 if (issues.empty())
52 {
54 const auto initialized = candidate.initialize(paths, context, options);
55 if (!initialized) issues.push_back(initialized.error());
56 }
57 return issues;
58 }
59
60 ResourceSnapshot::ResourceSnapshot(
61 ResourcePaths paths, ResourceContext context)
62 : paths_(std::move(paths)),
63 context_(context),
64 banks_(std::make_shared<DataBankRegistry>()),
65 data_(banks_)
66 {
67 }
68
69
70 const DataSource& ResourceSnapshot::data() const noexcept
71 {
72 return *data_;
73 }
74
75
76 const DataBankRegistry& ResourceSnapshot::banks() const noexcept
77 {
78 return *banks_;
79 }
80
81
82 std::shared_ptr<const LanguageSnapshot>
83 ResourceSnapshot::language() const noexcept
84 {
85 return language_.snapshot();
86 }
87
88
89 ResourceContext ResourceSnapshot::context() const noexcept
90 {
91 return context_;
92 }
93
94
95 const ResourcePaths& ResourceSnapshot::paths() const noexcept
96 {
97 return paths_;
98 }
99
100
101 std::expected<void, DataError> ResourceRuntime::initialize(
102 ResourcePaths paths,
103 ResourceContext context,
104 ArchiveOpenOptions options,
105 std::span<const DataSourceOverride> overrides)
106 {
107 if (context.board != BoardEdition::Usa &&
108 context.board != BoardEdition::Europe)
109 {
110 return std::unexpected(DataError{
111 DataErrorCode::InvalidBoardEdition, {}, std::nullopt,
112 "board edition must be USA or Europe" });
113 }
114 const auto* language = findLanguageBankTriplet(context.language);
115 if (language == nullptr)
116 {
117 return std::unexpected(DataError{
118 DataErrorCode::InvalidLanguage, {}, std::nullopt,
119 "language ID must be in the source-defined range 1..10" });
120 }
121
122 auto staged = std::shared_ptr<ResourceSnapshot>(
123 new ResourceSnapshot(std::move(paths), context));
124 const auto mount = [&](const BankDefinition& definition)
125 -> std::expected<void, DataError>
126 {
127 auto path = staged->paths_.resolve(definition.legacyPath);
128 if (!path)
129 {
130 auto error = path.error();
131 error.detail = std::string(definition.legacyPath) +
132 ": " + error.detail;
133 return std::unexpected(std::move(error));
134 }
135 auto archive = staged->banks_->mount(
136 *path, legacyGroupValue(definition.group), options);
137 if (!archive)
138 {
139 return std::unexpected(archive.error());
140 }
141 return {};
142 };
143
144 for (const auto& definition : coreBanks(context.board))
145 {
146 auto result = mount(definition);
147 if (!result)
148 {
149 return std::unexpected(result.error());
150 }
151 }
152 for (const auto* definition :
153 { &language->text, &language->graphics, &language->dialog })
154 {
155 auto result = mount(*definition);
156 if (!result)
157 {
158 return std::unexpected(result.error());
159 }
160 }
161 // Publish modern replacements on the logical DATA surface first.
162 // Language selection then validates its index and strings through the
163 // exact same source, so groups 5/9/10 can migrate incrementally too.
164 if (!overrides.empty())
165 {
166 auto layered = LayeredDataSource::create(staged->data_, overrides);
167 if (!layered)
168 {
169 return std::unexpected(layered.error());
170 }
171 staged->data_ = std::move(*layered);
172 }
173
174 auto selected = staged->language_.select(
175 *staged->banks_,
176 staged->data_,
177 context.language);
178 if (!selected)
179 {
180 return std::unexpected(selected.error());
181 }
182
183 std::scoped_lock lock(mutex_);
184 active_ = std::move(staged);
185 return {};
186 }
187
188
189 std::shared_ptr<const ResourceSnapshot>
190 ResourceRuntime::snapshot() const noexcept
191 {
192 std::scoped_lock lock(mutex_);
193 return active_;
194 }
195
196
197 void ResourceRuntime::shutdown() noexcept
198 {
199 std::scoped_lock lock(mutex_);
200 active_.reset();
201 }
202}
unsigned index
std::string path
std::string error
static std::expected< std::shared_ptr< LegacyDataArchive >, DataError > open(const std::filesystem::path &path, std::uint16_t group, ArchiveOpenOptions options={})
std::expected< std::filesystem::path, DataError > resolve(std::string_view relativePath) const
std::expected< void, DataError > initialize(ResourcePaths paths, ResourceContext context={}, ArchiveOpenOptions options={}, std::span< const DataSourceOverride > overrides={})
constexpr std::uint16_t legacyGroupValue(LegacyGroupId group) noexcept
Definition DataBanks.hpp:30
const LanguageBankTriplet * findLanguageBankTriplet(LanguageId language) noexcept
std::vector< DataError > inspectResourceInstallation(const ResourcePaths &paths, ResourceContext context, ArchiveOpenOptions options)
const CoreBankDefinitions & coreBanks(BoardEdition edition) noexcept