Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supports named arguments in AddComponent and AddElemen #12880

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@

# ninjanomnom

/code/__DEFINES/dcs/ @ninjanomnom
/code/controllers/subsystem/dcs.dm @ninjanomnom
/code/controllers/subsystem/shuttle.dm @ninjanomnom
/code/datums/components/ @ninjanomnom
/code/datums/elements/ @ninjanomnom
/code/modules/shuttle/ @ninjanomnom

# ShizCalev
Expand All @@ -80,6 +84,7 @@

# Multiple Owners

/code/__DEFINES/components.dm @Cyberboss @ninjanomnom
/code/controllers/subsystem/air.dm @duncathan @MrStonedOne
/code/datums/components/ @Cyberboss @ninjanomnom

#SIC SEMPER TYRANNIS
/code/modules/hydroponics/grown/citrus.dm @optimumtact
9 changes: 3 additions & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
"./tgui-next"
],

"workbench.editorAssociations": [
{
"filenamePattern": "*.dmi",
"viewType": "imagePreview.previewEditor"
}
]
"workbench.editorAssociations": {
"*.dmi": "imagePreview.previewEditor"
}
}
365 changes: 0 additions & 365 deletions code/__DEFINES/components.dm

This file was deleted.

41 changes: 41 additions & 0 deletions code/__DEFINES/dcs/flags.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type.
/// `parent` must not be modified if this is to be returned.
/// This will be noted in the runtime logs
#define COMPONENT_INCOMPATIBLE 1
/// Returned in PostTransfer to prevent transfer, similar to `COMPONENT_INCOMPATIBLE`
#define COMPONENT_NOTRANSFER 2

/// Return value to cancel attaching
#define ELEMENT_INCOMPATIBLE 1

// /datum/element flags
/// Causes the detach proc to be called when the host object is being deleted
#define ELEMENT_DETACH (1 << 0)
/**
* Only elements created with the same arguments given after `id_arg_index` share an element instance
* The arguments are the same when the text and number values are the same and all other values have the same ref
*/
#define ELEMENT_BESPOKE (1 << 1)

// How multiple components of the exact same type are handled in the same datum
/// old component is deleted (default)
#define COMPONENT_DUPE_HIGHLANDER 0
/// duplicates allowed
#define COMPONENT_DUPE_ALLOWED 1
/// new component is deleted
#define COMPONENT_DUPE_UNIQUE 2
/// old component is given the initialization args of the new
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4
/// each component of the same type is consulted as to whether the duplicate should be allowed
#define COMPONENT_DUPE_SELECTIVE 5

//Redirection component init flags
#define REDIRECT_TRANSFER_WITH_TURF 1

//Arch
#define ARCH_PROB "probability" //Probability for each item
#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount

//Ouch my toes!
#define CALTROP_BYPASS_SHOES 1
#define CALTROP_IGNORE_WALKERS 2
15 changes: 15 additions & 0 deletions code/__DEFINES/dcs/helpers.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// Used to trigger signals and call procs registered for that signal
/// The datum hosting the signal is automaticaly added as the first argument
/// Returns a bitfield gathered from all registered procs
/// Arguments given here are packaged in a list and given to _SendSignal
#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) )

#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )

/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments
#define AddElement(arguments...) _AddElement(list(##arguments))
/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments
#define RemoveElement(arguments...) _RemoveElement(list(##arguments))

/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments
#define AddComponent(arguments...) _AddComponent(list(##arguments))
1,565 changes: 1,565 additions & 0 deletions code/__DEFINES/dcs/signals.dm

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions code/__DEFINES/~hippie_defines/components.dm

This file was deleted.

31 changes: 30 additions & 1 deletion code/__DEFINES/~hippie_defines/material.dm
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
#define MAT_REAGENT "$reagent"
#define MAT_REAGENT "$reagent"

/// Hard materials, such as iron or silver
#define MAT_CATEGORY_RIGID "rigid material"
/// Is the material from an ore? currently unused but exists atm for categorizations sake
#define MAT_CATEGORY_ORE "ore capable"

/// Hard materials, such as iron or silver
#define MAT_CATEGORY_RIGID "rigid material"

/// Materials that can be used to craft items
#define MAT_CATEGORY_ITEM_MATERIAL "item material"

///Use this flag on TRUE if you want the basic recipes
#define MAT_CATEGORY_BASE_RECIPES "basic recipes"

