Skip to content

Commit 701dc45

Browse files
Merge pull request #5286 from MistakeNot4892/polaris-rebase
Updating Polaris rebase branch from dev.
2 parents 3876fba + 475e522 commit 701dc45

File tree

196 files changed

+2346
-987
lines changed

Some content is hidden

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

196 files changed

+2346
-987
lines changed

code/__defines/machinery.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
7474
#define NETWORK_ALARM_MOTION "Motion Alarms"
7575
#define NETWORK_ALARM_POWER "Power Alarms"
7676

77+
7778
//singularity defines
7879
#define STAGE_ONE 1
7980
#define STAGE_TWO 3

code/__defines/misc.dm

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,29 @@
8787
#define EVENT_LEVEL_MAJOR 3
8888

8989
//Area flags, possibly more to come
90-
#define AREA_FLAG_RAD_SHIELDED BITFLAG(1) // Shielded from radiation, clearly.
91-
#define AREA_FLAG_EXTERNAL BITFLAG(2) // External as in exposed to space, not outside in a nice, green, forest.
92-
#define AREA_FLAG_ION_SHIELDED BITFLAG(3) // Shielded from ionospheric anomalies.
93-
#define AREA_FLAG_IS_NOT_PERSISTENT BITFLAG(4) // SSpersistence will not track values from this area.
94-
#define AREA_FLAG_IS_BACKGROUND BITFLAG(5) // Blueprints can create areas on top of these areas. Cannot edit the name of or delete these areas.
95-
#define AREA_FLAG_MAINTENANCE BITFLAG(6) // Area is a maintenance area.
96-
#define AREA_FLAG_SHUTTLE BITFLAG(7) // Area is a shuttle area.
97-
#define AREA_FLAG_HALLWAY BITFLAG(8) // Area is a public hallway suitable for event selection
98-
#define AREA_FLAG_PRISON BITFLAG(9) // Area is a prison for the purposes of brigging objectives.
99-
#define AREA_FLAG_HOLY BITFLAG(10) // Area is holy for the purposes of marking turfs as cult-resistant.
100-
#define AREA_FLAG_SECURITY BITFLAG(11) // Area is security for the purposes of newscaster init.
101-
#define AREA_FLAG_HIDE_FROM_HOLOMAP BITFLAG(12) // if we shouldn't be drawn on station holomaps
102-
#define AREA_FLAG_IS_STATION_AREA BITFLAG(13) // TODO: Polaris port.
90+
#define AREA_FLAG_RAD_SHIELDED BITFLAG(1) // Shielded from radiation, clearly.
91+
#define AREA_FLAG_EXTERNAL BITFLAG(2) // External as in exposed to space, not outside in a nice, green, forest.
92+
#define AREA_FLAG_ION_SHIELDED BITFLAG(3) // Shielded from ionospheric anomalies.
93+
#define AREA_FLAG_NO_LEGACY_PERSISTENCE BITFLAG(4) // SSpersistence will not track values from this area.
94+
#define AREA_FLAG_IS_BACKGROUND BITFLAG(5) // Blueprints can create areas on top of these areas. Cannot edit the name of or delete these areas.
95+
#define AREA_FLAG_MAINTENANCE BITFLAG(6) // Area is a maintenance area.
96+
#define AREA_FLAG_SHUTTLE BITFLAG(7) // Area is a shuttle area.
97+
#define AREA_FLAG_HALLWAY BITFLAG(8) // Area is a public hallway suitable for event selection
98+
#define AREA_FLAG_PRISON BITFLAG(9) // Area is a prison for the purposes of brigging objectives.
99+
#define AREA_FLAG_HOLY BITFLAG(10) // Area is holy for the purposes of marking turfs as cult-resistant.
100+
#define AREA_FLAG_SECURITY BITFLAG(11) // Area is security for the purposes of newscaster init.
101+
#define AREA_FLAG_HIDE_FROM_HOLOMAP BITFLAG(12) // if we shouldn't be drawn on station holomaps
102+
#define AREA_FLAG_ALLOW_LEVEL_PERSISTENCE BITFLAG(13) // Whether or not this area should pass changed turfs to SSpersistence.
103+
#define AREA_FLAG_IS_STATION_AREA BITFLAG(14) // TODO: Polaris port.
103104

