Skip to content

Commit 8402a43

Browse files
authored
refactors suit storage allowed + new vv bitfield system (#7381)
1 parent 5f16804 commit 8402a43

File tree

170 files changed

+447
-679
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+447
-679
lines changed

citadel.dme

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "code\_macros.dm"
2121
#include "code\global.dm"
2222
#include "code\__DEFINES\_atoms.dm"
23+
#include "code\__DEFINES\_bitfields-legacy.dm"
2324
#include "code\__DEFINES\_bitfields.dm"
2425
#include "code\__DEFINES\_cooldowns.dm"
2526
#include "code\__DEFINES\_core.dm"
@@ -38,7 +39,6 @@
3839
#include "code\__DEFINES\assert.dm"
3940
#include "code\__DEFINES\automata.dm"
4041
#include "code\__DEFINES\belly_modes_vr.dm"
41-
#include "code\__DEFINES\bitflags.dm"
4242
#include "code\__DEFINES\bodypart_behaviour_flags.dm"
4343
#include "code\__DEFINES\bound_proc.dm"
4444
#include "code\__DEFINES\callbacks.dm"
@@ -433,6 +433,7 @@
433433
#include "code\__HELPERS\visual_effects.dm"
434434
#include "code\__HELPERS\animations\attack.dm"
435435
#include "code\__HELPERS\color\decode.dm"
436+
#include "code\__HELPERS\datastructs\bitfields.dm"
436437
#include "code\__HELPERS\datastructs\bodytypes.dm"
437438
#include "code\__HELPERS\datastructs\filters.dm"
438439
#include "code\__HELPERS\datastructs\ingredients.dm"
@@ -510,7 +511,7 @@
510511
#include "code\__HELPERS\vfx\flick.dm"
511512
#include "code\__HELPERS\vfx\see_anywhere.dm"
512513
#include "code\__HELPERS\vfx\shake_camera.dm"
513-
#include "code\_globals\bitfields.dm"
514+
#include "code\_globals\bitfield_legacy.dm"
514515
#include "code\_globals\configuration.dm"
515516
#include "code\_globals\debug.dm"
516517
#include "code\_globals\loadout.dm"
@@ -3024,7 +3025,6 @@
30243025
#include "code\modules\examine\descriptions\mecha.dm"
30253026
#include "code\modules\examine\descriptions\medical.dm"
30263027
#include "code\modules\examine\descriptions\mobs.dm"
3027-
#include "code\modules\examine\descriptions\paperwork.dm"
30283028
#include "code\modules\examine\descriptions\smokeables.dm"
30293029
#include "code\modules\examine\descriptions\stacks.dm"
30303030
#include "code\modules\examine\descriptions\structures.dm"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// todo: get rid of this and make it like DEFINE_ENUM
2+
#define DEFINE_BITFIELD(v, f) /datum/bitfield_legacy/single/##v { \
3+
flags = ##f; \
4+
variable = #v; \
5+
}
6+
7+
// todo: get rid of this and make it like DEFINE_ENUM
8+
#define DEFINE_SHARED_BITFIELD(n, v, f) /datum/bitfield_legacy/multi/##n { \
9+
flags = ##f; \
10+
variables = ##v; \
11+
}
12+
13+
// todo: get rid of this, rename BITFIELD_NAMED to this
14+
#define BITFIELD(thing) #thing = thing
15+
#define BITFIELD_NAMED(name, thing) name = thing
16+
17+
// todo: impl
18+
/// KEY: must be unique, may be arbitrary; not a string, as it's used in typepath generation
19+
/// CONSTRAINTS: list(/type = list(varname, ...), ...)
20+
/// BITFIELDS: list of BITFIELD_NEW().
21+
#define DEFINE_BITFIELD_NEW(KEY, CONSTRAINTS, BITFIELDS)

code/__DEFINES/_bitfields.dm

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1-
// todo: get rid of this and make it like DEFINE_ENUM
2-
#define DEFINE_BITFIELD(v, f) /datum/bitfield/single/##v { \
3-
flags = ##f; \
4-
variable = #v; \
5-
}
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
63

