Skip to content

Commit

Permalink
Global Abstractness (#419)
Browse files Browse the repository at this point in the history
* Global Abstraction pass

* fucking linters

* Dynamic codex entries use the basetype.

* Comments

* Baemed Consistency
  • Loading branch information
francinum authored Jul 31, 2023
1 parent 6431700 commit 579267d
Show file tree
Hide file tree
Showing 33 changed files with 76 additions and 77 deletions.
5 changes: 5 additions & 0 deletions code/__DEFINES/abstract.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
//This helper is underutilized, but that's a problem for me later. -Francinum

//514 does not allow initial(foo.static_var) on types, so we have to work around it.

#if DM_VERSION > 514
/// TRUE if the current path is abstract. See __DEFINES\abstract.dm for more information.
/// Instantiating abstract paths is illegal.
#define isabstract(foo) (initial(foo.type) == initial(foo.abstract_type))
#else
/// TRUE if the current path is abstract. See __DEFINES\abstract.dm for more information.
/// Instantiating abstract paths is illegal.
#define isabstract(foo) (ispath(foo) ? foo == initial(foo.abstract_type) : foo.type == foo.abstract_type)
#endif
2 changes: 1 addition & 1 deletion code/__HELPERS/reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@
var/static/list/random_reagents = list()
if(!random_reagents.len)
for(var/datum/reagent/random_candidate as anything in subtypesof(/datum/reagent))
if(!(initial(random_candidate.abstract_type) == random_candidate) && (initial(random_candidate.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED))
if(!(isabstract(random_candidate)) && (initial(random_candidate.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED))
random_reagents += random_candidate
var/picked_reagent = pick(random_reagents)
return picked_reagent
Expand Down
6 changes: 3 additions & 3 deletions code/controllers/appearance_modifier_manager.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ list(
var/list/modnames_by_species = list()

/datum/controller/modmanager/Initialize()
for(var/path as anything in subtypesof(/datum/appearance_modifier))
var/datum/appearance_modifier/mod = new path
if(mod.abstract_type == mod.type)
for(var/datum/path as anything in subtypesof(/datum/appearance_modifier))
if(isabstract(path))
continue
var/datum/appearance_modifier/mod = new path
mod_singletons += mod
mods_by_type[path] = mod
mods_by_name[mod.name] = mod
Expand Down
5 changes: 2 additions & 3 deletions code/controllers/configuration/config_entry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define KEY_MODE_TYPE 1

/datum/config_entry
abstract_type = /datum/config_entry
/// Read-only, this is determined by the last portion of the derived entry type
var/name
/// The configured value for this entry. This shouldn't be initialized in code, instead set default
Expand All @@ -20,8 +21,6 @@
var/deprecated_by
/// The /datum/config_entry type that supercedes this one
var/protection = NONE
/// Do not instantiate if type matches this
var/abstract_type = /datum/config_entry
/// Force validate and set on VV. VAS proccall guard will run regardless.
var/vv_VAS = TRUE
/// Controls if error is thrown when duplicate configuration values for this entry type are encountered
Expand All @@ -30,7 +29,7 @@
var/default_protection

/datum/config_entry/New()
if(type == abstract_type)
if(isabstract(src)) // are we abstract?
CRASH("Abstract config entry [type] instatiated!")
name = lowertext(type2top(type))
default_protection = protection
Expand Down
23 changes: 9 additions & 14 deletions code/controllers/configuration/configuration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,10 @@
var/list/_entries_by_type = list()
entries_by_type = _entries_by_type

for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
var/datum/config_entry/E = I
if(initial(E.abstract_type) == I)
for(var/datum/config_entry/I as anything in typesof(/datum/config_entry)) //typesof is faster in this case
if(isabstract(I))
continue
E = new I
var/datum/config_entry/E = new I
var/esname = E.name
var/datum/config_entry/test = _entries[esname]
if(test)
Expand Down Expand Up @@ -242,25 +241,21 @@
msg = "Edit"
return msg

/datum/controller/configuration/proc/Get(entry_type)
var/datum/config_entry/E = entry_type
var/entry_is_abstract = initial(E.abstract_type) == entry_type
if(entry_is_abstract)
/datum/controller/configuration/proc/Get(datum/config_entry/entry_type)
if(isabstract(entry_type))
CRASH("Tried to retrieve an abstract config_entry: [entry_type]")
E = entries_by_type[entry_type]
var/datum/config_entry/E = entries_by_type[entry_type]
if(!E)
CRASH("Missing config entry for [entry_type]!")
if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
return
return E.config_entry_value

/datum/controller/configuration/proc/Set(entry_type, new_val)
var/datum/config_entry/E = entry_type
var/entry_is_abstract = initial(E.abstract_type) == entry_type
if(entry_is_abstract)
/datum/controller/configuration/proc/Set(datum/config_entry/entry_type, new_val)
if(isabstract(entry_type))
CRASH("Tried to set an abstract config_entry: [entry_type]")
E = entries_by_type[entry_type]
var/datum/config_entry/E = entries_by_type[entry_type]
if(!E)
CRASH("Missing config entry for [entry_type]!")
if((E.protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
Expand Down
7 changes: 3 additions & 4 deletions code/controllers/subsystem/codex.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ SUBSYSTEM_DEF(codex)
trailingLinebreakRegexEnd = regex(@"<\s*\/*\s*br\s*\/*\s*>$", "ig")

// Create general hardcoded entries.
for(var/ctype in subtypesof(/datum/codex_entry))
var/datum/codex_entry/centry = ctype
if(initial(centry.name) && !(initial(centry.abstract_type) == centry))
centry = new centry()
for(var/datum/codex_entry/entry as anything in subtypesof(/datum/codex_entry))
if(initial(entry.name) && !(isabstract(entry)))
entry = new entry()

// Create categorized entries.
var/list/deferred_population = list()
Expand Down
7 changes: 3 additions & 4 deletions code/controllers/subsystem/processing/instruments.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
songs -= S

/datum/controller/subsystem/processing/instruments/proc/initialize_instrument_data()
for(var/path in subtypesof(/datum/instrument))
var/datum/instrument/I = path
if(initial(I.abstract_type) == path)
for(var/datum/instrument/I in subtypesof(/datum/instrument))
if(isabstract(I))
continue
I = new path
I = new
I.Initialize()
if(!I.id)
qdel(I)
Expand Down
6 changes: 6 additions & 0 deletions code/datums/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
*/
var/list/cooldowns

// Abstract types are expanded upon more in __DEFINES\abstract.dm
/// If this var's value is equivalent to the current type, it is considered abstract.
/// It is illegal to instantiate abstract types.
var/datum/abstract_type = /datum


#ifdef REFERENCE_TRACKING
var/running_find_references
var/last_find_references = 0
Expand Down
2 changes: 1 addition & 1 deletion code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@
break
if (!ispath(text2path(chosen_id)))
chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent)))
if (ispath(chosen_id) && initial(chosen_id.abstract_type) != chosen_id)
if (ispath(chosen_id) && !isabstract(chosen_id))
valid_id = TRUE
else
valid_id = TRUE
Expand Down
2 changes: 1 addition & 1 deletion code/modules/antagonists/traitor/objective_category.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
qdel(category)

/datum/traitor_category_handler/proc/objective_valid(datum/traitor_objective/objective_path, progression_points)
if(initial(objective_path.abstract_type) == objective_path)
if(isabstract(objective_path))
return FALSE
if(progression_points < initial(objective_path.progression_minimum))
return FALSE
Expand Down
3 changes: 1 addition & 2 deletions code/modules/antagonists/traitor/traitor_objective.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/// If a traitor objective needs to be removed from the failed/completed objective list of their handler, then you are doing something wrong
/// and you should reconsider. When an objective is failed/completed, that is final and the only way you can change that is by refactoring the code.
/datum/traitor_objective
abstract_type = /datum/traitor_objective
/// The name of the traitor objective
var/name = "traitor objective"
/// The description of the traitor objective
Expand Down Expand Up @@ -42,8 +43,6 @@
var/progression_cost_coeff = 0
/// The percentage that this objective has been increased or decreased by as a result of progression. Used by the UI
var/original_progression = 0
/// Abstract type that won't be included as a possible objective
var/abstract_type = /datum/traitor_objective

/// Returns a list of variables that can be changed by config, allows for balance through configuration.
/// It is not recommended to finetweak any values of objectives on your server.
Expand Down
2 changes: 1 addition & 1 deletion code/modules/appearance_modifier/appearance_modifier.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
var/name = "You shouldn't see this!"

///If you don't want an appearance mod to be usable, use this.
var/abstract_type = /datum/appearance_modifier
abstract_type = /datum/appearance_modifier
///The icon that gets blended onto the base appearance. Generated in new()
var/icon/my_icon = null
var/icon2use = ""
Expand Down
13 changes: 8 additions & 5 deletions code/modules/art/statues.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
material_modifier = 0.5
material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
abstract_type = /obj/structure/statue
/// Beauty component mood modifier
var/impressiveness = 15
/// Art component subtype added to this statue
var/art_type = /datum/element/art
/// Abstract root type
var/abstract_type = /obj/structure/statue
/// Can this statue be created by hand?
var/can_be_carved = TRUE

/obj/structure/statue/Initialize(mapload)
. = ..()
Expand Down Expand Up @@ -246,7 +247,7 @@
custom_materials = list(/datum/material/metalhydrogen = MINERAL_MATERIAL_AMOUNT*10)
max_integrity = 1000
impressiveness = 100
abstract_type = /obj/structure/statue/elder_atmosian //This one is uncarvable
can_be_carved = FALSE //Created by a crafting recipe instead of the standard system.

/obj/item/chisel
name = "chisel"
Expand Down Expand Up @@ -496,9 +497,11 @@ Moving interrupts

/obj/structure/carving_block/proc/build_statue_cost_table()
. = list()
for(var/statue_type in subtypesof(/obj/structure/statue) - /obj/structure/statue/custom)
for(var/obj/structure/statue/statue_type as anything in subtypesof(/obj/structure/statue) - /obj/structure/statue/custom)
if(isabstract(statue_type))
continue
var/obj/structure/statue/S = new statue_type()
if(!S.icon_state || S.abstract_type == S.type || !S.custom_materials)
if(!S.icon_state || !S.can_be_carved || !S.custom_materials)
continue
.[S.type] = S.custom_materials
qdel(S)
Expand Down
10 changes: 4 additions & 6 deletions code/modules/client/preferences/_preference.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@ GLOBAL_LIST_INIT(all_pref_groups, init_all_pref_groups())
/proc/init_preference_entries()
var/list/output = list()
for (var/datum/preference/preference_type as anything in subtypesof(/datum/preference))
if (initial(preference_type.abstract_type) == preference_type)
if (isabstract(preference_type))
continue
output[preference_type] = new preference_type
return output

/proc/init_preference_entries_by_key()
var/list/output = list()
for (var/datum/preference/preference_type as anything in subtypesof(/datum/preference))
if (initial(preference_type.abstract_type) == preference_type)
if (isabstract(preference_type))
continue
output[initial(preference_type.savefile_key)] = GLOB.preference_entries[preference_type]
return output

/proc/init_all_pref_groups()
. = list()
for(var/datum/preference_group/module as anything in typesof(/datum/preference_group))
if(initial(module.abstract_type) == module)
if(isabstract(module))
continue

. += new module()
Expand Down Expand Up @@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(all_pref_groups, init_all_pref_groups())

/// Represents an individual preference.
/datum/preference
abstract_type = /datum/preference
/// The display default name when inserted into the chargen
var/explanation = "ERROR"

Expand All @@ -99,9 +100,6 @@ GLOBAL_LIST_INIT(all_pref_groups, init_all_pref_groups())
/// It is up to the PreferencesMenu UI itself to interpret it.
var/category = "misc"

/// Do not instantiate if type matches this.
var/abstract_type = /datum/preference

/// What savefile should this preference be read from?
/// Valid values are PREFERENCE_CHARACTER and PREFERENCE_PLAYER.
/// See the documentation in [code/__DEFINES/preferences.dm].
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/datum/preference_group
abstract_type = /datum/preference_group
var/name = ""
/// Sort priority in the UI. Used to do things like place general before other categories.
var/priority = 1

var/abstract_type = /datum/preference_group


///Return a list of html data to be joined into a string
Expand Down
4 changes: 2 additions & 2 deletions code/modules/client/preferences/species_features/basic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@
return islist(value) && value.len == 3 && (findtext(value[1], GLOB.is_color) && findtext(value[2], GLOB.is_color) && findtext(value[3], GLOB.is_color))

/datum/preference/tri_color/apply_to_human(mob/living/carbon/human/target, value)
if (type == abstract_type)
return ..()
if (isabstract(src))
CRASH("`apply_to_human()` was called for abstract preference [type]")

target.dna.mutant_colors["[color_key]_1"] = sanitize_hexcolor(value[1])
target.dna.mutant_colors["[color_key]_2"] = sanitize_hexcolor(value[2])
Expand Down
4 changes: 2 additions & 2 deletions code/modules/codex/entries/_codex_entry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
var/disambiguator
var/list/categories

///Allows you to mark a type as "abstract" and to not generate it.
var/abstract_type
//Codex entries support abstract_type.
//Since the basetype is used for dynamically generated entries, it is not abstract.

/datum/codex_entry/New(_display_name, list/_associated_paths, list/_associated_strings, _lore_text, _mechanics_text, _antag_text, _controls_text, _disambiguator)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Exploration event
/datum/exploration_event
/// These types will be ignored in event creation
var/root_abstract_type = /datum/exploration_event
abstract_type = /datum/exploration_event
///This name will show up in exploration list if it's repeatable
var/name = "Something interesting"
/// encountered at least once
Expand Down Expand Up @@ -40,7 +40,7 @@

/// Simple events, not a full fledged adventure, consist only of single encounter screen
/datum/exploration_event/simple
root_abstract_type = /datum/exploration_event/simple
abstract_type = /datum/exploration_event/simple
var/ui_image = "default"
/// Show ignore button.
var/skippable = TRUE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/datum/exploration_event/adventure
discovery_log = "Encountered something unexpected"
var/datum/adventure/adventure
root_abstract_type = /datum/exploration_event/adventure
abstract_type = /datum/exploration_event/adventure

/datum/exploration_event/adventure/encounter(obj/item/exodrone/drone)
. = ..()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/explorer_drone/exploration_events/danger.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Danger event - unskippable, if you have appriopriate tool you can mitigate damage.
/datum/exploration_event/simple/danger
root_abstract_type = /datum/exploration_event/simple/danger
abstract_type = /datum/exploration_event/simple/danger
description = "You encounter a giant error."
var/required_tool = EXODRONE_TOOL_LASER
var/has_tool_action_text = "Fight"
Expand Down
2 changes: 1 addition & 1 deletion code/modules/explorer_drone/exploration_events/resource.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Simple event type that checks if you have a tool and after a retrieval delay adds loot to drone.
/datum/exploration_event/simple/resource
name = "Retrievable resource"
root_abstract_type = /datum/exploration_event/simple/resource
abstract_type = /datum/exploration_event/simple/resource
discovery_log = "Encountered recoverable resource"
action_text = "Extract"
/// Tool type required to recover this resource
Expand Down
2 changes: 1 addition & 1 deletion code/modules/explorer_drone/exploration_events/trader.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Trader events - If drone is loaded with X exchanges it for Y, might require translator tool.
/datum/exploration_event/simple/trader
root_abstract_type = /datum/exploration_event/simple/trader
abstract_type = /datum/exploration_event/simple/trader
action_text = "Trade"
/// Obj path we'll take or list of paths ,one path will be picked from it at init
var/required_path
Expand Down
7 changes: 3 additions & 4 deletions code/modules/explorer_drone/exploration_site.dm
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,10 @@ GLOBAL_LIST_EMPTY(exploration_sites)

/datum/exploration_site/proc/build_exploration_event_requirements_cache()
. = list()
for(var/event_type in subtypesof(/datum/exploration_event))
var/datum/exploration_event/event = event_type
if(initial(event.root_abstract_type) == event_type)
for(var/datum/exploration_event/event_type as anything in subtypesof(/datum/exploration_event))
if(isabstract(event_type))
continue
event = new event_type
var/datum/exploration_event/event = new event_type
.[event_type] = list("required" = event.required_site_traits,"blacklisted" = event.blacklisted_site_traits)
//Should be no event refs,GC'd naturally

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
/// Category
var/category = "Unsorted"
/// Used for categorization subtypes
var/abstract_type = /datum/instrument
abstract_type = /datum/instrument
/// Write here however many samples, follow this syntax: "%note num%"='%sample file%' eg. "27"='synthesizer/e2.ogg'. Key must never be lower than 0 and higher than 127
var/list/real_samples
/// assoc list key = /datum/instrument_key. do not fill this yourself!
Expand Down
2 changes: 1 addition & 1 deletion code/modules/reagents/chemistry/holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
var/paths = subtypesof(/datum/reagent)

for(var/datum/reagent/path as anything in paths)
if(initial(path.abstract_type) == path)//Are we abstract?
if(isabstract(path))//Are we abstract?
continue
var/datum/reagent/D = new path()
D.mass = rand(10, 800) //This is terrible and should be removed ASAP!
Expand Down
Loading

0 comments on commit 579267d

Please sign in to comment.