104105
//Map template flags
105-
#define TEMPLATE_FLAG_ALLOW_DUPLICATES BITFLAG(0) // Lets multiple copies of the template to be spawned
106-
#define TEMPLATE_FLAG_SPAWN_GUARANTEED BITFLAG(1) // Makes it ignore away site budget and just spawn (only for away sites)
107-
#define TEMPLATE_FLAG_CLEAR_CONTENTS BITFLAG(2) // if it should destroy objects it spawns on top of
108-
#define TEMPLATE_FLAG_NO_RUINS BITFLAG(3) // if it should forbid ruins from spawning on top of it
109-
#define TEMPLATE_FLAG_NO_RADS BITFLAG(4) // Removes all radiation from the template after spawning.
110-
#define TEMPLATE_FLAG_TEST_DUPLICATES BITFLAG(5) // Makes unit testing attempt to spawn mutliple copies of this template. Assumes unit testing is spawning at least one copy.
111-
#define TEMPLATE_FLAG_GENERIC_REPEATABLE BITFLAG(6) // Template can be picked repeatedly for the same level gen run.
106+
#define TEMPLATE_FLAG_ALLOW_DUPLICATES BITFLAG(0) // Lets multiple copies of the template to be spawned
107+
#define TEMPLATE_FLAG_SPAWN_GUARANTEED BITFLAG(1) // Makes it ignore away site budget and just spawn (only for away sites)
108+
#define TEMPLATE_FLAG_CLEAR_CONTENTS BITFLAG(2) // if it should destroy objects it spawns on top of
109+
#define TEMPLATE_FLAG_NO_RUINS BITFLAG(3) // if it should forbid ruins from spawning on top of it
110+
#define TEMPLATE_FLAG_NO_RADS BITFLAG(4) // Removes all radiation from the template after spawning.
111+
#define TEMPLATE_FLAG_TEST_DUPLICATES BITFLAG(5) // Makes unit testing attempt to spawn mutliple copies of this template. Assumes unit testing is spawning at least one copy.
112+
#define TEMPLATE_FLAG_GENERIC_REPEATABLE BITFLAG(6) // Template can be picked repeatedly for the same level gen run.
112113

113114
// Convoluted setup so defines can be supplied by Bay12 main server compile script.
114115
// Should still work fine for people jamming the icons into their repo.

code/__defines/persistence.dm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Handled elsewhere, do not let them load like vars.
2+
var/global/list/_forbid_field_load = list(
3+
(nameof(/datum::type)) = TRUE,
4+
(nameof(/atom::loc)) = TRUE
5+
)

