Standardizing the way dynamically loaded stuff is handled #11798
Labels
<Enhancement / Feature>
New features, or enhancements on existing
Game: Mechanics Change
Code that changes how major features work
(P5 - Long-term)
Long-term WIP, may stay on the list for a while.
<Suggestion / Discussion>
Talk it out before implementing
Handling the dynamically loaded stuff is very _in_consistently done:
termap
) vs inside a singleton, (e.g.item_action_generator
, which is not a real singleton because it has a public constructor)termap
,bionics
,Skills::skills
profession::_all_profs
,item_factory
termap
Skills::skills
item_factory
Having this consistent would make it easier to understand (one has to understand it for one object type and can transfer that knowledge to all the other object types). It might also allow to include a better (and generic) blacklist/whitelist. Hey, this just came up in another issue.
I thought about the following changes:
To address the access restriction:
Move all the maps/lists etc. into the class they contain, as static private variables. Add public load functions that can write to the private members (which allows to make those members private in the first place) and add / remove from the map.
Add get/find functions that can access the map, return a dummy value if no matching entry is found (along with a debug message), return a const reference to the entry to forbid writing to them.
The maps/lists do not need to be inside the struct, they can be hidden completely inside the cpp file as introduced in #11791, through the wrapper function should probably be part of the struct to prevent accessing it in a non-const way when a const reference is just as good.
At this point a standardization of those access function should be discussed, for example:
Instead of the whole map (
get_all
), one could expose begin and end iterators as it is already done for example in the profession class, but I think this is not very useful. It has no advantage at all and exposing the map (as const reference) allows much more (like find and range-based loops) and still respects the const.Having overloads for the
get
andhas
functions makes it easier to use, one can writeget(X)
without thinking about whetherX
is the int id, or the string id.The names are short, even with the struct prefix:
For loading/unloading, the container struct only needs to contain the following 7 lines (or less if the check_consistency/finalize function are not needed):
This packs the functions neatly together, has a reference to the place that explains the dynamic load system and has no redundant documentation because the function behave the same for all types,
load
loads the given entry (and adds it to the internal map),check_consistency
checks for internal consistency/invalid references,unload
unloads the data (inverse of load),finalize
does some stuff after everything else has been loaded to finalize the data.The
/*@{*/
marks the functions as belonging together (used in the automatically generated documentation).This leaves the places that use a wrapper instance, like
item_factory
,item_action
,MonsterGenerator
, probably more.Those are inconsistent in the way they expose the single instance:
item_factory
exists as a global static pointer variable,MonsterGenerator
has the staticgenerator
function that returns the single instance,snippet_library
exists as a global static variable (not a pointer).Their functions should probably follow the same naming scheme as the static functions.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered: