|
| 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; } |
0 commit comments