code/__defines/serde.dm

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#define SERDE_HINT_FINISHED 1
2+
#define SERDE_HINT_POSTINIT 2
3+
4+
#define SERDE_REAGENT_LIST "_reagent_list"
5+
#define SERDE_REAGENT_VOLUME "_reagent_volume"
6+
7+
#define SERIALIZE_VALUE(V, T, VAL) .[nameof(T::V)] = VAL;
8+
#define SERIALIZE(V, T) SERIALIZE_VALUE(V, T, V)
9+
#define SERIALIZE_IF_MODIFIED(V, T) if(V != initial(V)) { SERIALIZE_VALUE(V, T, V) }
10+
#define SERIALIZE_TYPE_IF_MODIFIED(V, T) if(V != initial(V)) { SERIALIZE_VALUE(V, T, "[V]") }
11+
#define SERIALIZE_DECL_IF_MODIFIED(V, T) if((isnull(V) && !isnull(initial(V))) || ((istext(V) || istype(V, /decl) || ispath(V, /decl)) && !DECLS_ARE_EQUIVALENT(V, initial(V)))) { var/decl/__D = RESOLVE_TO_DECL(V); SERIALIZE_VALUE(V, T, __D?.uid) }
12+
#define SERIALIZE_DECL_LIST(V, T) if(islist(V)) { var/list/__decl_uids = list(); for(var/decl/__decl in V) { __decl_uids += __decl.uid }; SERIALIZE_VALUE(V, T, __decl_uids) }
13+
#define SERIALIZE_REAGENTS(V, T, I) if(istype(V, /datum/reagents)) { \
14+
.[I + SERDE_REAGENT_VOLUME] = UNLINT(V.maximum_volume); \
15+
if(UNLINT(V.total_volume)) { \
16+
var/list/__compiled_reagents = list(); \
17+
for(var/decl/material/R in UNLINT(V.liquid_volumes)) { \
18+
__compiled_reagents[++__compiled_reagents.len] = list(R.uid, UNLINT(V.liquid_volumes[R]), (MAT_PHASE_LIQUID)); \
19+
} \
20+
for(var/decl/material/R in UNLINT(V.solid_volumes)) { \
21+
__compiled_reagents[++__compiled_reagents.len] = list(R.uid, UNLINT(V.solid_volumes[R]), (MAT_PHASE_SOLID)); \
22+
} \
23+
.[I + SERDE_REAGENT_LIST] = __compiled_reagents; \
24+
} else { \
25+
.[I + SERDE_REAGENT_LIST] = list(); \
26+
} \
27+
} else { \
28+
.[I + SERDE_REAGENT_LIST] = list(); \
29+
.[I + SERDE_REAGENT_VOLUME] = 0; \
30+
}
31+
32+
#define DESERIALIZE_REAGENTS(V, I) if(((I + SERDE_REAGENT_LIST) in __deserialization_payload) && ((I + SERDE_REAGENT_VOLUME) in __deserialization_payload)) { \
33+
V = list((SERDE_REAGENT_VOLUME) = __deserialization_payload[I + SERDE_REAGENT_VOLUME], (SERDE_REAGENT_LIST) = __deserialization_payload[I + SERDE_REAGENT_LIST]); \
34+
}
35+
36+
#define DESERIALIZE_DECL_TO_TYPE(V) if(istext(V) || ispath(V, /decl) || istype(V, /decl)) { var/decl/__D = RESOLVE_TO_DECL(V); V = __D?.type; } else { V = null; }
37+
#define DESERIALIZE_TYPE(V) if(istext(V)) { V = text2path(V); } else if(!ispath(V)) { V = null; }
38+
#define DESERIALIZE_DECL(V) if(istext(V) || ispath(V)) { V = RESOLVE_TO_DECL(V); } else { V = null; }
39+
40+
// List cast is to avoid OpenDream complaining about V typically being typed as a reagents datum, but holding a list for serde.
41+
#define FINALIZE_REAGENTS_SERDE_BODY(V) try { \
42+
if((SERDE_REAGENT_LIST in V) && (SERDE_REAGENT_VOLUME in V)) { \
43+
var/list/LV = V; \
44+
var/__serde_volume = LV[SERDE_REAGENT_VOLUME]; \
45+
if(__serde_volume <= 0) { \
46+
V = null; \
47+
} else { \
48+
var/list/__serde_reagents = LV[SERDE_REAGENT_LIST]; \
49+
V = new /datum/reagents(__serde_volume, src); \
50+
for(var/list/entry in __serde_reagents) { \
51+
V.add_reagent(RESOLVE_TO_DECL(entry[1]), entry[2], phase = entry[3], defer_update = TRUE); \
52+
} \
53+
V.handle_update(); \
54+
} \
55+
} else { \
56+
V = null; \
57+
} \
58+
} catch(var/exception/E) { \
59+
log_error("Exception while finalizing reagents load for [type]: [EXCEPTION_TEXT(E)]"); \
60+
V = null; \
61+
}
62+
63+
#define FINALIZE_REAGENTS_SERDE(V) if(islist(V)) { FINALIZE_REAGENTS_SERDE_BODY(V); }
64+
#define FINALIZE_REAGENTS_SERDE_AND_RETURN(V) if(islist(V)) { FINALIZE_REAGENTS_SERDE_BODY(V); return; }

code/__defines/subsystems.dm

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
// Subsystems shutdown in the reverse of the order they initialize in
2020
// The numbers just define the ordering, they are meaningless otherwise.
2121

