Merge pull request #4480 from Citadel-Station-13/upstream-merge-33550

[MIRROR] Adds instanceless component dupe mode
This commit is contained in:
LetterJay
2017-12-21 04:58:20 -06:00
committed by GitHub
5 changed files with 76 additions and 56 deletions

View File

@@ -6,9 +6,10 @@
// How multiple components of the exact same type are handled in the same datum
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new
// All signals. Format:
// When the signal is called: (signal arguments)

View File

@@ -40,6 +40,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
* `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added
* `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it
* `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component.
1. `/datum/component/var/dupe_type` (protected, type)
* Definition of a duplicate component type
* `null` means exact match on `type` (default)
@@ -66,6 +67,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* All components a datum owns are deleted with 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
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
@@ -104,9 +106,8 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* Allows the component to react to ownership transfers
1. `/datum/component/proc/_RemoveFromParent()` (private, final)
* Clears `parent` and removes the component from it's component list
1. `/datum/component/proc/_CheckDupesAndJoinParent` (private, final)
1. `/datum/component/proc/_JoinParent` (private, final)
* Tries to add the component to it's `parent`s `datum_components` list
* Properly handles duplicate situations based on the `dupe_mode` var
1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
* Makes a component listen for the specified `signal` on it's `parent` datum.

View File

@@ -6,54 +6,16 @@
var/datum/parent
/datum/component/New(datum/P, ...)
if(type == /datum/component)
qdel(src)
CRASH("[type] instantiated!")
//check for common mishaps
if(!isnum(dupe_mode))
qdel(src)
CRASH("[type]: Invalid dupe_mode!")
var/dt = dupe_type
if(dt && !ispath(dt))
qdel(src)
CRASH("[type]: Invalid dupe_type!")
parent = P
var/list/arguments = args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE)
return
_CheckDupesAndJoinParent(P)
_JoinParent(P)
/datum/component/proc/_CheckDupesAndJoinParent()
/datum/component/proc/_JoinParent()
var/datum/P = parent
var/dm = dupe_mode
var/datum/component/old
if(dm != COMPONENT_DUPE_ALLOWED)
var/dt = dupe_type
if(!dt)
old = P.GetExactComponent(type)
else
old = P.GetComponent(dt)
if(old)
//One or the other has to die
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
old.InheritComponent(src, TRUE)
qdel(src, TRUE, TRUE)
return
if(COMPONENT_DUPE_HIGHLANDER)
InheritComponent(old, FALSE)
qdel(old, FALSE, TRUE)
//provided we didn't eat someone
if(!old)
//let the others know
P.SendSignal(COMSIG_COMPONENT_ADDED, src)
//lazy init the parent's dc list
var/list/dc = P.datum_components
if(!dc)
@@ -212,10 +174,59 @@
return list(.)
/datum/proc/AddComponent(new_type, ...)
var/nt = new_type
var/datum/component/nt = new_type
var/dm = initial(nt.dupe_mode)
var/dt = initial(nt.dupe_type)
var/datum/component/old_comp
var/datum/component/new_comp
if(ispath(nt))
if(nt == /datum/component)
CRASH("[nt] attempted instantiation!")
if(!isnum(dm))
CRASH("[nt]: Invalid dupe_mode ([dm])!")
if(dt && !ispath(dt))
CRASH("[nt]: Invalid dupe_type ([dt])!")
else
new_comp = nt
args[1] = src
var/datum/component/C = new nt(arglist(args))
return QDELING(C) ? GetExactComponent(new_type) : C
if(dm != COMPONENT_DUPE_ALLOWED)
if(!dt)
old_comp = GetExactComponent(nt)
else
old_comp = GetComponent(dt)
if(old_comp)
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
if(!new_comp)
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
qdel(new_comp)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
qdel(old_comp)
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
var/list/arguments = args.Copy(2)
old_comp.InheritComponent(null, TRUE, arguments)
else
old_comp.InheritComponent(new_comp, TRUE)
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
else if(!new_comp)
new_comp = new nt(arglist(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
SendSignal(COMSIG_COMPONENT_ADDED, new_comp)
return new_comp
return old_comp
/datum/proc/LoadComponent(component_type, ...)
. = GetComponent(component_type)
@@ -235,7 +246,8 @@
C._RemoveFromParent()
helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C)
C.parent = src
C._CheckDupesAndJoinParent()
if(C == AddComponent(C))
C._JoinParent()
/datum/proc/TransferComponents(datum/target)
var/list/dc = datum_components

View File

@@ -4,7 +4,7 @@
#define RAD_AMOUNT_EXTREME 1000
/datum/component/radioactive
dupe_mode = COMPONENT_DUPE_UNIQUE
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/source
@@ -47,13 +47,16 @@
if(strength <= RAD_BACKGROUND_RADIATION)
return PROCESS_KILL
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original)
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments)
if(!i_am_original)
return
if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger
return
var/datum/component/radioactive/other = C
strength = max(strength, other.strength)
if(C)
var/datum/component/radioactive/other = C
strength = max(strength, other.strength)
else
strength = max(strength, arguments[1])
/datum/component/radioactive/proc/rad_examine(mob/user, atom/thing)
var/atom/master = parent

View File

@@ -1,5 +1,5 @@
/datum/component/thermite
dupe_mode = COMPONENT_DUPE_UNIQUE
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/amount
var/overlay
@@ -46,10 +46,13 @@
master.cut_overlay(overlay)
return ..()
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original)
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, list/arguments)
if(!i_am_original)
return
amount += newC.amount
if(newC)
amount += newC.amount
else
amount += arguments[1]
/datum/component/thermite/proc/thermite_melt(mob/user)
var/turf/master = parent