diff --git a/citadel.dme b/citadel.dme index edb5171297dd..e935f35dd1d2 100644 --- a/citadel.dme +++ b/citadel.dme @@ -1783,6 +1783,7 @@ #include "code\game\objects\items\storage\wallets.dm" #include "code\game\objects\items\storage\medical\firstaid.dm" #include "code\game\objects\items\storage\medical\hypokit.dm" +#include "code\game\objects\items\storage\misc\survival.dm" #include "code\game\objects\items\storage\misc_legacy\bible.dm" #include "code\game\objects\items\storage\misc_legacy\fancy.dm" #include "code\game\objects\items\storage\misc_legacy\laundry_basket.dm" @@ -2026,6 +2027,10 @@ #include "code\game\objects\structures\tables\update_triggers.dm" #include "code\game\objects\systems\_system.dm" #include "code\game\objects\systems\cell_slot.dm" +#include "code\game\objects\systems\storage\storage-filters.dm" +#include "code\game\objects\systems\storage\storage-indirection.dm" +#include "code\game\objects\systems\storage\storage-indirection_holder.dm" +#include "code\game\objects\systems\storage\storage-limits.dm" #include "code\game\objects\systems\storage\storage-screen_object.dm" #include "code\game\objects\systems\storage\storage-ui.dm" #include "code\game\objects\systems\storage\storage.dm" @@ -2259,6 +2264,7 @@ #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" #include "code\modules\admin\verbs\SDQL2\wrappers\map.dm" +#include "code\modules\admin\verbs\SDQL2\wrappers\math.dm" #include "code\modules\admin\verbs\server\admin_reboot.dm" #include "code\modules\admin\view_variables\admin_delete.dm" #include "code\modules\admin\view_variables\color_matrix_editor.dm" diff --git a/code/__DEFINES/materials/helpers.dm b/code/__DEFINES/materials/helpers.dm index 70eafe784e50..793a43a26c31 100644 --- a/code/__DEFINES/materials/helpers.dm +++ b/code/__DEFINES/materials/helpers.dm @@ -1,14 +1,45 @@ //* This file is explicitly licensed under the MIT license. *// //* Copyright (c) 2023 Citadel Station developers. *// -//* object checks +//* /datum/prototype/material declaration helpers *// + +#define DECLARE_MATERIAL(PATH_FRAGMENT) \ +/datum/prototype/material##PATH_FRAGMENT + +/** + * Generates material stacks for a material. + * + * The material must have: + * + * * a defined `display_name` + * * a defined `sheet_singular_name` + * * a defined `sheet_plural_name` + * * a defined `icon` + * * a defined `icon_stack_count` + */ +#define GENERATE_MATERIAL_STACKS(PATH_FRAGMENT) \ +/obj/item/stack/material##PATH_FRAGMENT { \ + name = /datum/prototype/material##PATH_FRAGMENT::name + " " + /datum/prototype/material##PATH_FRAGMENT::sheet_singular_name; \ + icon = /datum/prototype/material##PATH_FRAGMENT::icon; \ + icon_state = "stack-1"; \ + material = /datum/prototype/material##PATH_FRAGMENT; \ + no_variants = TRUE; \ + amount = 1; \ +} \ +/obj/item/stack/material##PATH_FRAGMENT/full_stack { \ + name = /datum/prototype/material##PATH_FRAGMENT::name + " " + /datum/prototype/material##PATH_FRAGMENT::sheet_plural_name; \ + icon_state = "stack"; \ + amount = 50; \ +} + +//* Material Traits - Checks *// /// We are ticking materials. #define IS_TICKING_MATERIALS(A) (A.atom_flags & ATOM_MATERIALS_TICKING) #define START_TICKING_MATERIALS(A) SSmaterials.add_ticked_object(src) #define STOP_TICKING_MATERIALS(A) SSmaterials.remove_ticked_object(src) -//* /atom level invocation of traits +//* Material Traits - /atom invocation *// /// Invocation of material traits /// A - the atom diff --git a/code/__DEFINES/objects/objects.dm b/code/__DEFINES/objects/objects.dm index 65cdac7abb35..92cb1c25f747 100644 --- a/code/__DEFINES/objects/objects.dm +++ b/code/__DEFINES/objects/objects.dm @@ -1,16 +1,23 @@ //* This file is explicitly licensed under the MIT license. *// -//* Copyright (c) 2024 silicons *// +//* Copyright (c) 2024 Citadel Station Developers *// //* /obj/var/hides_underfloor /// do not change these willy-nilly, these are strings for the map editor. /// just Don't -#define OBJ_UNDERFLOOR_DISABLED "disabled" +/// * this is different from 'NEVER' +#define OBJ_UNDERFLOOR_UNSUPPORTED "unsupported" /// never underfloor, even if floor isn't plating #define OBJ_UNDERFLOOR_NEVER "never" -/// always underfloor, as long as floor isn't plating -#define OBJ_UNDERFLOOR_ALWAYS "always" +/// Should be underfloor, and is not currently underfloor. +/// * Setting to this at runtime is equal to setting to [OBJ_UNDERFLOOR_ACTIVE]. +/// The atom will automatically hide under the floor if the floor is covered. +#define OBJ_UNDERFLOOR_INACTIVE "inactive" +/// Should be underfloor, and is currently underfloor. +/// * Setting to this at runtime is equal to setting to [OBJ_UNDERFLOOR_INACTIVE]. +/// The atom will automatically hide under the floor if the floor is covered. +#define OBJ_UNDERFLOOR_ACTIVE "active" /// automatic /// /// * gets set to UNDERFLOOR_NEVER if we were made while the floor is intact @@ -18,6 +25,7 @@ #define OBJ_UNDERFLOOR_IF_CREATED_UNCOVERED "initially-covered" /// automatic /// +/// * This is what you usually want. /// * IF_CREATED_UNCOVERED, but always underfloor if made in mapload #define OBJ_UNDERFLOOR_UNLESS_PLACED_ONTOP "initially-underfloor" @@ -26,9 +34,10 @@ DEFINE_ENUM("obj_hides_underfloor", list( "hides_underfloor", ), ), list( - "Disabled" = OBJ_UNDERFLOOR_DISABLED, - "Never" = OBJ_UNDERFLOOR_NEVER, - "Always" = OBJ_UNDERFLOOR_ALWAYS, + "Unsupported" = OBJ_UNDERFLOOR_UNSUPPORTED, + "No" = OBJ_UNDERFLOOR_NEVER, + "Yes (Currently Uncovered)" = OBJ_UNDERFLOOR_INACTIVE, + "Yes (Currently Covered)" = OBJ_UNDERFLOOR_ACTIVE, "If Created Uncovered (Init Only)" = OBJ_UNDERFLOOR_IF_CREATED_UNCOVERED, "If Created Uncovered Or In Mapload (Init Only)" = OBJ_UNDERFLOOR_UNLESS_PLACED_ONTOP, )) diff --git a/code/controllers/configuration_old/configuration.dm b/code/controllers/configuration_old/configuration.dm index d5f4efefc8fc..c67bb947d520 100644 --- a/code/controllers/configuration_old/configuration.dm +++ b/code/controllers/configuration_old/configuration.dm @@ -9,8 +9,6 @@ var/nudge_script_path = "nudge.py" // where the nudge.py script is located - var/hub_visibility = FALSE //CITADEL CHANGE - HUB CONFIG - var/log_ooc = 0 // log OOC channel var/log_access = 0 // log login/logout var/log_say = 0 // log client say @@ -280,9 +278,6 @@ if ("ban_legacy_system") config_legacy.ban_legacy_system = 1 - if ("hub_visibility") //CITADEL CHANGE - ADDS HUB CONFIG - config_legacy.hub_visibility = 1 - if ("jobs_have_minimal_access") config_legacy.jobs_have_minimal_access = 1 @@ -834,4 +829,3 @@ config_legacy.python_path = "/usr/bin/env python2" else //probably windows, if not this should work anyway config_legacy.python_path = "python" - world.update_hub_visibility(hub_visibility) //CITADEL CHANGE - HUB CONFIG diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 33e4e1156c9b..ce03cc2859c0 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -135,9 +135,34 @@ SUBSYSTEM_DEF(atoms) * * ... - rest of args are passed to new() / Initialize(). */ /datum/controller/subsystem/atoms/proc/instance_atom_immediate(path, mapload, atom/where, ...) + SHOULD_NOT_SLEEP(TRUE) var/old_init_status = atom_init_status atom_init_status = mapload? ATOM_INIT_IN_NEW_MAPLOAD : ATOM_INIT_IN_NEW_REGULAR - var/atom/created = new path(arglist(args.Copy())) + var/atom/created = new path(arglist(args.Copy(3))) + atom_init_status = old_init_status + return created + +/** + * immediately creates and inits an atom with a preloader callback. + * + * @params + * * path - typepath + * * mapload - treat as mapload? + * * preload_call - callback to invoke with (created) for the created atom. This is not allowed to sleep. + * * where - location to init at + * * ... - rest of args are passed to new() / Initialize(). + */ +/datum/controller/subsystem/atoms/proc/instance_atom_immediate_with_preloader(path, mapload, datum/callback/preload_call, atom/where, ...) + SHOULD_NOT_SLEEP(TRUE) + var/old_init_status = atom_init_status + atom_init_status = ATOM_INIT_IN_SUBSYSTEM + var/atom/created = new path(arglist(args.Copy(4))) + preload_call.invoke_no_sleep(created) + atom_init_status = mapload? ATOM_INIT_IN_NEW_MAPLOAD : ATOM_INIT_IN_NEW_REGULAR + // this sets 'where' to if we should be mapload. + // this is acceptable because args[4] ('where') is not used again. + args[4] = mapload + InitAtom(created, FALSE, args.Copy(4)) atom_init_status = old_init_status return created diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index cb85bfb611f4..ac1f562087f3 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -16,7 +16,8 @@ SUBSYSTEM_DEF(server_maint) var/cleanup_ticker = 0 /datum/controller/subsystem/server_maint/PreInit() - world.hub_password = "" //quickly! before the hubbies see us. + // quickly! before the hubbies see us. + world.update_hub_visibility(FALSE) /datum/controller/subsystem/server_maint/Initialize() if (fexists("tmp/")) diff --git a/code/datums/callback.dm b/code/datums/callback.dm index 2087fd6ef448..3918cf039a44 100644 --- a/code/datums/callback.dm +++ b/code/datums/callback.dm @@ -101,24 +101,39 @@ else calling_arguments = args if(datum_flags & DF_VAR_EDITED) - return WrapAdminProcCall(object, delegate, calling_arguments) - if(object == GLOBAL_PROC) - return call(delegate)(arglist(calling_arguments)) - return call(object, delegate)(arglist(calling_arguments)) + . = WrapAdminProcCall(object, delegate, calling_arguments) + else if(object == GLOBAL_PROC) + . = call(delegate)(arglist(calling_arguments)) + else + . = call(object, delegate)(arglist(calling_arguments)) + pass() /** * Invoke this callback and crash if it sleeps. * * * Use when a callback should never sleep, as call() cannot be verified by static analysis. + * * Do not use in performance critical code. This wraps calls more aggressively than InvokeAsync(). + * * `null` is returned if the call sleeps. + * + * The specific use case here is an async call where: + * + * * It's always invalid behavior for a callback to sleep. + * * The caller should be protected (caller shouldn't be interrupted by the sleep). + * + * This allows enforcement of the above invariants by loudly runtiming and bringing attention to the issue, + * as opposed to the usual way of compile checking it (which we can't because this is a reflection-based call to an arbitrary proc). */ /datum/callback/proc/invoke_no_sleep(...) . = CALLBACK_SLEEP_SENTINEL - ASYNC - . = Invoke(arglist(args)) + . = invoke_no_sleep_call(arglist(args)) if(. == CALLBACK_SLEEP_SENTINEL) . = null CRASH("Callback [src] slept on a no-sleeping invoke.") +/datum/callback/proc/invoke_no_sleep_call(...) + set waitfor = FALSE + . = Invoke(arglist(args)) + /** * Invoke this callback async (waitfor=false) * diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 85823242f516..c377c1e9964e 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -141,8 +141,59 @@ for(var/i=0,i