22-
#define SS_INIT_INPUT 22
23-
#define SS_INIT_EARLY 21
24-
#define SS_INIT_WEBHOOKS 20
25-
#define SS_INIT_MODPACKS 19
26-
#define SS_INIT_SECRETS 18
27-
#define SS_INIT_GARBAGE 17
22+
#define SS_INIT_INPUT 23
23+
#define SS_INIT_EARLY 22
24+
#define SS_INIT_WEBHOOKS 21
25+
#define SS_INIT_MODPACKS 20
26+
#define SS_INIT_SECRETS 19
27+
#define SS_INIT_GARBAGE 18
28+
#define SS_INIT_SERDE 17
2829
#define SS_INIT_MATERIALS 16
2930
#define SS_INIT_PLANTS 15
3031
#define SS_INIT_LORE 14

code/_helpers/serde.dm

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/proc/instantiate_serialized_data(load_z, requestor, list/instance_map, entries_decay_at, entry_decay_weight)
2+
3+
var/list/nested_instances = list()
4+
var/list/instanced_areas = list()
5+
var/list/created_data = list()
6+
7+
LAZYINITLIST(instance_map)
8+
9+
to_world_log("Finalising load of [length(instance_map)] instance\s for level '[requestor]'.")
10+
for(var/uid in instance_map)
11+
12+
var/list/instance_data = instance_map[uid]
13+
try
14+
15+
var/raw_load_path = instance_data[nameof(/datum::type)]
16+
var/load_path = ispath(raw_load_path, /datum) ? raw_load_path : text2path(raw_load_path)
17+
if(!ispath(load_path, /datum))
18+
error("[requestor]: attempted to load persistent instance with invalid or non-/datum type '[raw_load_path]'")
19+
continue
20+
21+
var/datum/created_instance
22+
23+
// Instance is a /datum.
24+
// Just pass the data in and assume the datum type knows what to do with it.
25+
if(!ispath(load_path, /atom) && ispath(load_path, /datum))
26+
created_instance = new load_path(instance_data)
27+
created_data += created_instance
28+
else
29+
var/list/spawn_data = instance_data[nameof(/atom/movable::loc)]
30+
if(spawn_data)
31+
32+
if(isnull(spawn_data) || length(spawn_data) < 3)
33+
error("[requestor]: attempted to load persistent instance with malformed loc.")
34+
continue
35+
36+
// Instance has a world coordinate.
37+
if(islist(spawn_data))
38+
var/turf/spawn_loc = locate(spawn_data[1], spawn_data[2], isnull(load_z) ? spawn_data[3] : load_z)
39+
if(!istype(spawn_loc))
40+
error("[requestor]: attempted to load persistent instance but could not find spawn loc.")
41+
continue
42+
if(ispath(load_path, /turf))
43+
if(spawn_loc.type == load_path)
44+
created_instance = spawn_loc
45+
else
46+
created_instance = spawn_loc.ChangeTurf(load_path)
47+
48+
// TODO: Areas will need bespoke handling for non-subtype-related persistence (blueprint renaming etc).
49+
else if(ispath(load_path, /area))
50+
var/area/area = instanced_areas[load_path]
51+
if(!area)
52+
area = new load_path(null)
53+
instanced_areas[load_path] = area
54+
ChangeArea(spawn_loc, area)
55+
56+
else if(ispath(load_path, /atom))
57+
created_instance = new load_path(spawn_loc)
58+
spawn_loc._contents_were_modified = TRUE // ensure
59+
else
60+
error("[requestor]: attempted to instantiate unimplemented path '[load_path]'.")
61+
continue
62+
63+
// Instance is inside another instance; implies/requires /atom/movable
64+
else if(istext(spawn_data))
65+
if(!ispath(load_path, /atom/movable))
66+
error("[requestor]: tried to spawn non-movable [load_path] inside an instance.")
67+
continue
68+
created_instance = new load_path
69+
nested_instances[created_instance] = spawn_data
70+
71+
else
72+
error("[requestor]: attempted to load persistent instance with malformed loc.")
73+
continue
74+
75+
else
76+
// Should we just go ahead and do this to create atoms in nullspace?
77+
// Would we ever want to track an atom in nullspace via level persistence?
78+
error("[requestor]: attempted to load non-/datum persistent instance with no spawn loc.")
79+
80+
if(istype(created_instance))
81+
LAZYSET(., uid, created_instance)
82+
if(isatom(created_instance))
83+
var/atom/atom = created_instance
84+
atom.__deserialization_payload = instance_data
85+
SSatoms.deserialized_atoms[uid] = atom
86+
if(!isnull(entries_decay_at) && !isnull(entry_decay_weight))
87+
created_instance.HandlePersistentDecay(entries_decay_at, entry_decay_weight)
88+
89+
catch(var/exception/E)
90+
log_error("Exception during persistent instance load - [islist(instance_data) ? json_encode(instance_data) : "no instance data"]: [EXCEPTION_TEXT(E)]")
91+
92+
// Atoms use SSatoms for this, datums don't go through SSatoms so need to do it here.
93+
for(var/datum/instance in created_data)
94+
instance.DeserializePostInit(.)
95+
96+
// Resolve any loc references to instances.
97+
for(var/atom/movable/atom as anything in nested_instances)
98+
var/nested_atom_id = nested_instances[atom]
99+
var/atom/nested_atom = .[nested_atom_id]
100+
if(!istype(nested_atom))
101+
error("[requestor]: could not resolve instance ref [nested_atom_id] to instance.")
102+
continue
103+
atom.forceMove(nested_atom)
104+
nested_atom.contents_were_modified()
105+
106+
// Now that everything is loaded and placed, clear out anything that should not be present on the turfs we've loaded.
107+
for(var/uid in SSatoms.deserialized_atoms)
108+
var/turf/turf = SSatoms.deserialized_atoms[uid]
109+
if(!istype(turf))
110+
continue
111+
for(var/atom/thing in turf)
112+
if(!thing.simulated)
113+
continue
114+
if(!isnull(thing.__deserialization_payload))
115+
continue
116+
qdel(thing)
117+
118+
to_world_log("[requestor] loaded [length(.)] persistent instance\s.")
119+
120+
/proc/apply_serde_message_decay(_message, _age, _decay_weight, _decay_at)
121+
var/static/list/decayed_chars = list(".",",","-","'","\\","/","\"",":",";")
122+
if(_age < _decay_at || isnull(_message))
123+
return _message
124+
. = ""
125+
for(var/i = 1 to length(_message))
126+
var/char = copytext(_message, i, i + 1)
127+
if(prob(round(_age * _decay_weight)))
128+
if(prob(99))
129+
. += pick(decayed_chars)
130+
else
131+
. += char