7-
// todo: get rid of this and make it like DEFINE_ENUM
8-
#define DEFINE_SHARED_BITFIELD(n, v, f) /datum/bitfield/multi/##n { \
9-
flags = ##f; \
10-
variables = ##v; \
4+
/**
5+
* * `ID` must be unique and in `snake_case`
6+
* * `BIT_TO_NAME` should be an list() with `BITFIELD_NEW()`'s inside it.
7+
*/
8+
#define DECLARE_BITFIELD(ID, BIT_TO_NAME); \
9+
/datum/bitfield/##ID/get_bit_constants() { \
10+
return BIT_TO_NAME; \
1111
}
1212

13-
// todo: get rid of this, rename BITFIELD_NAMED to this
14-
#define BITFIELD(thing) #thing = thing
15-
#define BITFIELD_NAMED(name, thing) name = thing
16-
17-
// todo: impl
18-
/// KEY: must be unique, may be arbitrary; not a string, as it's used in typepath generation
19-
/// CONSTRAINTS: list(/type = list(varname, ...), ...)
20-
/// BITFIELDS: list of BITFIELD_NEW().
21-
#define DEFINE_BITFIELD_NEW(KEY, CONSTRAINTS, BITFIELDS)
22-
// todo: impl
2313
/// NAME: must be a string
2414
/// VALUE: the actual enum value, whatever it is
25-
#define BITFIELD_NEW(NAME, VALUE) ##NAME = ##VALUE
15+
#define BITFIELD_NEW(NAME, VALUE) #NAME = ##VALUE
16+
17+
/**
18+
* * `ID` the same in `DECLARE_BITFIELD`
19+
* * `PATH` is `/your/path/whatever` (example)
20+
* * `VARNAME` is without quotes. This allows us to compile-time check it.
21+
*
22+
* CAVEATS:
23+
* * Performance of bitfield reflection is heavily dependent on how many things share the same variable
24+
* name. Please ensure all bitfields are called distinct names, including across different paths.
25+
*/
26+
#define ASSIGN_BITFIELD(ID, PATH, VARNAME) \
27+
/datum/bitfield/##ID/New() { \
28+
..(); \
29+
if(paths[PATH]) { \
30+
paths[PATH] += NAMEOF_TYPE(PATH, VARNAME); \
31+
} \
32+
else { \
33+
paths[PATH] = list(NAMEOF_TYPE(PATH, VARNAME)); \
34+
} \
35+
}
36+

code/__DEFINES/_lists.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
};\
160160
} while(FALSE)
161161

162-
#define islist(L) istype(L, /list)
162+
#define isalist(L) istype(L, /alist)
163163

164164
#define VARSET_FROM_LIST(L, V) if(L && L[#V]) V = L[#V]
165165
#define VARSET_FROM_LIST_IF(L, V, C...) if(L && L[#V] && (C)) V = L[#V]

code/__DEFINES/bitflags.dm

Lines changed: 0 additions & 3 deletions
This file was deleted.

code/__DEFINES/inventory/misc.dm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
14
// proc: dropped() on /obj/item
25
// todo: this should be in procs.dm and the names need to be changed probably
36
// todo: comsig instead?
47
/// relocated; return false
58
#define ITEM_RELOCATED_BY_DROPPED -1
9+
10+
//* Item `suit_storage_class` defines *//
11+
12+
#define SUIT_STORAGE_CLASS_HARDWEAR (1<<0)
13+
#define SUIT_STORAGE_CLASS_SOFTWEAR (1<<1)
14+
#define SUIT_STORAGE_CLASS_ARMOR (1<<2)
15+
16+
DECLARE_BITFIELD(suit_storage_class, list(
17+
BITFIELD_NEW("Hardwear", SUIT_STORAGE_CLASS_HARDWEAR),
18+
BITFIELD_NEW("Softwear", SUIT_STORAGE_CLASS_SOFTWEAR),
19+
BITFIELD_NEW("Armor", SUIT_STORAGE_CLASS_ARMOR),
20+
))
21+
ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class)
22+
ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_allow)
23+
ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_disallow)

