diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b29f093b2..8970747cd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,8 @@ add_library(${PROJECT_NAME} src/color.h src/compiler.h src/config_param.h + src/db.cpp + src/db.h src/decoder_fluidsynth.cpp src/decoder_fluidsynth.h src/decoder_libsndfile.cpp @@ -167,6 +169,8 @@ add_library(${PROJECT_NAME} src/hslrgb.cpp src/hslrgb.h src/icon.h + src/idutils.h + src/idutils.cpp src/image_bmp.cpp src/image_bmp.h src/image_png.cpp diff --git a/Makefile.am b/Makefile.am index 3365003d21..0dbcfd85ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,8 @@ libeasyrpg_player_a_SOURCES = \ src/cmdline_parser.h \ src/color.h \ src/compiler.h \ + src/db.cpp \ + src/db.h \ src/decoder_fluidsynth.cpp \ src/decoder_fluidsynth.h \ src/decoder_fmmidi.cpp \ @@ -158,6 +160,8 @@ libeasyrpg_player_a_SOURCES = \ src/hslrgb.cpp \ src/hslrgb.h \ src/icon.h \ + src/idutils.h \ + src/idutils.cpp \ src/image_bmp.cpp \ src/image_bmp.h \ src/image_png.cpp \ diff --git a/src/db.cpp b/src/db.cpp new file mode 100644 index 0000000000..bd8f183e05 --- /dev/null +++ b/src/db.cpp @@ -0,0 +1,44 @@ +#include "db.h" +#include +#include +#include + +namespace db { + +namespace _impl { +Db db = {}; +} // _impl + +/** Load a new game */ +void LoadGame(const lcf::rpg::Database* database, const lcf::rpg::TreeMap* treemap) { + Clear(); + + _impl::db.database = database; + _impl::db.treemap = treemap; + + _impl::db.actors = database->actors; + _impl::db.skills = database->skills; + _impl::db.items = database->items; + _impl::db.enemies = database->enemies; + _impl::db.troops = database->troops; + _impl::db.terrains = database->terrains; + _impl::db.attributes = database->attributes; + _impl::db.states = database->states; + _impl::db.animations = database->animations; + _impl::db.chipsets = database->chipsets; + _impl::db.commonevents = database->commonevents; + _impl::db.battlecommands = &database->battlecommands; + _impl::db.classes = database->classes; + _impl::db.battleranimations = database->battleranimations; + _impl::db.terms = &database->terms; + _impl::db.system = &database->system; + _impl::db.switches = database->switches; + _impl::db.variables = database->variables; +} + +/** Clear all state */ +void Clear() { + _impl::db = {}; +} + +} // namespace db diff --git a/src/db.h b/src/db.h new file mode 100644 index 0000000000..d0201c22ca --- /dev/null +++ b/src/db.h @@ -0,0 +1,147 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EasyRPG Player. If not, see . + */ + +#ifndef EP_DB_H +#define EP_DB_H + +#include +#include "span.h" +#include "idutils.h" + +#include +#include + +namespace db { + +/** @return database actors */ +Span Actors(); + +/** @return database skills */ +Span Skills(); + +/** @return database items */ +Span Items(); + +/** @return database enemies */ +Span Enemies(); + +/** @return database troops */ +Span Troops(); + +/** @return database terrains */ +Span Terrains(); + +/** @return database attributes */ +Span Attributes(); + +/** @return database states */ +Span States(); + +/** @return database animations */ +Span Animations(); + +/** @return database chipsets */ +Span Chipsets(); + +/** @return database commonevents */ +Span Commonevents(); + +/** @return database battlecommands */ +const lcf::rpg::BattleCommands& Battlecommands(); + +/** @return database classes */ +Span Classes(); + +/** @return database battleranimations */ +Span Battleranimations(); + +/** @return database terms */ +const lcf::rpg::Terms& Terms(); + +/** @return database system */ +const lcf::rpg::System& System(); + +/** @return database switches */ +Span Switches(); + +/** @return database variables */ +Span Variables(); + +/** @return LDB database */ +const lcf::rpg::Database& Database(); + +/** @return LMT treemap */ +const lcf::rpg::TreeMap& Treemap(); + +/** Load a new game */ +void LoadGame(const lcf::rpg::Database* db, const lcf::rpg::TreeMap* treemap); + +/** Clear all state */ +void Clear(); + +namespace _impl { +struct Db { + const lcf::rpg::Database* database = nullptr; + const lcf::rpg::TreeMap* treemap = nullptr; + + Span actors; + Span skills; + Span items; + Span enemies; + Span troops; + Span terrains; + Span attributes; + Span states; + Span animations; + Span chipsets; + Span commonevents; + const lcf::rpg::BattleCommands* battlecommands = nullptr; + Span classes; + Span battleranimations; + const lcf::rpg::Terms* terms = nullptr; + const lcf::rpg::System* system = nullptr; + Span switches; + Span variables; +}; + +extern Db db; +} // impl + +inline Span Actors() { return _impl::db.actors; } +inline Span Skills() { return _impl::db.skills; } +inline Span Items() { return _impl::db.items; } +inline Span Enemies() { return _impl::db.enemies; } +inline Span Troops() { return _impl::db.troops; } +inline Span Terrains() { return _impl::db.terrains; } +inline Span Attributes() { return _impl::db.attributes; } +inline Span States() { return _impl::db.states; } +inline Span Animations() { return _impl::db.animations; } +inline Span Chipsets() { return _impl::db.chipsets; } +inline Span Commonevents() { return _impl::db.commonevents; } +inline const lcf::rpg::BattleCommands& Battlecommands() { return *_impl::db.battlecommands; } +inline Span Classes() { return _impl::db.classes; } +inline Span Battleranimations() { return _impl::db.battleranimations; } +inline const lcf::rpg::Terms& Terms() { return *_impl::db.terms; } +inline const lcf::rpg::System& System() { return *_impl::db.system; } +inline Span Switches() { return _impl::db.switches; } +inline Span Variables() { return _impl::db.variables; } + +inline const lcf::rpg::Database& Database() { return *_impl::db.database; } +inline const lcf::rpg::TreeMap& Treemap() { return *_impl::db.treemap; } + +} // namespace db +#endif diff --git a/src/idutils.cpp b/src/idutils.cpp new file mode 100644 index 0000000000..5094cb64ce --- /dev/null +++ b/src/idutils.cpp @@ -0,0 +1,6 @@ +#include "idutils.h" +#include "output.h" + +void IdUtils::Warning(int id, StringView objname, StringView log_context) { + Output::Warning("{}: Invalid DB {} ID {}!", log_context, objname, id); +} diff --git a/src/idutils.h b/src/idutils.h new file mode 100644 index 0000000000..d91552029c --- /dev/null +++ b/src/idutils.h @@ -0,0 +1,110 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EasyRPG Player. If not, see . + */ + +#ifndef EP_GET_H +#define EP_GET_H + +#include "span.h" +#include "string_view.h" + +#include +#include + +namespace IdUtils { + +/** + * Check with a 1 based id is valid. + * + * @param array the array to check + * @param the id to check against array + * @return true if the id valid + */ +template +bool IsValid(Span array, int id); + +/** + * Retrieve an element from the array using it's 1 based index. + * + * @param array the array to look into. + * @param id the 1 based id. + * @return reference to the requested object + * @pre If id is not valid id into the dataset the result is undefined. + */ +template +T& Get(Span array, int id); + +/** + * Retrieve an element from the array using it's 1 based index. + * + * @param array the array to look into. + * @param id the 1 based id. + * @return pointer to the requested object, or null if the id is invalid. + */ +template +T* GetPtr(Span array, int id); + +/** + * Retrieve an element from the array using it's 1 based index and log a warning if the id is invalid. + * + * @param array the array to look into. + * @param id the 1 based id. + * @param objname The name of the object type + * @param log_context A string describing the content with which this was called. + * @return pointer to the requested object, or null if the id is invalid. + */ +template +T* GetPtr(Span array, int id, StringView objname, StringView log_context); + +/** + * Log a warning about an invalid id. + * + * @param id the 1 based id. + * @param objname The name of the object type + * @param log_context A string describing the content with which this was called. + */ +void Warning(int id, StringView objname, StringView log_context); + +template +inline bool IsValid(Span array, int id) { + return id >= 1 && id <= static_cast(array.size()); +} + +template +inline T& Get(Span array, int id) { + assert(IsValid(array, id)); + return array[id - 1]; +} + + +template +inline T* GetPtr(Span array, int id) { + return IsValid(array, id) + ? array.data() + id - 1 + : nullptr; +} + +template +inline T* GetPtr(Span array, int id, StringView objname, StringView log_context) { + auto* p = GetPtr(array, id); + if (p == nullptr) { + Warning(id, objname, log_context); + } + return p; +} + +} // namespace IdUtils +#endif diff --git a/src/player.cpp b/src/player.cpp index 1f3ed09dab..11ab6fc209 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -84,6 +84,7 @@ #include #include "baseui.h" #include "game_clock.h" +#include "db.h" #ifndef EMSCRIPTEN // This is not used on Emscripten. @@ -874,6 +875,7 @@ void Player::GuessNonStandardExtensions() { void Player::LoadDatabase() { // Load lcf::Database lcf::Data::Clear(); + db::Clear(); if (is_easyrpg_project) { std::string edb = FileFinder::FindDefault(DATABASE_NAME_EASYRPG); @@ -907,6 +909,7 @@ void Player::LoadDatabase() { FileExtGuesser::GuessAndAddLmuExtension(*FileFinder::GetDirectoryTree(), *meta, fileext_map); } } + db::LoadGame(&lcf::Data::data, &lcf::Data::treemap); } static void FixSaveGames() { diff --git a/src/scene_gamebrowser.cpp b/src/scene_gamebrowser.cpp index ba4bb970c8..fedc465bc9 100644 --- a/src/scene_gamebrowser.cpp +++ b/src/scene_gamebrowser.cpp @@ -25,6 +25,7 @@ #include "scene_title.h" #include "bitmap.h" #include "audio.h" +#include "db.h" #ifdef _WIN32 #include @@ -55,6 +56,7 @@ void Scene_GameBrowser::Continue(SceneType /* prev_scene */) { Cache::Clear(); AudioSeCache::Clear(); lcf::Data::Clear(); + db::Clear(); Main_Data::Cleanup(); FileFinder::Quit();