/// Used to make a material initialize at roundstart.
#define MATERIAL_INIT_MAPLOAD (1<<0)
/// Used to make a material type able to be instantiated on demand after roundstart.
#define MATERIAL_INIT_BESPOKE (1<<1)

//Material Container Flags.
///If the container shows the amount of contained materials on examine.
#define MATCONTAINER_EXAMINE (1<<0)
///If the container cannot have materials inserted through attackby().
#define MATCONTAINER_NO_INSERT (1<<1)
///if the user can insert mats into the container despite the intent.
#define MATCONTAINER_ANY_INTENT (1<<2)
///if the user won't receive a warning when attacking the container with an unallowed item.
#define MATCONTAINER_SILENT (1<<3)
47 changes: 42 additions & 5 deletions code/controllers/subsystem/dcs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,47 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
/datum/controller/subsystem/processing/dcs/Recover()
comp_lookup = SSdcs.comp_lookup

/datum/controller/subsystem/processing/dcs/proc/GetElement(eletype)
. = elements_by_type[eletype]
if(.)
return
/datum/controller/subsystem/processing/dcs/proc/GetElement(list/arguments)
var/datum/element/eletype = arguments[1]
var/element_id = eletype

if(!ispath(eletype, /datum/element))
CRASH("Attempted to instantiate [eletype] as a /datum/element")
. = elements_by_type[eletype] = new eletype

if(initial(eletype.element_flags) & ELEMENT_BESPOKE)
element_id = GetIdFromArguments(arguments)

. = elements_by_type[element_id]
if(.)
return
. = elements_by_type[element_id] = new eletype

/****
* Generates an id for bespoke elements when given the argument list
* Generating the id here is a bit complex because we need to support named arguments
* Named arguments can appear in any order and we need them to appear after ordered arguments
* We assume that no one will pass in a named argument with a value of null
**/
/datum/controller/subsystem/processing/dcs/proc/GetIdFromArguments(list/arguments)
var/datum/element/eletype = arguments[1]
var/list/fullid = list("[eletype]")
var/list/named_arguments = list()
for(var/i in initial(eletype.id_arg_index) to length(arguments))
var/key = arguments[i]
var/value
if(istext(key))
value = arguments[key]
if(!(istext(key) || isnum(key)))
key = REF(key)
key = "[key]" // Key is stringified so numbers dont break things
if(!isnull(value))
if(!(istext(value) || isnum(value)))
value = REF(value)
named_arguments["[key]"] = value
else
fullid += "[key]"

if(length(named_arguments))
named_arguments = sortList(named_arguments)
fullid += named_arguments
return list2params(fullid)
69 changes: 52 additions & 17 deletions code/datums/components/_component.dm
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
/datum/component
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER

/// The type to check for duplication
/// `null` means exact match on `type` (default)
/// Any other type means that and all subtypes
var/dupe_type

/// The datum this components belongs to
var/datum/parent
//only set to true if you are able to properly transfer this component
//At a minimum RegisterWithParent and UnregisterFromParent should be used
//Make sure you also implement PostTransfer for any post transfer handling

/// Only set to true if you are able to properly transfer this component
/// At a minimum RegisterWithParent and UnregisterFromParent should be used
/// Make sure you also implement PostTransfer for any post transfer handling
var/can_transfer = FALSE

/datum/component/New(datum/P, ...)
parent = P
var/list/arguments = args.Copy(2)
/**
* Create a new component.
* Additional arguments are passed to `Initialize()`
*
* Arguments:
* * datum/P the parent datum this component reacts to signals from
*/
/datum/component/New(list/raw_args)
parent = raw_args[1]
var/list/arguments = raw_args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE)
CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]")
CRASH("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]")

_JoinParent(P)
_JoinParent(parent)

/datum/component/proc/_JoinParent()
var/datum/P = parent
Expand Down Expand Up @@ -214,7 +228,15 @@
if(!length(.))
return list(.)

/datum/proc/AddComponent(new_type, ...)
/**
* Creates an instance of `new_type` in the datum and attaches to it as parent
* Sends the `COMSIG_COMPONENT_ADDED` signal to the datum
* Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
* If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
* Properly handles duplicate situations based on the `dupe_mode` var
*/
/datum/proc/_AddComponent(list/raw_args)
var/new_type = raw_args[1]
var/datum/component/nt = new_type
var/dm = initial(nt.dupe_mode)
var/dt = initial(nt.dupe_type)
Expand All @@ -229,7 +251,7 @@
new_comp = nt
nt = new_comp.type