code/__DEFINES/vv.dm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#define VV_TYPE "Custom Typepath"
1212
#define VV_FILE "File"
1313
#define VV_LIST "List"
14+
#define VV_ALIST "A-List"
1415
#define VV_NEW_ATOM "New Atom"
1516
#define VV_NEW_DATUM "New Datum"
1617
#define VV_NEW_TYPE "New Custom Typepath"
1718
#define VV_NEW_LIST "New List"
19+
#define VV_NEW_ALIST "New A-List"
1820
#define VV_NULL "NULL"
1921
#define VV_RESTORE_DEFAULT "Restore to Default"
2022
#define VV_MARKED_DATUM "Marked Datum"
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
2+
//* This file is explicitly licensed under the MIT license. *//
3+
//* Copyright (c) 2025 Citadel Station Developers *//
4+
5+
/**
6+
* All bitfield datums
7+
*/
8+
GLOBAL_LIST(bitfields)
9+
/**
10+
* All bitfield datums by path
11+
*/
12+
GLOBAL_LIST(bitfields_by_path)
13+
/**
14+
* All bitfield datums by var name
15+
*/
16+
GLOBAL_LIST(bitfields_by_var)
17+
18+
// TODO: why don't we just tgui picker bitfields so we don't need to do insane lookups?
19+
/proc/init_bitfield_meta()
20+
// TODO: GLOBAL_ALIST
21+
var/list/bitfields = list()
22+
var/list/bitfield_by_path = list()
23+
var/list/bitfield_by_var = list()
24+
25+
for(var/datum/bitfield/path as anything in subtypesof(/datum/bitfield))
26+
if(path.abstract_type == path)
27+
continue
28+
var/datum/bitfield/instance = new path
29+
bitfields += instance
30+
// add legacy shit
31+
var/list/legacy_bitfields = generate_bitfields()
32+
for(var/var_name in legacy_bitfields)
33+
var/list/reverse_lookup = legacy_bitfields[var_name]
34+
var/datum/bitfield/legacy_instance = new
35+
for(var/name in reverse_lookup)
36+
var/bit = reverse_lookup[name]
37+
legacy_instance.names += name
38+
legacy_instance.bits += bit
39+
legacy_instance.paths = list((/datum) = var_name)
40+
bitfields += legacy_instance
41+
for(var/datum/bitfield/bitfield as anything in bitfields)
42+
for(var/path in bitfield.paths)
43+
if(!bitfield_by_path[path])
44+
bitfield_by_path[path] = list(bitfield)
45+
else
46+
bitfield_by_path[path] += bitfield
47+
var/list/name_or_names = bitfield.paths[path]
48+
if(islist(name_or_names))
49+
for(var/name in name_or_names)
50+
if(!bitfield_by_var[name])
51+
bitfield_by_var[name] = list(bitfield)
52+
else
53+
bitfield_by_var[name] += bitfield
54+
else if(name_or_names)
55+
if(!bitfield_by_var[name_or_names])
56+
bitfield_by_var[name_or_names] = list(bitfield)
57+
else
58+
bitfield_by_var[name_or_names] += bitfield
59+
else
60+
STACK_TRACE("Bitfield [bitfield.type] ([json_encode(bitfield.names)]) had no var name on path [path]")
61+
62+
GLOB.bitfields = bitfields
63+
GLOB.bitfields_by_path = bitfield_by_path
64+
GLOB.bitfields_by_var = bitfield_by_var
65+
66+
#if DM_VERSION > 516
67+
#error remove the guards on path == /datum; byond will have fixed the crash bug by now
68+
#endif
69+
70+
/proc/fetch_all_bitfields(datum/path)
71+
. = list()
72+
do
73+
var/list/maybe_bitfields = GLOB.bitfields_by_path[path]
74+
if(maybe_bitfields)
75+
. += maybe_bitfields
76+
if(path == /datum)
77+
break
78+
path = path.parent_type
79+
while(path)
80+
81+
/proc/fetch_bitfield(datum/path, var_name) as /datum/bitfield
82+
if(istype(path))
83+
path = path.type
84+
for(var/datum/bitfield/bitfield as anything in GLOB.bitfields_by_var[var_name])
85+
for(var/match in bitfield.paths)
86+
if(ispath(path, match))
87+
return bitfield
88+
89+
/**
90+
* Bitfield datums used to reflect bitfield values in the game's code.
91+
*/
92+
/datum/bitfield
93+
abstract_type = /datum/bitfield
94+
/// typepaths this is valid on associated to variable or list of variables
95+
var/list/paths = list()
96+
var/list/bits
97+
var/list/names
98+
99+
/datum/bitfield/New()
100+
var/list/constants = get_bit_constants()
101+
bits = list()
102+
names = list()
103+
for(var/name in constants)
104+
var/bit = constants[name]
105+
bits += bit
106+
names += name
107+
108+
/datum/bitfield/proc/get_bit_name(bit)
109+
. = bits.Find(bit)
110+
return . ? names[.] : null
111+
112+
/datum/bitfield/proc/get_bit(name)
113+
. = names.Find(name)
114+
return . ? bits[.] : null
115+
116+
/**
117+
* This is NOT necessarily the number of bits in the bitfield. This is only how many of them
118+
* were declared in ourselves. Please be careful when using this;
119+
*/
120+
/datum/bitfield/proc/get_declared_count()
121+
return length(bits)
122+
123+
/**
124+
* @return list(NAME = BIT, ...)
125+
*/
126+
/datum/bitfield/proc/get_bit_constants()
127+
return list()
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1-
GLOBAL_LIST_INIT(bitfields, generate_bitfields())
2-
3-
/datum/bitfield
1+
/datum/bitfield_legacy
42
/// An associative list of the readable flag and its true value
53
var/list/flags
64

