From 7bf86ed53f4a7f7f14ca85b2f10b953683749451 Mon Sep 17 00:00:00 2001 From: kevinz000 Date: Sun, 22 Oct 2017 19:44:12 -0700 Subject: [PATCH 1/6] Refactors transit requests to turf_reservations. --- code/__DEFINES/flags.dm | 12 +- code/__DEFINES/maps.dm | 4 +- code/__HELPERS/level_traits.dm | 2 +- code/_globalvars/bitfields.dm | 2 +- code/controllers/subsystem/mapping.dm | 71 +++++++++- code/controllers/subsystem/shuttle.dm | 126 +++--------------- code/datums/components/stationloving.dm | 2 +- code/game/area/areas/shuttles.dm | 1 + code/game/atoms.dm | 2 +- code/modules/admin/verbs/debug.dm | 9 +- code/modules/antagonists/nukeop/nukeop.dm | 3 +- code/modules/events/pirates.dm | 2 +- .../space_management/space_reservation.dm | 70 ++++++++++ .../mining/equipment/wormhole_jaunter.dm | 2 +- .../mining/lavaland/necropolis_chests.dm | 2 +- code/modules/shuttle/docking.dm | 6 +- code/modules/shuttle/shuttle.dm | 21 +-- tgstation.dme | 1 + 18 files changed, 190 insertions(+), 148 deletions(-) create mode 100644 code/modules/mapping/space_management/space_reservation.dm diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index bcc9545b50fc5..88eca016edb87 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -25,12 +25,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff. //turf-only flags -#define NOJAUNT_1 (1<<0) -#define UNUSED_TRANSIT_TURF_1 (1<<1) -#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas. -#define NO_DEATHRATTLE_1 (1<<4) // Do not notify deadchat about any deaths that occur on this turf. -#define NO_RUINS_1 (1<<5) //Blocks ruins spawning on the turf -#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf +#define NOJAUNT_1 (1<<0) +#define UNUSED_RESERVATION_TURF_1 (1<<1) +#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas. +#define NO_DEATHRATTLE_1 (1<<4) // Do not notify deadchat about any deaths that occur on this turf. +#define NO_RUINS_1 (1<<5) //Blocks ruins spawning on the turf +#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf /* These defines are used specifically with the atom/pass_flags bitmask diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index c86e47709c8e8..a200e0a0c703e 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -33,7 +33,7 @@ require only minor tweaks. #define ZTRAIT_STATION "Station" #define ZTRAIT_MINING "Mining" #define ZTRAIT_REEBE "Reebe" -#define ZTRAIT_TRANSIT "Transit" +#define ZTRAIT_RESERVED "Transit/Reserved" #define ZTRAIT_AWAY "Away Mission" #define ZTRAIT_SPACE_RUINS "Space Ruins" #define ZTRAIT_LAVA_RUINS "Lava Ruins" @@ -76,6 +76,8 @@ require only minor tweaks. #define CAMERA_LOCK_CENTCOM 4 #define CAMERA_LOCK_REEBE 8 +//Reserved/Transit turf type +#define RESERVED_TURF_TYPE /turf/open/space //Ruin Generation diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm index 4d20c9b513b96..b73a0aa83dee0 100644 --- a/code/__HELPERS/level_traits.dm +++ b/code/__HELPERS/level_traits.dm @@ -9,7 +9,7 @@ #define is_reebe(z) SSmapping.level_trait(z, ZTRAIT_REEBE) -#define is_transit_level(z) SSmapping.level_trait(z, ZTRAIT_TRANSIT) +#define is_reserved_level(z) SSmapping.level_trait(z, ZTRAIT_RESERVED) #define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 9af1fd2da97e7..efae93fc354a4 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -114,7 +114,7 @@ GLOBAL_LIST_INIT(bitfields, list( ), "flags_1" = list( "NOJAUNT_1" = NOJAUNT_1, - "UNUSED_TRANSIT_TURF_1" = UNUSED_TRANSIT_TURF_1, + "UNUSED_RESERVED_TURF_1" = UNUSED_RESERVED_TURF_1, "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, "HEAR_1 / NO_DEATHRATTLE_1 (turfs)" = HEAR_1, "CHECK_RICOCHET_1 / NO_RUINS_1 (turfs)" = CHECK_RICOCHET_1, diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 2d9901288121d..58c73cb586ba5 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(mapping) name = "Mapping" init_order = INIT_ORDER_MAPPING - flags = SS_NO_FIRE + flags = NONE var/list/nuke_tiles = list() var/list/nuke_threats = list() @@ -21,6 +21,11 @@ SUBSYSTEM_DEF(mapping) var/list/areas_in_z = list() var/loading_ruins = FALSE + var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs) + var/list/datum/turf_reservations //list of turf reservations + var/list/used_turfs = list() //list of turf = datum/turf_reservation + + var/clearing_reserved_areas = FALSE // Z-manager stuff var/station_start // should only be used for maploading-related tasks @@ -58,12 +63,13 @@ SUBSYSTEM_DEF(mapping) ++space_levels_so_far empty_space = add_new_zlevel("Empty Area [space_levels_so_far]", list(ZTRAIT_LINKAGE = CROSSLINKED)) // and the transit level - transit = add_new_zlevel("Transit", list(ZTRAIT_TRANSIT = TRUE)) + transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE)) // Pick a random away mission. if(CONFIG_GET(flag/roundstart_away)) createRandomZlevel() + // Generate mining ruins loading_ruins = TRUE var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS) @@ -83,12 +89,17 @@ SUBSYSTEM_DEF(mapping) setup_map_transitions() generate_station_area_list() QDEL_NULL(loader) + initialize_reserved_level() ..() /* Nuke threats, for making the blue tiles on the station go RED Used by the AI doomsday and the self destruct nuke. */ +/datum/controller/subsystem/mapping/fire() + if(clearing_reserved_areas) + wipe_turf_reservations() + /datum/controller/subsystem/mapping/proc/add_nuke_threat(datum/nuke) nuke_threats[nuke] = TRUE check_nuke_threats() @@ -114,10 +125,15 @@ SUBSYSTEM_DEF(mapping) lava_ruins_templates = SSmapping.lava_ruins_templates shuttle_templates = SSmapping.shuttle_templates shelter_templates = SSmapping.shelter_templates + unused_turfs = SSmapping.unused_turfs + turf_reservations = SSmapping.turf_reservations. + used_turfs = SSmapping.used_turfs config = SSmapping.config next_map_config = SSmapping.next_map_config + clearing_reserved_areas = SSmapping.clearing_reserved_areas + z_list = SSmapping.z_list #define INIT_ANNOUNCE(X) to_chat(world, "[X]"); log_world(X) @@ -328,7 +344,6 @@ GLOBAL_LIST_EMPTY(the_station_areas) shelter_templates[S.shelter_id] = S map_templates[S.shelter_id] = S - //Manual loading of away missions. /client/proc/admin_away() set name = "Load Away Mission" @@ -381,4 +396,52 @@ GLOBAL_LIST_EMPTY(the_station_areas) break //Link station gate with away gate and remove wait time. GLOB.the_gateway.awaygate = new_gate - GLOB.the_gateway.wait = world.time \ No newline at end of file + GLOB.the_gateway.wait = world.time + +/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override) + var/datum/turf_reservation/reserve = new type + if(turf_type_override) + reserve.turf_type = turf_type_override + if(!z) + for(var/i in levels_by_trait(ZTRAIT_RESERVED)) + if(reserve.Reserve(width, height, i)) + return reserve + else + if(!level_trait(z, ZTRAIT_RESERVED)) + return + else + if(reserve.Reserve(width, height, z)) + return reserve + QDEL_NULL(reserve) + +/datum/controller/subsystem/mapping/proc/initialize_reserved_level() + // transit zone + for(var/i in levels_by_trait(ZTRAIT_RESERVED)) + var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i)) + var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i)) + reserve_turfs(block(A, B)) + +/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs) + for(var/i in turfs) + var/turf/T = i + T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE) + LAZYINITLIST(unused_turfs["[T.z]"]) + unused_turfs["[T.z]"] |= T + T.flags_1 |= UNUSED_RESERVATION_TURF_1 + +/datum/controller/subsystem/mapping/proc/wipe_turf_reservations() + if(SSshuttle && SSshuttle.transit_requesters) + SSshuttle.transit_requesters.Cut() + for(var/i in turf_reservations) + var/datum/turf_reservation/TR = i + qdel(TR, TRUE) + var/list/clearing = list() + for(var/l in unused_turfs) + for(var/i in l) + clearing |= i + for(var/i in used_turfs) + clearing |= i + unused_turfs = list() + used_turfs = list() + reserve_turfs(clearing) + UNSETEMPTY(turf_reservations) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 7370abf3d5fa6..77c98c0c5e7f2 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -1,4 +1,3 @@ -#define HIGHLIGHT_DYNAMIC_TRANSIT 0 #define MAX_TRANSIT_REQUEST_RETRIES 10 SUBSYSTEM_DEF(shuttle) @@ -14,10 +13,8 @@ SUBSYSTEM_DEF(shuttle) var/list/stationary = list() var/list/transit = list() - var/list/turf/transit_turfs = list() var/list/transit_requesters = list() var/list/transit_request_failures = list() - var/clear_transit = FALSE //emergency shuttle stuff var/obj/docking_port/mobile/emergency/emergency @@ -65,15 +62,8 @@ SUBSYSTEM_DEF(shuttle) continue supply_packs[P.type] = P - if(!transit_turfs.len) - setup_transit_zone() - initial_load() -#ifdef HIGHLIGHT_DYNAMIC_TRANSIT - color_space() -#endif - if(!arrivals) WARNING("No /obj/docking_port/mobile/arrivals placed on the map!") if(!emergency) @@ -93,33 +83,6 @@ SUBSYSTEM_DEF(shuttle) S.load_roundstart() CHECK_TICK -/datum/controller/subsystem/shuttle/proc/setup_transit_zone() - // transit zone - var/z = SSmapping.transit.z_value - var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z)) - var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z)) - for(var/i in block(A, B)) - var/turf/T = i - T.ChangeTurf(/turf/open/space) - transit_turfs += T - T.flags_1 |= UNUSED_TRANSIT_TURF_1 - -#ifdef HIGHLIGHT_DYNAMIC_TRANSIT -/datum/controller/subsystem/shuttle/proc/color_space() - var/z = SSmapping.transit.z_value - var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z)) - var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z)) - for(var/i in block(A, B)) - var/turf/T = i - // Only dying the "pure" space, not the transit tiles - if(istype(T, /turf/open/space/transit) || !isspaceturf(T)) - continue - if((T.x == A.x) || (T.x == B.x) || (T.y == A.y) || (T.y == B.y)) - T.color = "#ffff00" - else - T.color = "#00ffff" -#endif - /datum/controller/subsystem/shuttle/fire() for(var/thing in mobile) if(!thing) @@ -127,12 +90,10 @@ SUBSYSTEM_DEF(shuttle) continue var/obj/docking_port/mobile/P = thing P.check() - var/changed_transit = FALSE for(var/thing in transit) var/obj/docking_port/stationary/transit/T = thing if(!T.owner) qdel(T, force=TRUE) - changed_transit = TRUE // This next one removes transit docks/zones that aren't // immediately being used. This will mean that the zone creation // code will be running a lot. @@ -143,18 +104,6 @@ SUBSYSTEM_DEF(shuttle) var/not_in_use = (!T.get_docked()) if(idle && not_centcom_evac && not_in_use) qdel(T, force=TRUE) - changed_transit = TRUE - if(clear_transit) - transit_requesters.Cut() - for(var/i in transit) - qdel(i, force=TRUE) - setup_transit_zone() - clear_transit = FALSE - changed_transit = TRUE -#ifdef HIGHLIGHT_DYNAMIC_TRANSIT - if(changed_transit) - color_space() -#endif CheckAutoEvac() while(transit_requesters.len) @@ -473,43 +422,29 @@ SUBSYSTEM_DEF(shuttle) if(EAST, WEST) transit_width += M.height transit_height += M.width + /* to_chat(world, "The attempted transit dock will be [transit_width] width, and \) [transit_height] in height. The travel dir is [travel_dir]." */ - // Then find a place to put the zone - - var/list/proposed_zone + var/transit_path = /turf/open/space/transit + switch(travel_dir) + if(NORTH) + transit_path = /turf/open/space/transit/north + if(SOUTH) + transit_path = /turf/open/space/transit/south + if(EAST) + transit_path = /turf/open/space/transit/east + if(WEST) + transit_path = /turf/open/space/transit/west - base: - for(var/i in transit_turfs) - CHECK_TICK - var/turf/topleft = i - if(!(topleft.flags_1 & UNUSED_TRANSIT_TURF_1)) - continue - var/turf/bottomright = locate(topleft.x + transit_width, - topleft.y + transit_height, topleft.z) - if(!bottomright) - continue - if(!(bottomright.flags_1 & UNUSED_TRANSIT_TURF_1)) - continue + var/datum/turf_reservation/proposal = SSmapping.RequestBlockReservation(transit_width, transit_height, null, /datum/turf_reservation/transit, transit_path) - proposed_zone = block(topleft, bottomright) - if(!proposed_zone) - continue - for(var/j in proposed_zone) - var/turf/T = j - if(!T) - continue base - if(!(T.flags_1 & UNUSED_TRANSIT_TURF_1)) - continue base - break base - - if((!proposed_zone) || (!proposed_zone.len)) + if(!istype(proposal)) return FALSE - var/turf/topleft = proposed_zone[1] + var/turf/bottomleft = locate(proposal.bottom_left_coords[1], proposal.bottom_left_coords[2], proposal.bottom_left_coords[3]) // Then create a transit docking port in the middle var/coords = M.return_coords(0, 0, dock_dir) /* 0------2 @@ -528,41 +463,24 @@ SUBSYSTEM_DEF(shuttle) var/y2 = min(y0, y1) // Then invert the numbers - var/transit_x = topleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2) - var/transit_y = topleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2) - - var/transit_path = /turf/open/space/transit - switch(travel_dir) - if(NORTH) - transit_path = /turf/open/space/transit/north - if(SOUTH) - transit_path = /turf/open/space/transit/south - if(EAST) - transit_path = /turf/open/space/transit/east - if(WEST) - transit_path = /turf/open/space/transit/west + var/transit_x = bottomleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2) + var/transit_y = bottomleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2) - var/turf/midpoint = locate(transit_x, transit_y, topleft.z) + var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z) if(!midpoint) return FALSE var/area/shuttle/transit/A = new() A.parallax_movedir = travel_dir - A.contents = proposed_zone + A.contents = proposal.reserved_turfs var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint) - new_transit_dock.assigned_turfs = proposed_zone + new_transit_dock.reserved_area = proposal new_transit_dock.name = "Transit for [M.id]/[M.name]" new_transit_dock.owner = M new_transit_dock.assigned_area = A - // Add 180, because ports point inwards, rather than outwards new_transit_dock.setDir(angle2dir(dock_angle)) - for(var/i in new_transit_dock.assigned_turfs) - var/turf/T = i - T.ChangeTurf(transit_path) - T.flags_1 &= ~(UNUSED_TRANSIT_TURF_1) - M.assigned_transit = new_transit_dock return new_transit_dock @@ -573,9 +491,6 @@ SUBSYSTEM_DEF(shuttle) stationary = SSshuttle.stationary if (istype(SSshuttle.transit)) transit = SSshuttle.transit - - if (istype(SSshuttle.transit_turfs)) - transit_turfs = SSshuttle.transit_turfs if (istype(SSshuttle.transit_requesters)) transit_requesters = SSshuttle.transit_requesters if (istype(SSshuttle.transit_request_failures)) @@ -613,9 +528,6 @@ SUBSYSTEM_DEF(shuttle) if (istype(SSshuttle.shuttle_purchase_requirements_met)) shuttle_purchase_requirements_met = SSshuttle.shuttle_purchase_requirements_met - if (clear_transit) - WARNING("The shuttle subsystem crashed and was recovered while clearing transit.") - centcom_message = SSshuttle.centcom_message ordernum = SSshuttle.ordernum points = SSshuttle.points diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm index 136431b5ee99a..a0e3860ae174f 100644 --- a/code/datums/components/stationloving.dm +++ b/code/datums/components/stationloving.dm @@ -56,7 +56,7 @@ return FALSE if (is_station_level(T.z) || is_centcom_level(T.z)) return TRUE - if (is_transit_level(T.z)) + if (is_reserved_level(T.z)) if (is_type_in_typecache(A, allowed_shuttles)) return TRUE diff --git a/code/game/area/areas/shuttles.dm b/code/game/area/areas/shuttles.dm index 073e7714b2fd6..90a6bbd3b6103 100644 --- a/code/game/area/areas/shuttles.dm +++ b/code/game/area/areas/shuttles.dm @@ -67,6 +67,7 @@ /area/shuttle/transit name = "Hyperspace" desc = "Weeeeee" + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED /area/shuttle/custom name = "Custom player shuttle" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 66610ed94d798..f2bc4d0525709 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -112,7 +112,7 @@ if(!T) return FALSE - if(is_transit_level(T.z)) + if(is_reserved_level(T.z)) for(var/A in SSshuttle.mobile) var/obj/docking_port/mobile/M = A if(M.launch_status == ENDGAME_TRANSIT) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index e6ddd72e3a00b..d5b08e97d0fff 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -961,11 +961,14 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) /client/proc/clear_dynamic_transit() set category = "Debug" - set name = "Clear Dynamic Transit" - set desc = "Deallocates all transit space, restoring it to round start conditions." + set name = "Clear Dynamic Turf Reservations" + set desc = "Deallocates all reserved space, restoring it to round start conditions." if(!holder) return - SSshuttle.clear_transit = TRUE + var/answer = alert("WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", "YES", "NO") + if(answer != "YES") + return + SSmapping.clearing_reserved_areas = TRUE message_admins("[key_name_admin(src)] cleared dynamic transit space.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Clear Dynamic Transit") // If... log_admin("[key_name(src)] cleared dynamic transit space.") diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 1796227f9caa8..3df9d1d9ca005 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -258,7 +258,8 @@ /datum/team/nuclear/proc/syndies_escaped() var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate") - return S && (is_centcom_level(S.z) || is_transit_level(S.z)) + var/obj/docking_port/stationary/transit/T = locate() in S.loc + return S && (is_centcom_level(S.z) || T) /datum/team/nuclear/proc/get_result() var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index ea341c2997deb..76c51aabcddc8 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -209,7 +209,7 @@ /obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE) . = ..() - if(. == DOCKING_SUCCESS && !is_transit_level(new_dock.z)) + if(. == DOCKING_SUCCESS && !is_reserved_level(new_dock.z)) engines_cooling = TRUE addtimer(CALLBACK(src,.proc/reset_cooldown),engine_cooldown,TIMER_UNIQUE) diff --git a/code/modules/mapping/space_management/space_reservation.dm b/code/modules/mapping/space_management/space_reservation.dm new file mode 100644 index 0000000000000..38e7e4ecad797 --- /dev/null +++ b/code/modules/mapping/space_management/space_reservation.dm @@ -0,0 +1,70 @@ + +//Yes, they can only be rectangular. +//Yes, I'm sorry. +/datum/turf_reservation + var/list/reserved_turfs = list() + var/bottom_left_coords[3] + var/top_right_coords[3] + var/wipe_reservation_on_release = TRUE + var/turf_type = /turf/open/space + +/datum/turf_reservation/transit + turf_type = /turf/open/space/transit + +/datum/turf_reservation/proc/Release() + var/v = reserved_turfs.Copy() + for(var/i in reserved_turfs) + reserved_turfs -= i + SSmapping.used_turfs -= i + SSmapping.reserve_turfs(v) + +/datum/turf_reservation/proc/Reserve(width, height, zlevel) + if(width > world.maxx || height > world.maxy) + return FALSE + var/list/avail = SSmapping.unused_turfs["[zlevel]"] + var/turf/BL + var/turf/TR + var/list/turf/final = list() + var/passing = FALSE + for(var/i in avail) + CHECK_TICK + BL = i + if(!(BL.flags_1 & UNUSED_RESERVATION_TURF_1)) + continue + if(BL.x + width > world.maxx || BL.y + height > world.maxy) + continue + TR = locate(BL.x + width, BL.y + height, BL.z) + if(!(TR.flags_1 & UNUSED_RESERVATION_TURF_1)) + continue + final = block(BL, TR) + if(!final) + continue + passing = TRUE + for(var/I in final) + var/turf/checking = I + if(!(checking.flags_1 & UNUSED_RESERVATION_TURF_1)) + passing = FALSE + break + if(!passing) + continue + break + if(!passing || !istype(BL) || !istype(TR)) + return FALSE + bottom_left_coords = list(BL.x, BL.y, BL.z) + top_right_coords = list(TR.x, TR.y, TR.z) + for(var/i in final) + var/turf/T = i + reserved_turfs |= T + T.flags_1 &= ~UNUSED_RESERVATION_TURF_1 + SSmapping.unused_turfs["[T.z]"] -= T + SSmapping.used_turfs[T] = src + T.ChangeTurf(turf_type, turf_type) + return TRUE + +/datum/turf_reservation/New() + LAZYADD(SSmapping.turf_reservations, src) + +/datum/turf_reservation/Destroy() + Release() + LAZYREMOVE(SSmapping.turf_reservations, src) + return ..() diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index 437d6fb26f6fc..9cb3f5c323499 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -20,7 +20,7 @@ /obj/item/wormhole_jaunter/proc/turf_check(mob/user) var/turf/device_turf = get_turf(user) - if(!device_turf || is_centcom_level(device_turf.z) || is_transit_level(device_turf.z)) + if(!device_turf || is_centcom_level(device_turf.z) || is_reserved_level(device_turf.z)) to_chat(user, "You're having difficulties getting the [src.name] to work.") return FALSE return TRUE diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 4e345668a0e2b..a184c3d4dadc4 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -589,7 +589,7 @@ to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.") var/last_ladder = null for(var/i in 1 to world.maxz) - if(is_centcom_level(i) || is_transit_level(i) || is_reebe(i) || is_away_level(i)) + if(is_centcom_level(i) || is_reserved_level(i) || is_reebe(i) || is_away_level(i)) continue var/turf/T2 = locate(ladder_x, ladder_y, i) last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder) diff --git a/code/modules/shuttle/docking.dm b/code/modules/shuttle/docking.dm index c0052845c777a..fa78c8cb99b47 100644 --- a/code/modules/shuttle/docking.dm +++ b/code/modules/shuttle/docking.dm @@ -16,7 +16,7 @@ // The area that gets placed under where the shuttle moved from var/underlying_area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA - + if(old_dock) //Dock overwrites underlying_area_type = old_dock.area_type @@ -105,7 +105,7 @@ list/areas_to_move, rotation, ) - + for(var/i in 1 to old_turfs.len) CHECK_TICK var/turf/oldT = old_turfs[i] @@ -173,7 +173,7 @@ movement_direction, area/underlying_old_area, ) - + underlying_old_area.afterShuttleMove() // Parallax handling diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index a687fa5bbefa4..48985821ddc40 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -202,7 +202,7 @@ /obj/docking_port/stationary/transit name = "In Transit" - var/list/turf/assigned_turfs = list() + var/datum/turf_reservation/reserved_area var/area/shuttle/transit/assigned_area var/obj/docking_port/mobile/owner @@ -210,14 +210,6 @@ . = ..() SSshuttle.transit += src -/obj/docking_port/stationary/transit/proc/dezone() - for(var/i in 1 to assigned_turfs.len) - var/turf/T = assigned_turfs[i] - if(istype(T, /turf/open/space/transit)) - T.ChangeTurf(/turf/open/space) - T.assemble_baseturfs(initial(T.baseturfs)) - T.flags_1 |= UNUSED_TRANSIT_TURF_1 - /obj/docking_port/stationary/transit/Destroy(force=FALSE) if(force) if(get_docked()) @@ -227,10 +219,7 @@ if(owner.assigned_transit == src) owner.assigned_transit = null owner = null - if(assigned_turfs) - dezone() - assigned_turfs.Cut() - assigned_turfs = null + QDEL_NULL(reserved_area) . = ..() /obj/docking_port/mobile @@ -282,7 +271,7 @@ SSshuttle.mobile -= src destination = null previous = null - assigned_transit = null + QDEL_NULL(assigned_transit) //don't need it where we're goin'! shuttle_areas = null . = ..() @@ -432,7 +421,7 @@ underlying_area_type = current_dock.area_type var/list/old_turfs = return_ordered_turfs(x, y, z, dir) - + var/area/underlying_area for(var/i in GLOB.sortedAreas) var/area/place = i @@ -450,7 +439,7 @@ underlying_area.contents += oldT oldT.change_area(old_area, underlying_area) oldT.empty(FALSE) - + // Here we locate the bottomost shuttle boundary and remove all turfs above it var/list/baseturf_cache = oldT.baseturfs for(var/k in 1 to length(baseturf_cache)) diff --git a/tgstation.dme b/tgstation.dme index 24f9efbae03ae..056fd03298fc0 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1730,6 +1730,7 @@ #include "code\modules\mapping\reader.dm" #include "code\modules\mapping\ruins.dm" #include "code\modules\mapping\space_management\space_level.dm" +#include "code\modules\mapping\space_management\space_reservation.dm" #include "code\modules\mapping\space_management\space_transition.dm" #include "code\modules\mapping\space_management\traits.dm" #include "code\modules\mapping\space_management\zlevel_manager.dm" From 3b0072602a64e6f0059f669bf45a977f0a87e78b Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sat, 2 Jun 2018 13:32:26 -0700 Subject: [PATCH 2/6] typo --- code/_globalvars/bitfields.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index efae93fc354a4..dead8d3ab3bc1 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -114,7 +114,7 @@ GLOBAL_LIST_INIT(bitfields, list( ), "flags_1" = list( "NOJAUNT_1" = NOJAUNT_1, - "UNUSED_RESERVED_TURF_1" = UNUSED_RESERVED_TURF_1, + "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1, "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, "HEAR_1 / NO_DEATHRATTLE_1 (turfs)" = HEAR_1, "CHECK_RICOCHET_1 / NO_RUINS_1 (turfs)" = CHECK_RICOCHET_1, From c437b094ee28d4303bfce373aa4f24b6db40051e Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 3 Jun 2018 10:08:36 -0700 Subject: [PATCH 3/6] Woops, nice catch, nearly caused a memory leak there :^) --- code/__DEFINES/maps.dm | 2 +- code/controllers/subsystem/mapping.dm | 1 + code/game/machinery/computer/communications.dm | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index a200e0a0c703e..98d022d27e09d 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -77,7 +77,7 @@ require only minor tweaks. #define CAMERA_LOCK_REEBE 8 //Reserved/Transit turf type -#define RESERVED_TURF_TYPE /turf/open/space +#define RESERVED_TURF_TYPE /turf/open/space/basic //What the turf is when not being used //Ruin Generation diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 58c73cb586ba5..167e664b87a97 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -408,6 +408,7 @@ GLOBAL_LIST_EMPTY(the_station_areas) return reserve else if(!level_trait(z, ZTRAIT_RESERVED)) + qdel(reserve) return else if(reserve.Reserve(width, height, z)) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index e8c999a80f31a..1daeb94f570e0 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -51,7 +51,7 @@ /obj/machinery/computer/communications/Topic(href, href_list) if(..()) return - if(!is_station_level(z) && !is_transit_level(z)) //Can only use in transit and on SS13 + if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") return usr.set_machine(src) From 7996baca4c178a471df52317a9bd2e17c42063e0 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 5 Jun 2018 16:30:49 -0700 Subject: [PATCH 4/6] Clear transit changes --- code/controllers/subsystem/mapping.dm | 74 +++++++++++++++++++-------- code/controllers/subsystem/shuttle.dm | 25 ++++----- code/modules/admin/verbs/debug.dm | 3 +- code/modules/shuttle/shuttle.dm | 6 ++- 4 files changed, 72 insertions(+), 36 deletions(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 167e664b87a97..a48360803bae0 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -1,7 +1,9 @@ SUBSYSTEM_DEF(mapping) name = "Mapping" init_order = INIT_ORDER_MAPPING - flags = NONE + flags = SS_NO_FIRE + + var/world_loaded = FALSE var/list/nuke_tiles = list() var/list/nuke_threats = list() @@ -25,7 +27,7 @@ SUBSYSTEM_DEF(mapping) var/list/datum/turf_reservations //list of turf reservations var/list/used_turfs = list() //list of turf = datum/turf_reservation - var/clearing_reserved_areas = FALSE + var/clearing_reserved_turfs = FALSE // Z-manager stuff var/station_start // should only be used for maploading-related tasks @@ -46,6 +48,8 @@ SUBSYSTEM_DEF(mapping) /datum/controller/subsystem/mapping/Initialize(timeofday) + if(initialized) + return if(config.defaulted) to_chat(world, "Unable to load next map config, defaulting to Box Station") loader = new @@ -96,9 +100,34 @@ SUBSYSTEM_DEF(mapping) Used by the AI doomsday and the self destruct nuke. */ -/datum/controller/subsystem/mapping/fire() - if(clearing_reserved_areas) - wipe_turf_reservations() +/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100) + if(clearing_reserved_turfs || !initialized) //in either case this is just not needed. + return + clearing_reserved_turfs = TRUE + SSshuttle.transit_requesters.Cut() + message_admins("Clearing dynamic reservation space.") + var/list/obj/docking_port/mobile/in_transit = list() + for(var/i in SSshuttle.transit) + var/obj/docking_port/stationary/transit/T = i + if(!istype(T)) + continue + in_transit[T] = T.get_docked() + var/go_ahead = world.time + wipe_safety_delay + if(in_transit.len) + message_admins("Shuttles in transit detected. Attempting to fast travel. Timeout is [go_ahead/10] seconds.") + var/list/cleared = list() + for(var/i in in_transit) + INVOKE_ASYNC(src, .proc/safety_clear_transit_dock, i, in_transit[i], cleared) + UNTIL((go_ahead < world.time) || (cleared.len == in_transit.len)) + do_wipe_turf_reservations() + clearing_reserved_turfs = FALSE + +/datum/controller/subsystem/mapping/proc/safety_clear_transit_dock(obj/docking_port/stationary/transit/T, obj/docking_port/mobile/M, list/returning) + M.setTimer(0) + var/error = M.initiate_docking(M.destination, M.preferred_direction) + if(!error) + returning += M + qdel(T, TRUE) /datum/controller/subsystem/mapping/proc/add_nuke_threat(datum/nuke) nuke_threats[nuke] = TRUE @@ -126,13 +155,13 @@ SUBSYSTEM_DEF(mapping) shuttle_templates = SSmapping.shuttle_templates shelter_templates = SSmapping.shelter_templates unused_turfs = SSmapping.unused_turfs - turf_reservations = SSmapping.turf_reservations. + turf_reservations = SSmapping.turf_reservations used_turfs = SSmapping.used_turfs config = SSmapping.config next_map_config = SSmapping.next_map_config - clearing_reserved_areas = SSmapping.clearing_reserved_areas + clearing_reserved_turfs = SSmapping.clearing_reserved_turfs z_list = SSmapping.z_list @@ -399,6 +428,7 @@ GLOBAL_LIST_EMPTY(the_station_areas) GLOB.the_gateway.wait = world.time /datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override) + UNTIL(initialized && !clearing_reserved_turfs) var/datum/turf_reservation/reserve = new type if(turf_type_override) reserve.turf_type = turf_type_override @@ -415,12 +445,15 @@ GLOBAL_LIST_EMPTY(the_station_areas) return reserve QDEL_NULL(reserve) +//This is not for wiping reserved levels, use wipe_reservations() for that. /datum/controller/subsystem/mapping/proc/initialize_reserved_level() - // transit zone + UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case. + clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it. for(var/i in levels_by_trait(ZTRAIT_RESERVED)) var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i)) var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i)) reserve_turfs(block(A, B)) + clearing_reserved_turfs = FALSE /datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs) for(var/i in turfs) @@ -429,20 +462,21 @@ GLOBAL_LIST_EMPTY(the_station_areas) LAZYINITLIST(unused_turfs["[T.z]"]) unused_turfs["[T.z]"] |= T T.flags_1 |= UNUSED_RESERVATION_TURF_1 + CHECK_TICK -/datum/controller/subsystem/mapping/proc/wipe_turf_reservations() - if(SSshuttle && SSshuttle.transit_requesters) - SSshuttle.transit_requesters.Cut() +//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations(). +/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations() + UNTIL(initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things. for(var/i in turf_reservations) var/datum/turf_reservation/TR = i - qdel(TR, TRUE) + if(!QDELETED(TR)) + qdel(TR, TRUE) + UNSETEMPTY(turf_reservations) var/list/clearing = list() - for(var/l in unused_turfs) - for(var/i in l) - clearing |= i - for(var/i in used_turfs) - clearing |= i - unused_turfs = list() - used_turfs = list() + for(var/l in unused_turfs) //unused_turfs is a assoc list by z = list(turfs) + if(islist(unused_turfs[l])) + clearing |= unused_turfs[l] + clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already. + unused_turfs.Cut() + used_turfs.Cut() reserve_turfs(clearing) - UNSETEMPTY(turf_reservations) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 77c98c0c5e7f2..1e656ae1eb75a 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -106,18 +106,19 @@ SUBSYSTEM_DEF(shuttle) qdel(T, force=TRUE) CheckAutoEvac() - while(transit_requesters.len) - var/requester = popleft(transit_requesters) - var/success = generate_transit_dock(requester) - if(!success) // BACK OF THE QUEUE - transit_request_failures[requester]++ - if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES) - transit_requesters += requester - else - var/obj/docking_port/mobile/M = requester - M.transit_failure() - if(MC_TICK_CHECK) - break + if(!SSmapping.clearing_reserved_turfs) + while(transit_requesters.len) + var/requester = popleft(transit_requesters) + var/success = generate_transit_dock(requester) + if(!success) // BACK OF THE QUEUE + transit_request_failures[requester]++ + if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES) + transit_requesters += requester + else + var/obj/docking_port/mobile/M = requester + M.transit_failure() + if(MC_TICK_CHECK) + break /datum/controller/subsystem/shuttle/proc/CheckAutoEvac() if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted()) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index d5b08e97d0fff..d34e1ebd4220c 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -968,11 +968,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) var/answer = alert("WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", "YES", "NO") if(answer != "YES") return - SSmapping.clearing_reserved_areas = TRUE message_admins("[key_name_admin(src)] cleared dynamic transit space.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Clear Dynamic Transit") // If... log_admin("[key_name(src)] cleared dynamic transit space.") - + SSmapping.wipe_reservations() //this goes after it's logged, incase something horrible happens. /client/proc/toggle_medal_disable() set category = "Debug" diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 48985821ddc40..fc8169f6d258d 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -219,8 +219,10 @@ if(owner.assigned_transit == src) owner.assigned_transit = null owner = null - QDEL_NULL(reserved_area) - . = ..() + if(!QDELETED(reserved_area)) + qdel(reserved_area) + reserved_area = null + return ..() /obj/docking_port/mobile name = "shuttle" From 93a90155007877188aca4f89d36498432ea37449 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Wed, 13 Jun 2018 14:10:33 -0700 Subject: [PATCH 5/6] Woops, wrong var. --- code/controllers/subsystem/mapping.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index a48360803bae0..2de2acebf8a2f 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -114,7 +114,7 @@ SUBSYSTEM_DEF(mapping) in_transit[T] = T.get_docked() var/go_ahead = world.time + wipe_safety_delay if(in_transit.len) - message_admins("Shuttles in transit detected. Attempting to fast travel. Timeout is [go_ahead/10] seconds.") + message_admins("Shuttles in transit detected. Attempting to fast travel. Timeout is [wipe_safety_delay/10] seconds.") var/list/cleared = list() for(var/i in in_transit) INVOKE_ASYNC(src, .proc/safety_clear_transit_dock, i, in_transit[i], cleared) @@ -148,6 +148,7 @@ SUBSYSTEM_DEF(mapping) /datum/controller/subsystem/mapping/Recover() flags |= SS_NO_INIT + initialized = SSmapping.initialized map_templates = SSmapping.map_templates ruins_templates = SSmapping.ruins_templates space_ruins_templates = SSmapping.space_ruins_templates From f6564b51f4ef0f6b0c5a4b1e79d3ff9ff176985d Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Thu, 14 Jun 2018 23:33:24 -0700 Subject: [PATCH 6/6] Unused variable --- code/controllers/subsystem/mapping.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 2de2acebf8a2f..e2698670e9647 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -3,8 +3,6 @@ SUBSYSTEM_DEF(mapping) init_order = INIT_ORDER_MAPPING flags = SS_NO_FIRE - var/world_loaded = FALSE - var/list/nuke_tiles = list() var/list/nuke_threats = list()