args[1] = src
raw_args[1] = src

if(dm != COMPONENT_DUPE_ALLOWED)
if(!dt)
Expand All @@ -240,26 +262,39 @@
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
if(!new_comp)
new_comp = new nt(arglist(args))
new_comp = new nt(raw_args)
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
QDEL_NULL(new_comp)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
new_comp = new nt(arglist(args))
new_comp = new nt(raw_args)
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
QDEL_NULL(old_comp)
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
var/list/arguments = args.Copy(2)
old_comp.InheritComponent(null, TRUE, arguments)
var/list/arguments = raw_args.Copy(2)
arguments.Insert(1, null, TRUE)
old_comp.InheritComponent(arglist(arguments))
else
old_comp.InheritComponent(new_comp, TRUE)
if(COMPONENT_DUPE_SELECTIVE)
var/list/arguments = raw_args.Copy()
arguments[1] = new_comp
var/make_new_component = TRUE
for(var/i in GetComponents(new_type))
var/datum/component/C = i
if(C.CheckDupeComponent(arglist(arguments)))
make_new_component = FALSE
QDEL_NULL(new_comp)
break
if(!new_comp && make_new_component)
new_comp = new nt(raw_args)
else if(!new_comp)
new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal
new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal
else if(!new_comp)
new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal
new_comp = new nt(raw_args) // Dupes are allowed, act like normal

if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy
SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp)
Expand All @@ -269,7 +304,7 @@
/datum/proc/LoadComponent(component_type, ...)
. = GetComponent(component_type)
if(!.)
return AddComponent(arglist(args))
return _AddComponent(args)

/datum/component/proc/RemoveComponent()
if(!parent)
Expand Down
15 changes: 7 additions & 8 deletions code/datums/components/fantasy/_fantasy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,16 @@
/datum/component/fantasy/UnregisterFromParent()
unmodify()

/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments)
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, quality, list/affixes, canFail, announce)
unmodify()
if(newComp)
quality += newComp.quality
canFail = newComp.canFail
announce = newComp.announce
src.quality += newComp.quality
src.canFail = newComp.canFail
src.announce = newComp.announce
else
arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given
quality += arguments[1]
canFail = arguments[4] || canFail
announce = arguments[5] || announce
src.quality += quality
src.canFail = canFail || src.canFail
src.announce = announce || src.announce
modify()

/datum/component/fantasy/proc/randomQuality()
Expand Down
4 changes: 2 additions & 2 deletions code/datums/components/nanites.dm
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@
host_mob = null
return ..()

/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments)
/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, amount, cloud)
if(new_nanites)
adjust_nanites(null, new_nanites.nanite_volume)
else
adjust_nanites(null, arguments[1]) //just add to the nanite volume
adjust_nanites(null, amount) //just add to the nanite volume

/datum/component/nanites/process()
if(!IS_IN_STASIS(host_mob))
Expand Down
6 changes: 3 additions & 3 deletions code/datums/components/orbiter.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
orbiters = null
return ..()

/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
if(arguments)
begin_orbit(arglist(arguments))
/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
if(!newcomp)
begin_orbit(arglist(args.Copy(3)))
return
// The following only happens on component transfers
orbiters += newcomp.orbiters
Expand Down
6 changes: 3 additions & 3 deletions code/datums/components/radioactive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
hl3_release_date = _half_life
can_contaminate = _can_contaminate

if(istype(parent, /atom))
if(istype(parent, /atom))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/rad_examine)
if(istype(parent, /obj/item))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/rad_attack)
Expand Down Expand Up @@ -46,7 +46,7 @@
if(strength <= RAD_BACKGROUND_RADIATION)
return PROCESS_KILL

/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments)
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, _strength, _source, _half_life, _can_contaminate)
if(!i_am_original)
return
if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger
Expand All @@ -55,7 +55,7 @@
var/datum/component/radioactive/other = C
strength = max(strength, other.strength)
else
strength = max(strength, arguments[1])
strength = max(strength, _strength)

/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, atom/thing)
var/atom/master = parent
Expand Down
Loading