Runtime Dynamic Station Loading (#24171)

* Dynamic map loading prototype

* Get the title screen working

* Fixes the random pod bugs

* map configs

* Add back the asteroid

* Ignore the rotate file

* Fix some shit

* More shit fixes

* Babby's first json

* Cyberboss confirmed shitcoder

* Makes map rotation great again

* Moves the map defines

* Delete tgstation2.dm

* Convert runtimestation

* Convert PubbyStation

* Convert OmegaStation

* Convert Metastation

* Convert Delta Station

* Lol file extensions

* Reee line endings

* Take out the trash

* Fix loadallmaps.dm

* Deltaassssssstation?

* Fix travis

* Did I ASK you to change the line endings?

* Remove votable maps

* Cleanup

* Previous config. Load configs in New. Fix splash

* Fix this

* More generic minetype

* STOP TOUCHING THE LINE ENDINGS!!!

* Add some flexibility to /obj/screen/splash

* Fix the shit

* Update gitignore

* Smooth transition from last map

* Better check

* Missed this map rotate check

* Remove these checks too

* Prep for a future request by @kevinz000

* Fix z2 line endings

* Solution for custom .dms

* Rename some things, trim some fat

* Fixes default map_config

* Remove stale comment

* Delete the previous config after loading

* Don't try to open a non-existent file

* Delete the old rotator script

* And references to it

* Line endings

* More line endings

* Del checks from when m-config may have not existed

* LINE ENDINGS

* Update the default map config

* Map load error checking for what it's worth

* Small cleanup

* For case sensitive

* File systems

* Strip maprotate stuff from build script

* Spruce up the _maps tree. Compile some empty space

* Make travis simpler

* LINEARU ENDARU!!!

* tgstation TWO!!!

* Lowercase mine type

* Dummy dm's for testmerging

* Fixes job ordering

* If ghosts wanna watch the map load so be it

* Let them know what's going on

* Fixes z-transitions

* Optimize z expansion further

* Remove this old var

* Fix wiznerd teleportation

* Rmove butt

* Does the thing

* Moved temp configs to the data dir

* Un-touch gitignore

* Forgot templates.dm

* Forgot to include the includer

* Fair enough

* SILENCE IMBECILE!

* @Cyberboss still a fuckboi

* Speed things up a bit

* Fix a potential bug with the error message

* Whatever
This commit is contained in:
Cyberboss
2017-03-07 10:45:31 +13:00
committed by oranges
parent 63c33469df
commit 1bbc640afe
71 changed files with 562 additions and 2139 deletions
-4
View File
@@ -350,9 +350,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
//if find_references isn't working for some datum
//update this list using tools/DMTreeToGlobalsList
/datum/proc/find_references_in_globals()
SearchVar(nextmap)
SearchVar(mapchanging)
SearchVar(rebootingpendingmapchange)
SearchVar(clockwork_construction_value)
SearchVar(clockwork_caches)
SearchVar(clockwork_daemons)
@@ -481,7 +478,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
SearchVar(CELLRATE)
SearchVar(CHARGELEVEL)
SearchVar(powernets)
SearchVar(map_name)
SearchVar(hair_styles_list)
SearchVar(hair_styles_male_list)
SearchVar(hair_styles_female_list)
+3
View File
@@ -39,6 +39,9 @@ var/datum/subsystem/job/SSjob
continue
if(!job.config_check())
continue
if(!job.map_check()) //Even though we initialize before mapping, this is fine because the config is loaded at new
testing("Removed [job.type] due to map config");
continue
occupations += job
name_occupations[job.title] = job
type_occupations[J] = job
+121 -4
View File
@@ -8,6 +8,10 @@ var/datum/subsystem/mapping/SSmapping
var/list/nuke_tiles = list()
var/list/nuke_threats = list()
var/datum/map_config/previous_map_config
var/datum/map_config/config
var/datum/map_config/next_map_config
var/list/map_templates = list()
var/list/ruins_templates = list()
@@ -19,18 +23,29 @@ var/datum/subsystem/mapping/SSmapping
/datum/subsystem/mapping/New()
NEW_SS_GLOBAL(SSmapping)
if(!previous_map_config)
previous_map_config = new("data/previous_map.json", delete_after = TRUE)
if(previous_map_config.defaulted)
previous_map_config = null
if(!config)
config = new
return ..()
/datum/subsystem/mapping/Initialize(timeofday)
if(config.defaulted)
world << "<span class='boldannounce'>Unable to load next map config, defaulting to Box Station</span>"
loadWorld()
SortAreas()
process_teleport_locs() //Sets up the wizard teleport locations
preloadTemplates()
// Pick a random away mission.
createRandomZlevel()
// Generate mining.
var/mining_type = MINETYPE
var/mining_type = config.minetype
if (mining_type == "lavaland")
seedRuins(list(5), config.lavaland_budget, /area/lavaland/surface/outdoors, lava_ruins_templates)
seedRuins(list(5), global.config.lavaland_budget, /area/lavaland/surface/outdoors, lava_ruins_templates)
spawn_rivers()
// deep space ruins
@@ -42,7 +57,7 @@ var/datum/subsystem/mapping/SSmapping
else
space_zlevels += i
seedRuins(space_zlevels, config.space_budget, /area/space, space_ruins_templates)
seedRuins(space_zlevels, global.config.space_budget, /area/space, space_ruins_templates)
// Set up Z-level transistions.
setup_map_transitions()
@@ -80,6 +95,108 @@ var/datum/subsystem/mapping/SSmapping
shuttle_templates = SSmapping.shuttle_templates
shelter_templates = SSmapping.shelter_templates
previous_map_config = SSmapping.previous_map_config
config = SSmapping.config
next_map_config = SSmapping.next_map_config
/datum/subsystem/mapping/proc/TryLoadZ(filename, errorList, forceLevel, last)
var/static/dmm_suite/loader
if(!loader)
loader = new
if(!loader.load_map(file(filename), 0, 0, forceLevel, no_changeturf = TRUE))
errorList |= filename
if(last)
QDEL_NULL(loader)
/datum/subsystem/mapping/proc/CreateSpace()
++world.maxz
CHECK_TICK
for(var/T in block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)))
CHECK_TICK
new /turf/open/space(T)
#define INIT_ANNOUNCE(X) world << "<span class='boldannounce'>[X]</span>"; log_world(X)
/datum/subsystem/mapping/proc/loadWorld()
//if any of these fail, something has gone horribly, HORRIBLY, wrong
var/list/FailedZs = list()
INIT_ANNOUNCE("Loading [config.map_name]...")
TryLoadZ(config.GetFullMapPath(), FailedZs, ZLEVEL_STATION)
INIT_ANNOUNCE("Loaded station!")
INIT_ANNOUNCE("Loading mining level...")
TryLoadZ("_maps/map_files/generic/[config.minetype].dmm", FailedZs, ZLEVEL_MINING, TRUE)
INIT_ANNOUNCE("Loaded mining level!")
for(var/I in (ZLEVEL_MINING + 1) to ZLEVEL_SPACEMAX)
CreateSpace()
if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen
var/msg = "RED ALERT! The following map files failed to load: [FailedZs[1]]"
if(FailedZs.len > 1)
for(var/I in 2 to FailedZs.len)
msg += ", [I]"
msg += ". Yell at your server host!"
INIT_ANNOUNCE(msg)
#undef INIT_ANNOUNCE
/datum/subsystem/mapping/proc/maprotate()
var/players = clients.len
var/list/mapvotes = list()
//count votes
for (var/client/c in clients)
var/vote = c.prefs.preferred_map
if (!vote)
if (global.config.defaultmap)
mapvotes[global.config.defaultmap.map_name] += 1
continue
mapvotes[vote] += 1
//filter votes
for (var/map in mapvotes)
if (!map)
mapvotes.Remove(map)
if (!(map in global.config.maplist))
mapvotes.Remove(map)
continue
var/datum/map_config/VM = global.config.maplist[map]
if (!VM)
mapvotes.Remove(map)
continue
if (VM.voteweight <= 0)
mapvotes.Remove(map)
continue
if (VM.config_min_users > 0 && players < VM.config_min_users)
mapvotes.Remove(map)
continue
if (VM.config_max_users > 0 && players > VM.config_max_users)
mapvotes.Remove(map)
continue
mapvotes[map] = mapvotes[map]*VM.voteweight
var/pickedmap = pickweight(mapvotes)
if (!pickedmap)
return
var/datum/map_config/VM = global.config.maplist[pickedmap]
message_admins("Randomly rotating map to [VM.map_name]")
. = changemap(VM)
if (.)
world << "<span class='boldannounce'>Map rotation has chosen [VM.map_name] for next round!</span>"
/datum/subsystem/mapping/proc/changemap(var/datum/map_config/VM)
if(!VM.MakeNextMap())
next_map_config = new(default_to_box = TRUE)
message_admins("Failed to set new map with next_map.json for [VM.map_name]! Using default as backup!")
return
next_map_config = VM
return TRUE
/datum/subsystem/mapping/Shutdown()
if(config)
config.MakePreviousMap()
/datum/subsystem/mapping/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup
var/list/filelist = flist(path)
for(var/map in filelist)
@@ -136,4 +253,4 @@ var/datum/subsystem/mapping/SSmapping
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
+6 -6
View File
@@ -13,7 +13,7 @@ var/datum/subsystem/minimap/SSminimap
NEW_SS_GLOBAL(SSminimap)
/datum/subsystem/minimap/Initialize(timeofday)
var/hash = md5(file2text("_maps/[MAP_PATH]/[MAP_FILE]"))
var/hash = md5(SSmapping.config.GetFullMapPath())
if(config.generate_minimaps)
if(hash == trim(file2text(hash_path())))
for(var/z in z_levels) //We have these files cached, let's register them
@@ -45,22 +45,22 @@ var/datum/subsystem/minimap/SSminimap
for(var/z in z_levels)
if(!fexists(file(map_path(z,backup)))) //Let's make sure we have a file for this map
if(backup)
log_world("Failed to find backup file for map [MAP_NAME] on zlevel [z].")
log_world("Failed to find backup file for map [SSmapping.config.map_name] on zlevel [z].")
return FALSE
return TRUE
/datum/subsystem/minimap/proc/hash_path(backup)
if(backup)
return "icons/minimaps/[MAP_NAME].md5"
return "icons/minimaps/[SSmapping.config.map_name].md5"
else
return "data/minimaps/[MAP_NAME].md5"
return "data/minimaps/[SSmapping.config.map_name].md5"
/datum/subsystem/minimap/proc/map_path(z,backup)
if(backup)
return "icons/minimaps/[MAP_NAME]_[z].png"
return "icons/minimaps/[SSmapping.config.map_name]_[z].png"
else
return "data/minimaps/[MAP_NAME]_[z].png"
return "data/minimaps/[SSmapping.config.map_name]_[z].png"
/datum/subsystem/minimap/proc/send(client/client)
for(var/z in z_levels)
+5 -5
View File
@@ -25,7 +25,7 @@ var/datum/subsystem/persistence/SSpersistence
/datum/subsystem/persistence/proc/LoadSatchels()
secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav")
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/weapon/crowbar))
secret_satchels[MAP_NAME] >> old_secret_satchels
secret_satchels[SSmapping.config.map_name] >> old_secret_satchels
var/list/expanded_old_satchels = list()
var/placed_satchels = 0
@@ -51,7 +51,7 @@ var/datum/subsystem/persistence/SSpersistence
satchel_string = pick_n_take(expanded_old_satchels)
old_secret_satchels = jointext(expanded_old_satchels,"#")
secret_satchels[MAP_NAME] << old_secret_satchels
secret_satchels[SSmapping.config.map_name] << old_secret_satchels
var/list/chosen_satchel = splittext(satchel_string,"|")
if(!chosen_satchel || isemptylist(chosen_satchel) || chosen_satchel.len != 3) //Malformed
@@ -78,7 +78,7 @@ var/datum/subsystem/persistence/SSpersistence
/datum/subsystem/persistence/proc/LoadChiselMessages()
chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
var/saved_json
chisel_messages_sav[MAP_NAME] >> saved_json
chisel_messages_sav[SSmapping.config.map_name] >> saved_json
if(!saved_json)
return
@@ -118,13 +118,13 @@ var/datum/subsystem/persistence/SSpersistence
if(isemptylist(savable_obj))
continue
old_secret_satchels += "[F.x]|[F.y]|[pick(savable_obj)]#"
secret_satchels[MAP_NAME] << old_secret_satchels
secret_satchels[SSmapping.config.map_name] << old_secret_satchels
/datum/subsystem/persistence/proc/CollectChiselMessages()
for(var/obj/structure/chisel_message/M in chisel_messages)
saved_messages += list(M.pack())
chisel_messages_sav[MAP_NAME] << json_encode(saved_messages)
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
/datum/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
saved_messages += list(M.pack()) // dm eats one list.
+2 -2
View File
@@ -613,7 +613,7 @@ var/datum/subsystem/ticker/ticker
queue_delay = 0
/datum/subsystem/ticker/proc/check_maprotate()
if (!config.maprotation || !SERVERTOOLS)
if (!config.maprotation)
return
if (SSshuttle.emergency.mode != SHUTTLE_ESCAPE || SSshuttle.canRecall())
return
@@ -625,7 +625,7 @@ var/datum/subsystem/ticker/ticker
//map rotate chance defaults to 75% of the length of the round (in minutes)
if (!prob((world.time/600)*config.maprotatechancedelta))
return
INVOKE_ASYNC(GLOBAL_PROC, /.proc/maprotate)
INVOKE_ASYNC(SSmapping, /datum/subsystem/mapping/.proc/maprotate)
/world/proc/has_round_started()
+20 -22
View File
@@ -2,11 +2,10 @@ var/datum/subsystem/title/SStitle
/datum/subsystem/title
name = "Title Screen"
init_order = INFINITY //It's the very first thing you see, don't make it wait!
init_order = 15
flags = SS_NO_FIRE
var/turf/closed/indestructible/splashscreen/title_screen
/datum/subsystem/title/New()
NEW_SS_GLOBAL(SStitle)
@@ -15,27 +14,26 @@ var/datum/subsystem/title/SStitle
var/list/title_screens = list()
var/use_rare_screens = FALSE
if(!title_screen)
return
if(title_screen)
if(prob(1))
use_rare_screens = TRUE
if(prob(1))
use_rare_screens = TRUE
for(var/S in provisional_title_screens)
var/list/L = splittext(S,"+")
if((L.len == 1 && L[1] != "blank.png")|| (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(SSmapping.config.map_name)))))
title_screens += S
for(var/S in provisional_title_screens)
var/list/L = splittext(S,"+")
if((L.len == 1 && L[1] != "blank.png")|| (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(MAP_NAME)))))
title_screens += S
if(!isemptylist(title_screens))
if(length(title_screens) > 1)
for(var/S in title_screens)
var/list/L = splittext(S,".")
if(L.len != 2 || L[1] != "default")
continue
title_screens -= S
break
if(!isemptylist(title_screens))
if(length(title_screens) > 1)
for(var/S in title_screens)
var/list/L = splittext(S,".")
if(L.len != 2 || L[1] != "default")
continue
title_screens -= S
break
var/path_string = "config/title_screens/images/[pick(title_screens)]"
var/icon/screen_to_use = new(path_string)
var/path_string = "config/title_screens/images/[pick(title_screens)]"
var/icon/screen_to_use = new(path_string)
title_screen.icon = screen_to_use
title_screen.icon = screen_to_use
..()