mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Fixes the Sun/Weather and Ports Vore's Lighting SS
New lighting system is needed to handle updating literally 14k+ tiles whenever the sun moves. The straight port seems to have had no adverse effects from what I could see. Don't know if it's more performant but it doesn't seem to be less. I didn't expect the latter would be needed for the former.
This commit is contained in:
@@ -11,3 +11,5 @@
|
|||||||
|
|
||||||
var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_GAME, RUNLEVEL_POSTGAME)
|
var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_GAME, RUNLEVEL_POSTGAME)
|
||||||
#define RUNLEVEL_FLAG_TO_INDEX(flag) (log(2, flag) + 1) // Convert from the runlevel bitfield constants to index in runlevel_flags list
|
#define RUNLEVEL_FLAG_TO_INDEX(flag) (log(2, flag) + 1) // Convert from the runlevel bitfield constants to index in runlevel_flags list
|
||||||
|
|
||||||
|
#define INIT_ORDER_LIGHTING 0
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/var/lighting_overlays_initialised = FALSE
|
|
||||||
|
|
||||||
/var/list/lighting_update_lights = list() // List of lighting sources queued for update.
|
|
||||||
/var/list/lighting_update_corners = list() // List of lighting corners queued for update.
|
|
||||||
/var/list/lighting_update_overlays = list() // List of lighting overlays queued for update.
|
|
||||||
|
|
||||||
/var/list/lighting_update_lights_old = list() // List of lighting sources currently being updated.
|
|
||||||
/var/list/lighting_update_corners_old = list() // List of lighting corners currently being updated.
|
|
||||||
/var/list/lighting_update_overlays_old = list() // List of lighting overlays currently being updated.
|
|
||||||
|
|
||||||
|
|
||||||
/datum/controller/process/lighting
|
|
||||||
// Queues of update counts, waiting to be rolled into stats lists
|
|
||||||
var/list/stats_queues = list(
|
|
||||||
"Source" = list(), "Corner" = list(), "Overlay" = list())
|
|
||||||
// Stats lists
|
|
||||||
var/list/stats_lists = list(
|
|
||||||
"Source" = list(), "Corner" = list(), "Overlay" = list())
|
|
||||||
var/update_stats_every = (1 SECONDS)
|
|
||||||
var/next_stats_update = 0
|
|
||||||
var/stat_updates_to_keep = 5
|
|
||||||
|
|
||||||
/datum/controller/process/lighting/setup()
|
|
||||||
name = "lighting"
|
|
||||||
|
|
||||||
schedule_interval = 0 // run as fast as you possibly can
|
|
||||||
sleep_interval = 10 // Yield every 10% of a tick
|
|
||||||
defer_usage = 80 // Defer at 80% of a tick
|
|
||||||
create_all_lighting_overlays()
|
|
||||||
lighting_overlays_initialised = TRUE
|
|
||||||
|
|
||||||
// Pre-process lighting once before the round starts. Wait 30 seconds so the away mission has time to load.
|
|
||||||
spawn(300)
|
|
||||||
doWork(1)
|
|
||||||
|
|
||||||
/datum/controller/process/lighting/doWork(roundstart)
|
|
||||||
|
|
||||||
lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated.
|
|
||||||
lighting_update_lights = list()
|
|
||||||
for(var/datum/light_source/L in lighting_update_lights_old)
|
|
||||||
|
|
||||||
if(L.check() || L.destroyed || L.force_update)
|
|
||||||
L.remove_lum()
|
|
||||||
if(!L.destroyed)
|
|
||||||
L.apply_lum()
|
|
||||||
|
|
||||||
else if(L.vis_update) //We smartly update only tiles that became (in) visible to use.
|
|
||||||
L.smart_vis_update()
|
|
||||||
|
|
||||||
L.vis_update = FALSE
|
|
||||||
L.force_update = FALSE
|
|
||||||
L.needs_update = FALSE
|
|
||||||
|
|
||||||
SCHECK
|
|
||||||
|
|
||||||
lighting_update_corners_old = lighting_update_corners //Same as above.
|
|
||||||
lighting_update_corners = list()
|
|
||||||
for(var/A in lighting_update_corners_old)
|
|
||||||
var/datum/lighting_corner/C = A
|
|
||||||
|
|
||||||
C.update_overlays()
|
|
||||||
|
|
||||||
C.needs_update = FALSE
|
|
||||||
|
|
||||||
SCHECK
|
|
||||||
|
|
||||||
lighting_update_overlays_old = lighting_update_overlays //Same as above.
|
|
||||||
lighting_update_overlays = list()
|
|
||||||
|
|
||||||
for(var/A in lighting_update_overlays_old)
|
|
||||||
var/atom/movable/lighting_overlay/O = A
|
|
||||||
O.update_overlay()
|
|
||||||
O.needs_update = 0
|
|
||||||
SCHECK
|
|
||||||
|
|
||||||
stats_queues["Source"] += lighting_update_lights_old.len
|
|
||||||
stats_queues["Corner"] += lighting_update_corners_old.len
|
|
||||||
stats_queues["Overlay"] += lighting_update_overlays_old.len
|
|
||||||
|
|
||||||
if(next_stats_update <= world.time)
|
|
||||||
next_stats_update = world.time + update_stats_every
|
|
||||||
for(var/stat_name in stats_queues)
|
|
||||||
var/stat_sum = 0
|
|
||||||
var/list/stats_queue = stats_queues[stat_name]
|
|
||||||
for(var/count in stats_queue)
|
|
||||||
stat_sum += count
|
|
||||||
stats_queue.Cut()
|
|
||||||
|
|
||||||
var/list/stats_list = stats_lists[stat_name]
|
|
||||||
stats_list.Insert(1, stat_sum)
|
|
||||||
if(stats_list.len > stat_updates_to_keep)
|
|
||||||
stats_list.Cut(stats_list.len)
|
|
||||||
|
|
||||||
/datum/controller/process/lighting/statProcess()
|
|
||||||
..()
|
|
||||||
stat(null, "[total_lighting_sources] sources, [total_lighting_corners] corners, [total_lighting_overlays] overlays")
|
|
||||||
for(var/stat_type in stats_lists)
|
|
||||||
stat(null, "[stat_type] updates: [jointext(stats_lists[stat_type], " | ")]")
|
|
||||||
166
code/controllers/subsystems/lighting.dm
Normal file
166
code/controllers/subsystems/lighting.dm
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
** Lighting Subsystem - Process the lighting! Do it!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SSLIGHTING_STAGE_LIGHTS 1
|
||||||
|
#define SSLIGHTING_STAGE_CORNERS 2
|
||||||
|
#define SSLIGHTING_STAGE_OVERLAYS 3
|
||||||
|
#define SSLIGHTING_STAGE_DONE 4
|
||||||
|
// This subsystem's fire() method also gets called once during Master.Initialize().
|
||||||
|
// During this fire we need to use CHECK_TICK to sleep and continue, but in all other fires we need to use MC_CHECK_TICK to pause and return.
|
||||||
|
// This leads us to a rather annoying little tidbit of code that I have stuffed into this macro so I don't have to see it.
|
||||||
|
#define DUAL_TICK_CHECK if (init_tick_checks) { CHECK_TICK; } else if (MC_TICK_CHECK) { return; }
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
/var/lighting_overlays_initialised = FALSE
|
||||||
|
/var/list/lighting_update_lights = list() // List of lighting sources queued for update.
|
||||||
|
/var/list/lighting_update_corners = list() // List of lighting corners queued for update.
|
||||||
|
/var/list/lighting_update_overlays = list() // List of lighting overlays queued for update.
|
||||||
|
|
||||||
|
SUBSYSTEM_DEF(lighting)
|
||||||
|
name = "Lighting"
|
||||||
|
wait = 2 // Ticks, not deciseconds
|
||||||
|
init_order = INIT_ORDER_LIGHTING
|
||||||
|
flags = SS_TICKER
|
||||||
|
|
||||||
|
var/list/currentrun = list()
|
||||||
|
var/stage = null
|
||||||
|
|
||||||
|
var/cost_lights = 0
|
||||||
|
var/cost_corners = 0
|
||||||
|
var/cost_overlays = 0
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/Initialize(timeofday)
|
||||||
|
if(!lighting_overlays_initialised)
|
||||||
|
// TODO - TG initializes starlight here.
|
||||||
|
create_all_lighting_overlays()
|
||||||
|
lighting_overlays_initialised = TRUE
|
||||||
|
|
||||||
|
// Pre-process lighting once before the round starts.
|
||||||
|
internal_process_lights(FALSE, TRUE)
|
||||||
|
internal_process_corners(FALSE, TRUE)
|
||||||
|
internal_process_overlays(FALSE, TRUE)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/fire(resumed = FALSE)
|
||||||
|
var/timer
|
||||||
|
if(!resumed)
|
||||||
|
ASSERT(LAZYLEN(currentrun) == 0) // Santity checks to make sure we don't somehow have items left over from last cycle
|
||||||
|
ASSERT(stage == null) // Or somehow didn't finish all the steps from last cycle
|
||||||
|
stage = SSLIGHTING_STAGE_LIGHTS // Start with Step 1 of course
|
||||||
|
|
||||||
|
if(stage == SSLIGHTING_STAGE_LIGHTS)
|
||||||
|
timer = world.tick_usage
|
||||||
|
internal_process_lights(resumed)
|
||||||
|
cost_lights = MC_AVERAGE(cost_lights, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
||||||
|
if(state != SS_RUNNING)
|
||||||
|
return
|
||||||
|
resumed = 0
|
||||||
|
stage = SSLIGHTING_STAGE_CORNERS
|
||||||
|
|
||||||
|
if(stage == SSLIGHTING_STAGE_CORNERS)
|
||||||
|
timer = world.tick_usage
|
||||||
|
internal_process_corners(resumed)
|
||||||
|
cost_corners = MC_AVERAGE(cost_corners, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
||||||
|
if(state != SS_RUNNING)
|
||||||
|
return
|
||||||
|
resumed = 0
|
||||||
|
stage = SSLIGHTING_STAGE_OVERLAYS
|
||||||
|
|
||||||
|
if(stage == SSLIGHTING_STAGE_OVERLAYS)
|
||||||
|
timer = world.tick_usage
|
||||||
|
internal_process_overlays(resumed)
|
||||||
|
cost_overlays = MC_AVERAGE(cost_overlays, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
||||||
|
if(state != SS_RUNNING)
|
||||||
|
return
|
||||||
|
resumed = 0
|
||||||
|
stage = SSLIGHTING_STAGE_DONE
|
||||||
|
|
||||||
|
// Okay, we're done! Woo! Got thru a whole air_master cycle!
|
||||||
|
ASSERT(LAZYLEN(currentrun) == 0) // Sanity checks to make sure there are really none left
|
||||||
|
ASSERT(stage == SSLIGHTING_STAGE_DONE) // And that we didn't somehow skip past the last step
|
||||||
|
currentrun = null
|
||||||
|
stage = null
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/proc/internal_process_lights(resumed = FALSE, init_tick_checks = FALSE)
|
||||||
|
if (!resumed)
|
||||||
|
// We swap out the lists so any additions to the global list during a pause don't make things wierd.
|
||||||
|
src.currentrun = global.lighting_update_lights
|
||||||
|
global.lighting_update_lights = list()
|
||||||
|
|
||||||
|
//cache for sanic speed (lists are references anyways)
|
||||||
|
var/list/currentrun = src.currentrun
|
||||||
|
while(currentrun.len)
|
||||||
|
var/datum/light_source/L = currentrun[currentrun.len]
|
||||||
|
currentrun.len--
|
||||||
|
|
||||||
|
if(!L) continue
|
||||||
|
if(L.check() || L.destroyed || L.force_update)
|
||||||
|
L.remove_lum()
|
||||||
|
if(!L.destroyed)
|
||||||
|
L.apply_lum()
|
||||||
|
|
||||||
|
else if(L.vis_update) //We smartly update only tiles that became (in) visible to use.
|
||||||
|
L.smart_vis_update()
|
||||||
|
|
||||||
|
L.vis_update = FALSE
|
||||||
|
L.force_update = FALSE
|
||||||
|
L.needs_update = FALSE
|
||||||
|
|
||||||
|
DUAL_TICK_CHECK
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/proc/internal_process_corners(resumed = FALSE, init_tick_checks = FALSE)
|
||||||
|
if (!resumed)
|
||||||
|
// We swap out the lists so any additions to the global list during a pause don't make things wierd.
|
||||||
|
src.currentrun = global.lighting_update_corners
|
||||||
|
global.lighting_update_corners = list()
|
||||||
|
|
||||||
|
//cache for sanic speed (lists are references anyways)
|
||||||
|
var/list/currentrun = src.currentrun
|
||||||
|
while(currentrun.len)
|
||||||
|
var/datum/lighting_corner/C = currentrun[currentrun.len]
|
||||||
|
currentrun.len--
|
||||||
|
|
||||||
|
if(!C) continue
|
||||||
|
C.update_overlays()
|
||||||
|
C.needs_update = FALSE
|
||||||
|
|
||||||
|
DUAL_TICK_CHECK
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/proc/internal_process_overlays(resumed = FALSE, init_tick_checks = FALSE)
|
||||||
|
if (!resumed)
|
||||||
|
// We swap out the lists so any additions to the global list during a pause don't make things wierd.
|
||||||
|
src.currentrun = global.lighting_update_overlays
|
||||||
|
global.lighting_update_overlays = list()
|
||||||
|
|
||||||
|
//cache for sanic speed (lists are references anyways)
|
||||||
|
var/list/currentrun = src.currentrun
|
||||||
|
while(currentrun.len)
|
||||||
|
var/atom/movable/lighting_overlay/O = currentrun[currentrun.len]
|
||||||
|
currentrun.len--
|
||||||
|
|
||||||
|
if(!O) continue
|
||||||
|
O.update_overlay()
|
||||||
|
O.needs_update = FALSE
|
||||||
|
|
||||||
|
DUAL_TICK_CHECK
|
||||||
|
|
||||||
|
/datum/controller/subsystem/lighting/stat_entry(msg_prefix)
|
||||||
|
var/list/msg = list(msg_prefix)
|
||||||
|
msg += "T:{"
|
||||||
|
msg += "S [total_lighting_sources] | "
|
||||||
|
msg += "C [total_lighting_corners] | "
|
||||||
|
msg += "O [total_lighting_overlays]"
|
||||||
|
msg += "}"
|
||||||
|
msg += "C:{"
|
||||||
|
msg += "S [round(cost_lights, 1)] | "
|
||||||
|
msg += "C [round(cost_corners, 1)] | "
|
||||||
|
msg += "O [round(cost_overlays, 1)]"
|
||||||
|
msg += "}"
|
||||||
|
..(msg.Join())
|
||||||
|
|
||||||
|
#undef DUAL_TICK_CHECK
|
||||||
|
#undef SSLIGHTING_STAGE_LIGHTS
|
||||||
|
#undef SSLIGHTING_STAGE_CORNERS
|
||||||
|
#undef SSLIGHTING_STAGE_OVERLAYS
|
||||||
|
#undef SSLIGHTING_STAGE_STATS
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
if (force)
|
if (force)
|
||||||
total_lighting_overlays--
|
total_lighting_overlays--
|
||||||
global.lighting_update_overlays -= src
|
global.lighting_update_overlays -= src
|
||||||
global.lighting_update_overlays_old -= src
|
LAZYREMOVE(SSlighting.currentrun, src)
|
||||||
|
|
||||||
var/turf/T = loc
|
var/turf/T = loc
|
||||||
if(istype(T))
|
if(istype(T))
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
|
// Create lighting overlays on all turfs with dynamic lighting in areas with dynamic lighting.
|
||||||
/proc/create_all_lighting_overlays()
|
/proc/create_all_lighting_overlays()
|
||||||
for(var/zlevel = 1 to world.maxz)
|
for(var/area/A in world)
|
||||||
create_lighting_overlays_zlevel(zlevel)
|
if(!A.dynamic_lighting)
|
||||||
|
continue
|
||||||
|
for(var/turf/T in A)
|
||||||
|
if(!T.dynamic_lighting)
|
||||||
|
continue
|
||||||
|
new /atom/movable/lighting_overlay(T, TRUE)
|
||||||
|
CHECK_TICK
|
||||||
|
CHECK_TICK
|
||||||
|
|
||||||
/proc/create_lighting_overlays_zlevel(var/zlevel)
|
/proc/create_lighting_overlays_zlevel(var/zlevel)
|
||||||
ASSERT(zlevel)
|
ASSERT(zlevel)
|
||||||
|
|||||||
@@ -149,4 +149,11 @@
|
|||||||
..()
|
..()
|
||||||
teleport_x = src.x
|
teleport_x = src.x
|
||||||
teleport_y = 2
|
teleport_y = 2
|
||||||
teleport_z = Z_LEVEL_SURFACE
|
teleport_z = Z_LEVEL_SURFACE
|
||||||
|
|
||||||
|
/datum/planet/sif
|
||||||
|
expected_z_levels = list(
|
||||||
|
Z_LEVEL_SURFACE,
|
||||||
|
Z_LEVEL_SURFACE_MINE,
|
||||||
|
Z_LEVEL_SURFACE_WILD
|
||||||
|
)
|
||||||
@@ -155,7 +155,6 @@
|
|||||||
#include "code\controllers\Processes\event.dm"
|
#include "code\controllers\Processes\event.dm"
|
||||||
#include "code\controllers\Processes\game_master.dm"
|
#include "code\controllers\Processes\game_master.dm"
|
||||||
#include "code\controllers\Processes\inactivity.dm"
|
#include "code\controllers\Processes\inactivity.dm"
|
||||||
#include "code\controllers\Processes\lighting.dm"
|
|
||||||
#include "code\controllers\Processes\machinery.dm"
|
#include "code\controllers\Processes\machinery.dm"
|
||||||
#include "code\controllers\Processes\mob.dm"
|
#include "code\controllers\Processes\mob.dm"
|
||||||
#include "code\controllers\Processes\nanoui.dm"
|
#include "code\controllers\Processes\nanoui.dm"
|
||||||
@@ -173,6 +172,7 @@
|
|||||||
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
||||||
#include "code\controllers\subsystems\creation.dm"
|
#include "code\controllers\subsystems\creation.dm"
|
||||||
#include "code\controllers\subsystems\garbage.dm"
|
#include "code\controllers\subsystems\garbage.dm"
|
||||||
|
#include "code\controllers\subsystems\lighting.dm"
|
||||||
#include "code\datums\ai_law_sets.dm"
|
#include "code\datums\ai_law_sets.dm"
|
||||||
#include "code\datums\ai_laws.dm"
|
#include "code\datums\ai_laws.dm"
|
||||||
#include "code\datums\browser.dm"
|
#include "code\datums\browser.dm"
|
||||||
@@ -2262,7 +2262,6 @@
|
|||||||
#include "interface\interface.dm"
|
#include "interface\interface.dm"
|
||||||
#include "interface\skin.dmf"
|
#include "interface\skin.dmf"
|
||||||
#include "maps\northern_star\northern_star.dm"
|
#include "maps\northern_star\northern_star.dm"
|
||||||
#include "maps\northern_star\northern_star_defines.dm"
|
|
||||||
#include "maps\submaps\_readme.dm"
|
#include "maps\submaps\_readme.dm"
|
||||||
#include "maps\submaps\cave_submaps\cave.dm"
|
#include "maps\submaps\cave_submaps\cave.dm"
|
||||||
#include "maps\submaps\space_submaps\space.dm"
|
#include "maps\submaps\space_submaps\space.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user