7-
/datum/bitfield/single
5+
/datum/bitfield_legacy/single
86
/// The variable name that contains the bitfield
97
var/variable
108

11-
/datum/bitfield/multi
9+
/datum/bitfield_legacy/multi
1210
/// our variable names
1311
var/list/variables
1412

15-
/// Turns /datum/bitfield subtypes into a list for use in debugging
13+
/// Turns /datum/bitfield_legacy subtypes into a list for use in debugging
1614
/proc/generate_bitfields()
1715
var/list/bitfields = list()
18-
for (var/_bitfield in subtypesof(/datum/bitfield/single))
19-
var/datum/bitfield/single/bitfield = new _bitfield
16+
for (var/_bitfield in subtypesof(/datum/bitfield_legacy/single))
17+
var/datum/bitfield_legacy/single/bitfield = new _bitfield
2018
bitfields[bitfield.variable] = bitfield.flags
21-
for (var/_bitfield in subtypesof(/datum/bitfield/multi))
22-
var/datum/bitfield/multi/bitfield = new _bitfield
19+
for (var/_bitfield in subtypesof(/datum/bitfield_legacy/multi))
20+
var/datum/bitfield_legacy/multi/bitfield = new _bitfield
2321
for(var/n in bitfield.variables)
2422
bitfields[n] = bitfield.flags
2523
// sue me i haven't slept in 18 hours

code/controllers/configuration/entries/game.dm

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,9 @@
9292
. = ..()
9393
if(!.)
9494
return
95-
var/datum/bitfield/single/target_bitfield = /datum/bitfield/single/nightshift_level
96-
var/target_bitname = initial(target_bitfield.variable)
97-
var/list/actual_bitfield = GLOB.bitfields[target_bitname]
95+
var/datum/bitfield_legacy/single/target_bitfield = new /datum/bitfield_legacy/single/nightshift_level
9896
var/new_flags = NONE
9997
for(var/key in config_entry_value)
10098
if(config_entry_value[key])
101-
new_flags |= actual_bitfield[key]
99+
new_flags |= target_bitfield.flags[key]
102100
SSnightshift.nightshift_level = new_flags

0 commit comments

Comments
 (0)