code/controllers/evacuation/evacuation.dm

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,8 @@
9191
A.readyalert()
9292
if(!skip_announce)
9393
global.using_map.emergency_shuttle_called_announcement()
94-
else
95-
if(!skip_announce)
96-
priority_announcement.Announce(replacetext(replacetext(global.using_map.shuttle_called_message, "%dock_name%", "[global.using_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"))
97-
94+
else if(!skip_announce && global.using_map.shuttle_called_message)
95+
priority_announcement.Announce(replacetext(replacetext(global.using_map.shuttle_called_message, "%dock_name%", "[global.using_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"))
9896
return 1
9997

10098
/datum/evacuation_controller/proc/cancel_evacuation()
@@ -113,12 +111,13 @@
113111
auto_recall_time = null
114112

115113
if(emergency_evacuation)
116-
evac_recalled.Announce(global.using_map.emergency_shuttle_recall_message)
114+
if(global.using_map.emergency_shuttle_recall_message)
115+
evac_recalled.Announce(global.using_map.emergency_shuttle_recall_message)
117116
for(var/area/A in global.areas)
118117
if(istype(A) && (A.area_flags & AREA_FLAG_HALLWAY))
119118
A.readyreset()
120119
emergency_evacuation = 0
121-
else
120+
else if(global.using_map.emergency_shuttle_recall_message)
122121
priority_announcement.Announce(global.using_map.shuttle_recall_message)
123122

124123
return 1

0 commit comments

Comments
 (0)