diff --git a/.gitignore b/.gitignore index d4a9c94a4fd..1d850f44988 100644 --- a/.gitignore +++ b/.gitignore @@ -208,3 +208,6 @@ check_regex_output.txt # local development secrets /secret + +# map build directory +/_maps2eb diff --git a/_maps/ship_config_schema.json b/_maps/ship_config_schema.json index b1cfac1b563..6dff27d4985 100644 --- a/_maps/ship_config_schema.json +++ b/_maps/ship_config_schema.json @@ -92,7 +92,7 @@ "title": "Map File Path", "type": "string", "description": "The path to the ship class's map file. Use forward slashes (/) for directories, and include the .dmm extension. Map files must be somewhere under the _maps folder.", - "pattern": "^_maps/([a-zA-Z0-9_/.-]*)dmm$" + "pattern": "^.*_maps/([a-zA-Z0-9_/.-]*)dmm$" }, "job_slots": { "title": "Job Slots", diff --git a/code/__DEFINES/__starfly.dm b/code/__DEFINES/__starfly.dm index 019f3b9e0bd..0de07043d82 100644 --- a/code/__DEFINES/__starfly.dm +++ b/code/__DEFINES/__starfly.dm @@ -45,5 +45,5 @@ #define STARFLY13_MODULE_ROSEUS_GALACTIC_ENABLED #define STARFLY13_MODULE_SINTA_UNATHI_ENABLED #define STARFLY13_MODULE_STARFLY_BRANDING_ENABLED -#define STARFLY13_MODULE_STARFLY_SHIPS_ENABLED +#define STARFLY13_MODULE_STARFLY_MAPS_ENABLED #define STARFLY13_MODULE_YEOSA_UNATHI_ENABLED diff --git a/code/__DEFINES/__starflymaps.dm b/code/__DEFINES/__starflymaps.dm new file mode 100644 index 00000000000..00e145ec0cb --- /dev/null +++ b/code/__DEFINES/__starflymaps.dm @@ -0,0 +1,29 @@ +// __starflymaps.dm +// Copyright 2026 Patrick Meade. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +//--------------------------------------------------------------------------- + +// if we weren't provided with a MAPROOT at build time +#ifndef MAPROOT + // if we're using STARFLY-13 maps... + #ifdef STARFLY13_MODULE_STARFLY_MAPS_ENABLED + // STARFLY-13 maps are located at _maps 2: electric boogaloo + #define MAPROOT "_maps2eb" + // otherwise... + #else + // Shiptest maps are located at _maps + #define MAPROOT "_maps" + #endif // #ifdef STARFLY13_MODULE_STARFLY_MAPS_ENABLED +#endif // #ifndef MAPROOT diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 4ac4b8c6b80..3c1332eef5f 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -136,7 +136,7 @@ SUBSYSTEM_DEF(mapping) #define INIT_ANNOUNCE(X) to_chat(world, span_boldannounce("[X]")); log_world(X) -/datum/controller/subsystem/mapping/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup +/datum/controller/subsystem/mapping/proc/preloadTemplates(path = MAPROOT + "/templates/") //see master controller setup var/list/filelist = flist(path) for(var/map in filelist) var/datum/map_template/T = new(path = "[path][map]", rename = "[map]") @@ -181,12 +181,12 @@ SUBSYSTEM_DEF(mapping) #define CHECK_LIST_EXISTS(X) if(!islist(data[X])) { stack_trace("[##X] missing from json!"); continue; } /datum/controller/subsystem/mapping/proc/load_ship_templates() ship_purchase_list = list() - var/list/filelist = flist("_maps/configs/") + var/list/filelist = flist(MAPROOT + "/configs/") filelist = sortList(filelist) for(var/filename in filelist) - var/file = file("_maps/configs/" + filename) + var/file = file(MAPROOT + "/configs/" + filename) if(!file) stack_trace("Could not open map config: [filename]") continue @@ -203,8 +203,9 @@ SUBSYSTEM_DEF(mapping) CHECK_STRING_EXISTS("map_name") CHECK_STRING_EXISTS("map_path") CHECK_LIST_EXISTS("job_slots") - var/datum/map_template/shuttle/S = new(data["map_path"], data["map_name"], TRUE) - S.file_name = data["map_path"] + var/fixed_path = fix_map_path(data["map_path"]) + var/datum/map_template/shuttle/S = new(fixed_path, data["map_name"], TRUE) + S.file_name = fixed_path S.ship_class = data["map_name"] if(istext(data["map_short_name"])) @@ -446,3 +447,20 @@ SUBSYSTEM_DEF(mapping) height-- var/list/allocation_coords = SSmapping.get_free_allocation(allocation_type, width, height, allocation_jump) return new /datum/virtual_level(new_name, traits, mapzone, allocation_coords[1], allocation_coords[2], allocation_coords[1] + width, allocation_coords[2] + height, allocation_coords[3]) + + + +/proc/fix_map_path(var/path) + if(!istext(path)) + return path + + // Match everything up to and including "_maps" + var/regex/r = regex(@"^.*_maps") + + // If it matches, replace that portion with MAPROOT + if(r.Find(path)) + var/new_path = r.Replace(path, MAPROOT) + return new_path + + // If no match, just return original (or you could warn) + return path diff --git a/code/controllers/subsystem/overmap.dm b/code/controllers/subsystem/overmap.dm index eba96e43c70..c14b2121a56 100644 --- a/code/controllers/subsystem/overmap.dm +++ b/code/controllers/subsystem/overmap.dm @@ -1283,5 +1283,5 @@ SUBSYSTEM_DEF(overmap) name = "Abandoned - New Dawn" can_be_selected_randomly = FALSE can_jump_to = FALSE - json = '_maps/sectors/sunset_starsystem.json' + json = MAPROOT + "/sectors/sunset_starsystem.json" generator_type = OVERMAP_GENERATOR_JSON diff --git a/code/datums/mapgen/greebles/jungleplanet.dm b/code/datums/mapgen/greebles/jungleplanet.dm index ab10745e3a5..23f3f17c88c 100644 --- a/code/datums/mapgen/greebles/jungleplanet.dm +++ b/code/datums/mapgen/greebles/jungleplanet.dm @@ -126,153 +126,153 @@ /datum/map_template/greeble/jungleplanet name = "Jungle Greeble 1" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_1.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_1.dmm" description = "A small attempt at a fishing pier" clear_everything = TRUE /datum/map_template/greeble/jungleplanet/two name = "Jungle Greeble 2" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_2.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_2.dmm" description = "A simple garden, abandoned." /datum/map_template/greeble/jungleplanet/three name = "Jungle Greeble 3" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_3.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_3.dmm" description = "A grave for the damned." /datum/map_template/greeble/jungleplanet/four name = "Jungle Greeble 4" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_4.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_4.dmm" description = "Beware of bear caves." /datum/map_template/greeble/jungleplanet/five name = "Jungle Greeble 5" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_5.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_5.dmm" description = "Murdered frontiersman bits." /datum/map_template/greeble/jungleplanet/six name = "Jungle Greeble 6" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_6.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_6.dmm" description = "Radioactive hole." /datum/map_template/greeble/jungleplanet/seven name = "Jungle Greeble 7" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_7.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_7.dmm" description = "A radioactive incident." /datum/map_template/greeble/jungleplanet/eight name = "Jungle Greeble 8" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_8.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_8.dmm" description = "Radioactive Hole 2" /datum/map_template/greeble/jungleplanet/nine name = "Jungle Greeble 9" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_9.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_9.dmm" description = "Radioactive debris." /datum/map_template/greeble/jungleplanet/ten name = "Jungle Greeble 10" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_10.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_10.dmm" description = "A simple pond." /datum/map_template/greeble/jungleplanet/eleven name = "Jungle Greeble 11" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_11.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_11.dmm" description = "A radioactive trench left to rot." /datum/map_template/greeble/jungleplanet/twelve name = "Jungle Greeble 12" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_12.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_12.dmm" description = "A friend's grave adorned with a flower" /datum/map_template/greeble/jungleplanet/thirteen name = "Jungle Greeble 13" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_13.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_13.dmm" description = "Industrial decay." /datum/map_template/greeble/jungleplanet/fourteen name = "Jungle Greeble 14" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_14.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_14.dmm" description = "Industrial decay 2" /datum/map_template/greeble/jungleplanet/fifteen name = "Jungle Greeble 15" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_15.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_15.dmm" description = "Industrial decay the third." /datum/map_template/greeble/jungleplanet/sixteen name = "Jungle Greeble 16" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_16.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_16.dmm" description = "A broken road." /datum/map_template/greeble/jungleplanet/seventeen name = "Jungle Greeble 17" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_17.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_17.dmm" description = "Who let the chickens out? Who put them here? A chicken coop." /datum/map_template/greeble/jungleplanet/eighteen name = "Jungle Greeble 18" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_18.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_18.dmm" description = "Mangrooves in the water." /datum/map_template/greeble/jungleplanet/nineteen name = "Jungle Greeble 19" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_19.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_19.dmm" description = "Syndicate-flavored debris." /datum/map_template/greeble/jungleplanet/twenty name = "Jungle Greeble 20" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_20.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_20.dmm" description = "Frontiersmen aren't very good pilots, are they?" /datum/map_template/greeble/jungleplanet/twentyone name = "Jungle Greeble 21" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_21.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_21.dmm" description = "Be careful where you dig! Not every site is safe." /datum/map_template/greeble/jungleplanet/twentytwo name = "Jungle Greeble 22" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_22.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_22.dmm" description = "A crashed vessel, completely out of place." /datum/map_template/greeble/jungleplanet/twentythree name = "Jungle Greeble 23" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_23.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_23.dmm" description = "Not every colonization effort works out." /datum/map_template/greeble/jungleplanet/twentyfour name = "Jungle Greeble 24" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_24.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_24.dmm" description = "A quaint little rest from a hostile world." /datum/map_template/greeble/jungleplanet/twentyfive name = "Jungle Greeble 25" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_25.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_25.dmm" description = "An overgrown landing pad. The trees have reclaimed the concrete." /datum/map_template/greeble/jungleplanet/twentysix name = "Jungle Greeble 26" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_26.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_26.dmm" description = "Another scar from the war. A platform." /datum/map_template/greeble/jungleplanet/twentyseven name = "Jungle Greeble 27" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_27.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_27.dmm" description = "Poor bastard exploded." /datum/map_template/greeble/jungleplanet/twentyeight name = "Jungle Greeble 28" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_28.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_28.dmm" description = "A very small, unbroken trench segment." /datum/map_template/greeble/jungleplanet/twentynine name = "Jungle Greeble 29" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_29.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_29.dmm" description = "A watchtower. Better times to be had." /datum/map_template/greeble/jungleplanet/thirty name = "Jungle Greeble 30" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_30.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_30.dmm" description = "Water has come to the surface here, and the ground around it has eroded." /* Cave Greebles */ @@ -324,52 +324,52 @@ /datum/map_template/greeble/jungleplanet/cave name = "Jungle Cave Greeble 1" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_1.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_1.dmm" description = "Nuclear waste dumping incident" /datum/map_template/greeble/jungleplanet/cave/two name = "Jungle Cave Greeble 2" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_2.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_2.dmm" description = "Broken mineshaft." /datum/map_template/greeble/jungleplanet/cave/three name = "Jungle Cave Greeble 3" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_3.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_3.dmm" description = "A den of wolves." /datum/map_template/greeble/jungleplanet/cave/four name = "Jungle Cave Greeble 4" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_4.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_4.dmm" description = "Deep in the world lay shelters for people long-gone." /datum/map_template/greeble/jungleplanet/cave/five name = "Jungle Cave Greeble 5" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_5.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_5.dmm" description = "Wolves have feasted upon those who sought shelter here." /datum/map_template/greeble/jungleplanet/cave/six name = "Jungle Cave Greeble 6" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_6.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_6.dmm" description = "Radioactive trash incident" /datum/map_template/greeble/jungleplanet/cave/seven name = "Jungle Cave Greeble 7" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_7.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_7.dmm" description = "Oil? Don't let the PGF hear." /datum/map_template/greeble/jungleplanet/cave/eight name = "Jungle Cave Greeble 8" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_8.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_8.dmm" description = "A small damp grotto." /datum/map_template/greeble/jungleplanet/cave/nine name = "Jungle Cave Greeble 9" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_9.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_9.dmm" description = "A blossoming corpse left to its own devices." /datum/map_template/greeble/jungleplanet/cave/ten name = "Jungle Cave Greeble 10" - mappath = "_maps/templates/greebles/jungle/greeble_junglecave_10.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_junglecave_10.dmm" description = "Diamonds in the rough." /* Anomaly Greebles @@ -437,61 +437,61 @@ /datum/map_template/greeble/jungleplanet/anomaly name = "Jungle Anomaly Greeble 1" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_1.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_1.dmm" description = "A pool of blood and its conductor." clear_everything = TRUE /datum/map_template/greeble/jungleplanet/anomaly/two name = "Jungle Anomaly Greeble 2" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_2.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_2.dmm" description = "Death comes for us all eventually." /datum/map_template/greeble/jungleplanet/anomaly/three name = "Jungle Anomaly Greeble 3" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_3.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_3.dmm" description = "This doesn't seem right." /datum/map_template/greeble/jungleplanet/anomaly/four name = "Jungle Anomaly Greeble 4" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_4.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_4.dmm" description = "Jungle carpets." /datum/map_template/greeble/jungleplanet/anomaly/five name = "Jungle Anomaly Greeble 5" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_5.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_5.dmm" description = "A lone heartbeat chokes the land around it." /datum/map_template/greeble/jungleplanet/anomaly/six name = "Jungle Anomaly Greeble 6" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_6.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_6.dmm" description = "Go ahead, dump your waste. The frontier has a way with it." /datum/map_template/greeble/jungleplanet/anomaly/seven name = "Jungle Anomaly Greeble 7" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_7.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_7.dmm" description = "Something from outside! Something different!" /datum/map_template/greeble/jungleplanet/anomaly/eight name = "Jungle Anomaly Greeble 8" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_8.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_8.dmm" description = "KILL YOUR TELEVISION" /datum/map_template/greeble/jungleplanet/anomaly/nine name = "Jungle Anomaly Greeble 9" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_9.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_9.dmm" description = "Feed the fountain of life with your corpse." /datum/map_template/greeble/jungleplanet/anomaly/ten name = "Jungle Anomaly Greeble 10" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_10.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_10.dmm" description = "Not every dead mercenary gets buried." /datum/map_template/greeble/jungleplanet/anomaly/eleven name = "Jungle Anomaly Greeble 11" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_11.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_11.dmm" description = "Reach out and touch me." /datum/map_template/greeble/jungleplanet/anomaly/twelve name = "Jungle Anomaly Greeble 12" - mappath = "_maps/templates/greebles/jungle/greeble_jungle_anomaly_12.dmm" + mappath = MAPROOT + "/templates/greebles/jungle/greeble_jungle_anomaly_12.dmm" description = "Will you join my friends and I?" diff --git a/code/datums/mapgen/greebles/sandplanet.dm b/code/datums/mapgen/greebles/sandplanet.dm index 9a9690f0f80..36824698f61 100644 --- a/code/datums/mapgen/greebles/sandplanet.dm +++ b/code/datums/mapgen/greebles/sandplanet.dm @@ -79,81 +79,81 @@ /datum/map_template/greeble/whitesands/sulfurpool1 name = "Sulfur Greeble 1" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_1.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_1.dmm" /datum/map_template/greeble/whitesands/sulfurpool2 name = "Sulfur Greeble 2" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_2.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_2.dmm" /datum/map_template/greeble/whitesands/sulfurpool3 name = "Sulfur Greeble 3" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_3.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_3.dmm" /datum/map_template/greeble/whitesands/sulfurpool4 name = "Sulfur Greeble 4" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_4.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_4.dmm" /datum/map_template/greeble/whitesands/sulfurpool5 name = "Sulfur Greeble 5" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_5.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_5.dmm" /datum/map_template/greeble/whitesands/sulfurpool6 name = "Sulfur Greeble 6" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_6.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_6.dmm" /datum/map_template/greeble/whitesands/sulfurpool7 name = "Sulfur Greeble 7" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_7.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_7.dmm" /datum/map_template/greeble/whitesands/sulfurpool8 name = "Sulfur Greeble 8" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_8.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_8.dmm" /datum/map_template/greeble/whitesands/sulfurpool9 name = "Sulfur Greeble 9" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_9.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_9.dmm" /datum/map_template/greeble/whitesands/sulfurpool10 name = "Sulfur Greeble 10" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_10.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_10.dmm" /datum/map_template/greeble/whitesands/sulfurpool11 name = "Sulfur Greeble 11" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_11.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_11.dmm" /datum/map_template/greeble/whitesands/sulfurpool12 name = "Sulfur Greeble 12" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_12.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_12.dmm" /datum/map_template/greeble/whitesands/sulfurpool13 name = "Sulfur Greeble 13" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_13.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_13.dmm" /datum/map_template/greeble/whitesands/sulfurpool14 name = "Sulfur Greeble 14" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_14.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_14.dmm" /datum/map_template/greeble/whitesands/sulfurpool15 name = "Sulfur Greeble 15" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_15.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_15.dmm" /datum/map_template/greeble/whitesands/sulfurpool16 name = "Sulfur Greeble 16" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_16.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_16.dmm" /datum/map_template/greeble/whitesands/sulfurpool17 name = "Sulfur Greeble 17" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_17.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_17.dmm" /datum/map_template/greeble/whitesands/sulfurpool18 name = "Sulfur Greeble 18" - mappath = "_maps/templates/greebles/whitesands/sulfur_pool_18.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/sulfur_pool_18.dmm" /obj/effect/greeble_spawner/whitesands/oasis template = /datum/map_template/greeble/whitesands/oasis /datum/map_template/greeble/whitesands/oasis name = "Rare Oasis" - mappath = "_maps/templates/greebles/whitesands/oasis_1.dmm" + mappath = MAPROOT + "/templates/greebles/whitesands/oasis_1.dmm" clear_everything = TRUE diff --git a/code/datums/mapgen/planetary/moon_generator.dm b/code/datums/mapgen/planetary/moon_generator.dm index 85cba567e56..fc8d77c6578 100644 --- a/code/datums/mapgen/planetary/moon_generator.dm +++ b/code/datums/mapgen/planetary/moon_generator.dm @@ -138,24 +138,24 @@ /datum/map_template/greeble/moon/crater1 name = "Crater 1" - mappath = "_maps/templates/greebles/moon_crater1.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater1.dmm" /datum/map_template/greeble/moon/crater2 name = "Crater 2" - mappath = "_maps/templates/greebles/moon_crater2.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater2.dmm" /datum/map_template/greeble/moon/crater3 name = "Crater 3" - mappath = "_maps/templates/greebles/moon_crater3.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater3.dmm" /datum/map_template/greeble/moon/crater4 name = "Crater 4" - mappath = "_maps/templates/greebles/moon_crater4.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater4.dmm" /datum/map_template/greeble/moon/crater5 name = "Crater 5" - mappath = "_maps/templates/greebles/moon_crater5.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater5.dmm" /datum/map_template/greeble/moon/crater6 name = "Crater 6" - mappath = "_maps/templates/greebles/moon_crater6.dmm" + mappath = MAPROOT + "/templates/greebles/moon_crater6.dmm" diff --git a/code/datums/ruins/battlefield.dm b/code/datums/ruins/battlefield.dm index f93f24657b9..5bdbf642c52 100644 --- a/code/datums/ruins/battlefield.dm +++ b/code/datums/ruins/battlefield.dm @@ -1,6 +1,6 @@ ///dummy file in case anyone wants to make ruins/punchcards for this /datum/map_template/ruin/battlefield - prefix = "_maps/RandomRuins/BattleRuins/" + prefix = MAPROOT + "/RandomRuins/BattleRuins/" ruin_type = RUINTYPE_BATTLEFIELD allow_duplicates = FALSE cost = 5 diff --git a/code/datums/ruins/beachplanet.dm b/code/datums/ruins/beachplanet.dm index 1f1eb158468..6e2fd4f5447 100644 --- a/code/datums/ruins/beachplanet.dm +++ b/code/datums/ruins/beachplanet.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/beachplanet - prefix = "_maps/RandomRuins/BeachRuins/" + prefix = MAPROOT + "/RandomRuins/BeachRuins/" ruin_type = RUINTYPE_BEACH /datum/map_template/ruin/beachplanet/ancient diff --git a/code/datums/ruins/desert.dm b/code/datums/ruins/desert.dm index d3371dd538b..86a107deca5 100644 --- a/code/datums/ruins/desert.dm +++ b/code/datums/ruins/desert.dm @@ -1,6 +1,6 @@ ///dummy file in case anyone wants to make ruins/punchcards for this /datum/map_template/ruin/desert - prefix = "_maps/RandomRuins/DesertRuins/" + prefix = MAPROOT + "/RandomRuins/DesertRuins/" ruin_type = RUINTYPE_DESERT allow_duplicates = FALSE cost = 5 diff --git a/code/datums/ruins/icemoon.dm b/code/datums/ruins/icemoon.dm index ac5aa322fd7..ba66cf6e5c5 100644 --- a/code/datums/ruins/icemoon.dm +++ b/code/datums/ruins/icemoon.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/icemoon - prefix = "_maps/RandomRuins/IceRuins/" + prefix = MAPROOT + "/RandomRuins/IceRuins/" ruin_type = RUINTYPE_ICE /datum/map_template/ruin/icemoon/ice_lodge diff --git a/code/datums/ruins/jungle.dm b/code/datums/ruins/jungle.dm index 8c437121002..e58123a64cd 100644 --- a/code/datums/ruins/jungle.dm +++ b/code/datums/ruins/jungle.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/jungle - prefix = "_maps/RandomRuins/JungleRuins/" + prefix = MAPROOT + "/RandomRuins/JungleRuins/" ruin_type = RUINTYPE_JUNGLE /datum/map_template/ruin/jungle/syndicate diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 03ca3b9c742..7ed6e8dbc11 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/lavaland - prefix = "_maps/RandomRuins/LavaRuins/" + prefix = MAPROOT + "/RandomRuins/LavaRuins/" ruin_type = RUINTYPE_LAVA /datum/map_template/ruin/lavaland/biodome/winter diff --git a/code/datums/ruins/moon.dm b/code/datums/ruins/moon.dm index d9fcf5866b6..95b538f13e5 100644 --- a/code/datums/ruins/moon.dm +++ b/code/datums/ruins/moon.dm @@ -1,5 +1,5 @@ /datum/map_template/ruin/moon - prefix = "_maps/RandomRuins/MoonRuins/" + prefix = MAPROOT + "/RandomRuins/MoonRuins/" ruin_type = RUINTYPE_MOON diff --git a/code/datums/ruins/reebe.dm b/code/datums/ruins/reebe.dm index d1a9de3e024..7fe0aa9ddfd 100644 --- a/code/datums/ruins/reebe.dm +++ b/code/datums/ruins/reebe.dm @@ -1,5 +1,5 @@ /datum/map_template/ruin/reebe - prefix = "_maps/RandomRuins/ReebeRuins/" + prefix = MAPROOT + "/RandomRuins/ReebeRuins/" allow_duplicates = FALSE cost = 5 ruin_type = RUINTYPE_YELLOW diff --git a/code/datums/ruins/rockplanet.dm b/code/datums/ruins/rockplanet.dm index f95d0af429b..b14ae2575dd 100644 --- a/code/datums/ruins/rockplanet.dm +++ b/code/datums/ruins/rockplanet.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/rockplanet - prefix = "_maps/RandomRuins/RockRuins/" + prefix = MAPROOT + "/RandomRuins/RockRuins/" ruin_type = RUINTYPE_ROCK diff --git a/code/datums/ruins/shrouded.dm b/code/datums/ruins/shrouded.dm index 164a0e930e5..0a19ff8edd8 100644 --- a/code/datums/ruins/shrouded.dm +++ b/code/datums/ruins/shrouded.dm @@ -1,6 +1,6 @@ ///dummy file in case anyone wants to make ruins/punchcards for this /datum/map_template/ruin/shrouded - prefix = "_maps/RandomRuins/ShroudRuins/" + prefix = MAPROOT + "/RandomRuins/ShroudRuins/" ruin_type = RUINTYPE_SHROUDED allow_duplicates = FALSE cost = 5 diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm index 6a03372f279..4a3f3ec3093 100644 --- a/code/datums/ruins/space.dm +++ b/code/datums/ruins/space.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/space - prefix = "_maps/RandomRuins/SpaceRuins/" + prefix = MAPROOT + "/RandomRuins/SpaceRuins/" cost = 1 allow_duplicates = FALSE ruin_type = RUINTYPE_SPACE diff --git a/code/datums/ruins/wasteplanet.dm b/code/datums/ruins/wasteplanet.dm index 5f119ecbf68..910bf0ac397 100644 --- a/code/datums/ruins/wasteplanet.dm +++ b/code/datums/ruins/wasteplanet.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/wasteplanet - prefix = "_maps/RandomRuins/WasteRuins/" + prefix = MAPROOT + "/RandomRuins/WasteRuins/" ruin_type = RUINTYPE_WASTE /datum/map_template/ruin/wasteplanet/radiation diff --git a/code/datums/ruins/water.dm b/code/datums/ruins/water.dm index e276bdd2be0..6571bc65758 100644 --- a/code/datums/ruins/water.dm +++ b/code/datums/ruins/water.dm @@ -1,6 +1,6 @@ ///dummy file in case anyone wants to make ruins/punchcards for this /datum/map_template/ruin/water - prefix = "_maps/RandomRuins/WaterRuins/" + prefix = MAPROOT + "/RandomRuins/WaterRuins/" ruin_type = RUINTYPE_WATER allow_duplicates = FALSE cost = 5 diff --git a/code/datums/ruins/whitesands.dm b/code/datums/ruins/whitesands.dm index fbd9200c368..e3b49ffc7cf 100644 --- a/code/datums/ruins/whitesands.dm +++ b/code/datums/ruins/whitesands.dm @@ -1,7 +1,7 @@ // Hey! Listen! Update _maps\map_catalogue.txt with your new ruins! /datum/map_template/ruin/whitesands - prefix = "_maps/RandomRuins/SandRuins/" + prefix = MAPROOT + "/RandomRuins/SandRuins/" ruin_type = RUINTYPE_SAND /datum/map_template/ruin/whitesands/pubbyslopcrash diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index 97979c8c57c..13a59b4aa60 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -55,7 +55,7 @@ if(path) mappath = path else if(category && file_name) - mappath = "_maps/shuttles/[category]/[file_name].dmm" + mappath = MAPROOT + "/shuttles/[category]/[file_name].dmm" . = ..() /datum/map_template/shuttle/preload_size(path, cache) diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm index 6cd5a217571..1e9be9da05e 100644 --- a/code/modules/mining/shelters.dm +++ b/code/modules/mining/shelters.dm @@ -37,7 +37,7 @@ built-in navigation, entertainment, medical facilities and a \ sleeping area! Order now, and we'll throw in a TINY FAN, \ absolutely free!" - mappath = "_maps/templates/shelter_1.dmm" + mappath = MAPROOT + "/templates/shelter_1.dmm" /datum/map_template/shelter/beta name = "Shelter Beta" @@ -47,7 +47,7 @@ running water, a gourmet three course meal, cooking facilities, \ and a deluxe companion to keep you from getting lonely during \ an ash storm." - mappath = "_maps/templates/shelter_2.dmm" + mappath = MAPROOT + "/templates/shelter_2.dmm" /datum/map_template/shelter/charlie name = "Shelter Charlie" @@ -57,4 +57,4 @@ also has a sink. This isn't a survival capsule and so you can \ expect that this won't save you if you're bleeding out to \ death." - mappath = "_maps/templates/shelter_3.dmm" + mappath = MAPROOT + "/templates/shelter_3.dmm" diff --git a/code/modules/overmap/objects/outpost/outpost_types.dm b/code/modules/overmap/objects/outpost/outpost_types.dm index 994e0a94f29..7fa028d1ef3 100644 --- a/code/modules/overmap/objects/outpost/outpost_types.dm +++ b/code/modules/overmap/objects/outpost/outpost_types.dm @@ -12,7 +12,7 @@ var/outpost_administrator = "Fallback Administration" /datum/map_template/outpost/New() - . = ..(path = "_maps/outpost/[name].dmm") + . = ..(path = MAPROOT + "/outpost/[name].dmm") /datum/map_template/outpost/hangar var/dock_width diff --git a/code/modules/overmap/star_systems/safezone.dm b/code/modules/overmap/star_systems/safezone.dm index 44e62fb626d..277d0433b9e 100644 --- a/code/modules/overmap/star_systems/safezone.dm +++ b/code/modules/overmap/star_systems/safezone.dm @@ -143,7 +143,7 @@ can_jump_to = FALSE //the json file itself, you can change the directory of this if '_maps/sectors/*_starsystem.json' isn't a good enough naming scheme - json = '_maps/sectors/teagarden_starsystem.json' + json = MAPROOT + "/sectors/teagarden_starsystem.json" //to avoid loading shit on top of hte map, and to copy the system information from the file generator_type = OVERMAP_GENERATOR_JSON diff --git a/modular_starfly/modules/starfly_ships/README.md b/modular_starfly/modules/starfly_maps/README.md similarity index 83% rename from modular_starfly/modules/starfly_ships/README.md rename to modular_starfly/modules/starfly_maps/README.md index ed2dfae3857..895c7a157f5 100644 --- a/modular_starfly/modules/starfly_ships/README.md +++ b/modular_starfly/modules/starfly_maps/README.md @@ -1,11 +1,11 @@ -# Starfly-13 Ships +# Starfly-13 Maps -Module ID: `STARFLY_SHIPS` +Module ID: `STARFLY_MAPS` ## Description -Removes non-lore ships and ship configurations in a modular way. New ships will -appear in thier own modules. +Module layers STARFLY-13 maps over upstream maps, and removes non-lore maps +from the game. ### Usage @@ -17,16 +17,16 @@ module providing a new file will take precedence over upstream. Modules that provide identical filenames will conflict with each other. Those conflicts must be resolved between the modules if you expect the ships to work properly. -Finally, anything defined in this module `STARFLY_SHIPS` will be deleted from +Finally, anything defined in this module `STARFLY_MAPS` will be deleted from the `_maps` directory. By providing a file like `_maps/configs/srm_elder.json` in this module, we instruct the build process to remove that file from the codebase at build time. It will not be present in the game. #### tl;dr -- Add your new ships under `_maps` in your own new modular_starfly modules. +- Add your new maps under `_maps` in your own new modular_starfly modules. -- Add empty files in this module `STARFLY_SHIPS` if you want to DELETE a ship +- Add empty files in this module `STARFLY_MAPS` if you want to DELETE a ship from the Starfly version of the game. ## TG Proc/File Changes diff --git a/modular_starfly/modules/starfly_ships/_maps/configs/srm_elder.json b/modular_starfly/modules/starfly_maps/_maps/configs/srm_elder.json similarity index 100% rename from modular_starfly/modules/starfly_ships/_maps/configs/srm_elder.json rename to modular_starfly/modules/starfly_maps/_maps/configs/srm_elder.json diff --git a/modular_starfly/modules/starfly_ships/_maps/configs/srm_sojourner.json b/modular_starfly/modules/starfly_maps/_maps/configs/srm_sojourner.json similarity index 100% rename from modular_starfly/modules/starfly_ships/_maps/configs/srm_sojourner.json rename to modular_starfly/modules/starfly_maps/_maps/configs/srm_sojourner.json diff --git a/modular_starfly/modules/starfly_ships/maps.sh b/modular_starfly/modules/starfly_ships/maps.sh deleted file mode 100755 index c1226a0b291..00000000000 --- a/modular_starfly/modules/starfly_ships/maps.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -# maps.sh - -set -euo pipefail - -# if this module isn't enabled, just bail out here (no error) -if ! grep -q '^#define STARFLY13_MODULE_STARFLY_SHIPS_ENABLED$' code/__DEFINES/__starfly.dm; then - exit 0 -fi - -# define some useful stuff -dest_maps="_maps" -modules_root="modular_starfly/modules" -starfly_maps="$modules_root/starfly_ships/_maps" - -# if _maps doesn't exist, just bail out here (error) -[[ -d "$dest_maps" ]] || { echo "ERROR: $dest_maps not found" >&2; exit 1; } - -# otherwise, its time to build up the custom maps staging directory -export STARFLY_MAPS_DIR=".staging/_maps" - -# ensure staging directory exists and is clean -rm -rf "$STARFLY_MAPS_DIR" -mkdir -p "$STARFLY_MAPS_DIR" - -# copy the original maps into our staging directory -echo "Copying: $dest_maps -> $STARFLY_MAPS_DIR/" -cp -a "$dest_maps"/. "$STARFLY_MAPS_DIR"/ - -# copy the custom maps provided by every other module -shopt -s nullglob -for module_dir in "$modules_root"/*/; do - [[ "${module_dir%/}" == "$modules_root/starfly_ships" ]] && continue - maps_dir="${module_dir%/}/_maps" - - [[ -d "$maps_dir" ]] || continue - - echo "Merging: $maps_dir -> $STARFLY_MAPS_DIR/" - cp -a "$maps_dir"/. "$STARFLY_MAPS_DIR"/ -done - -# remove all the maps specified by this module -if [[ -d "$starfly_maps" ]]; then - ( - cd "$starfly_maps" - find . -type f -mindepth 1 -depth -print0 - ) | while IFS= read -r -d '' relpath; do - echo "Removing: $STARFLY_MAPS_DIR/$relpath" - rm -rf "$STARFLY_MAPS_DIR/$relpath" - done -fi diff --git a/shiptest.dme b/shiptest.dme index 67197ed12a9..8e3c61bd905 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -19,6 +19,7 @@ #include "code\_compile_options.dm" #include "code\world.dm" #include "code\__DEFINES\__starfly.dm" +#include "code\__DEFINES\__starflymaps.dm" #include "code\__DEFINES\_click.dm" #include "code\__DEFINES\_globals.dm" #include "code\__DEFINES\_helpers.dm" diff --git a/tgui/packages/tgui/starfly.ts b/tgui/packages/tgui/starfly.ts index c683e0deaf0..52fc91b55ab 100644 --- a/tgui/packages/tgui/starfly.ts +++ b/tgui/packages/tgui/starfly.ts @@ -32,6 +32,6 @@ export const STARFLY13 = { MODULE_ROSEUS_GALACTIC_ENABLED: true, MODULE_SINTA_UNATHI_ENABLED: true, MODULE_STARFLY_BRANDING_ENABLED: true, - MODULE_STARFLY_SHIPS_ENABLED: true, + MODULE_STARFLY_MAPS_ENABLED: true, MODULE_YEOSA_UNATHI_ENABLED: true, }; diff --git a/tools/build/build b/tools/build/build index f6af20fdcc2..0e202e1bba7 100755 --- a/tools/build/build +++ b/tools/build/build @@ -1,5 +1,4 @@ #!/bin/sh set -e -modular_starfly/modules/starfly_ships/maps.sh cd "$(dirname "$0")" exec ../bootstrap/node build.js "$@" diff --git a/tools/build/build.js b/tools/build/build.js index 6624c566bdf..02c11ac6431 100755 --- a/tools/build/build.js +++ b/tools/build/build.js @@ -12,6 +12,7 @@ import { env } from "process"; import Juke from "./juke/index.js"; import { DreamDaemon, DreamMaker, NamedVersionFile } from "./lib/byond.js"; import { yarn } from "./lib/yarn.js"; +import buildLayeredMaps from "./lib/maps.js"; Juke.chdir("../..", import.meta.url); Juke.setup({ file: import.meta.url }).then((code) => { @@ -26,24 +27,6 @@ Juke.setup({ file: import.meta.url }).then((code) => { const DME_NAME = "shiptest"; -//--------------------------------------------------------------------------------------------------------------------- -// STARFLY EDIT - ADDITION BEGIN -// #ifdef STARFLY13_MODULE_STARFLY_SHIPS_ENABLED -//--------------------------------------------------------------------------------------------------------------------- -const DEFAULT_MAPS_DIR = "_maps"; -const STAGED_MAPS_DIR = process.env.STARFLY_MAPS_DIR; // e.g. ".staging/_maps" - -// Use staged maps dir if provided AND it exists; otherwise normal _maps -const MAPS_DIR = - STAGED_MAPS_DIR && fs.existsSync(STAGED_MAPS_DIR) ? STAGED_MAPS_DIR : DEFAULT_MAPS_DIR; - -const mapsPath = (p) => `${MAPS_DIR}/${p}`; -const stripMapsPrefix = (p) => p.replace(`${MAPS_DIR}/`, ""); -//--------------------------------------------------------------------------------------------------------------------- -// #endif // #ifdef STARFLY13_MODULE_ADMIN_VERB_FREEZE_ENABLED -// STARFLY EDIT - ADDITION END -//--------------------------------------------------------------------------------------------------------------------- - export const DefineParameter = new Juke.Parameter({ type: "string[]", alias: "D", @@ -80,7 +63,7 @@ export const DmMapsIncludeTarget = new Juke.Target({ ]; const content = folders - .map(stripMapsPrefix) + .map((file) => file.replace("_maps/", "")) .map((file) => `#include "${file}"`) .join("\n") + "\n"; fs.writeFileSync("_maps/templates.dm", content); @@ -98,11 +81,12 @@ export const DmTarget = new Juke.Target({ get(DefineParameter).includes("ALL_MAPS") && DmMapsIncludeTarget, ], inputs: [ - mapsPath("map_files/**"), + "_maps/map_files/**", "code/**", "html/**", "icons/**", "interface/**", + "modular_starfly/modules/**", `${DME_NAME}.dme`, NamedVersionFile, ], @@ -113,6 +97,12 @@ export const DmTarget = new Juke.Target({ return [`${DME_NAME}.dmb`, `${DME_NAME}.rsc`]; }, executes: async ({ get }) => { + const layered = await buildLayeredMaps({ + projectRoot: process.cwd(), + outputMapsDir: "_maps2eb", + logger: Juke.logger, + }); + await DreamMaker(`${DME_NAME}.dme`, { defines: ["CBT", ...get(DefineParameter)], warningsAsErrors: get(WarningParameter).includes("error"), diff --git a/tools/build/lib/maps.js b/tools/build/lib/maps.js new file mode 100644 index 00000000000..132df8d1b2a --- /dev/null +++ b/tools/build/lib/maps.js @@ -0,0 +1,197 @@ +// maps.js +// Copyright 2026 Patrick Meade. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import fs from "fs"; +import path from "path"; + +const fsp = fs.promises; + +async function pathExists(p) { + try { + await fsp.access(p); + return true; + } catch { + return false; + } +} + +async function isDirectory(p) { + try { + const st = await fsp.stat(p); + return st.isDirectory(); + } catch { + return false; + } +} + +async function mkdirp(dir) { + await fsp.mkdir(dir, { recursive: true }); +} + +async function removeTree(target) { + await fsp.rm(target, { recursive: true, force: true }); +} + +async function copyTree(src, dest) { + if (!(await isDirectory(src))) { + return; + } + + await mkdirp(dest); + + const entries = await fsp.readdir(src, { withFileTypes: true }); + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + await copyTree(srcPath, destPath); + } else if (entry.isFile()) { + await mkdirp(path.dirname(destPath)); + await fsp.copyFile(srcPath, destPath); + } else if (entry.isSymbolicLink()) { + // Optional: preserve symlinks if they ever appear. + const linkTarget = await fsp.readlink(srcPath); + await mkdirp(path.dirname(destPath)); + try { + await fsp.symlink(linkTarget, destPath); + } catch { + // On Windows this may fail depending on permissions. + // Fall back to copying the linked file if possible. + const realSrc = await fsp.realpath(srcPath); + const st = await fsp.stat(realSrc); + if (st.isDirectory()) { + await copyTree(realSrc, destPath); + } else { + await fsp.copyFile(realSrc, destPath); + } + } + } + } +} + +async function* walkFiles(root, base = root) { + if (!(await isDirectory(root))) { + return; + } + + const entries = await fsp.readdir(root, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(root, entry.name); + if (entry.isDirectory()) { + yield* walkFiles(fullPath, base); + } else if (entry.isFile() || entry.isSymbolicLink()) { + yield path.relative(base, fullPath); + } + } +} + +async function removeMatchesFromTree(removalsRoot, destRoot, logger = console) { + if (!(await isDirectory(removalsRoot))) { + return; + } + + for await (const relPath of walkFiles(removalsRoot)) { + const targetPath = path.join(destRoot, relPath); + logger.info?.(`Removing: ${targetPath}`) ?? logger.log(`Removing: ${targetPath}`); + await fsp.rm(targetPath, { recursive: true, force: true }); + } +} + +async function readText(file) { + return await fsp.readFile(file, "utf8"); +} + +export async function buildLayeredMaps({ + projectRoot = process.cwd(), + definesFile = path.join("code", "__DEFINES", "__starfly.dm"), + moduleEnableDefine = "STARFLY13_MODULE_STARFLY_MAPS_ENABLED", + upstreamMapsDir = "_maps", + modulesRoot = path.join("modular_starfly", "modules"), + removalModuleName = "starfly_maps", + outputMapsDir = "_maps2eb", + logger = console, +} = {}) { + const definesPath = path.resolve(projectRoot, definesFile); + const upstreamMapsPath = path.resolve(projectRoot, upstreamMapsDir); + const modulesRootPath = path.resolve(projectRoot, modulesRoot); + const removalMapsPath = path.join(modulesRootPath, removalModuleName, "_maps"); + const outputMapsPath = path.resolve(projectRoot, outputMapsDir); + + // If the module isn't enabled, bail out with success. + if (!(await pathExists(definesPath))) { + throw new Error(`Defines file not found: ${definesPath}`); + } + + const definesText = await readText(definesPath); + const defineLine = `#define ${moduleEnableDefine}`; + if (!definesText.split(/\r?\n/).includes(defineLine)) { + logger.info?.( + `Skipping layered maps build; ${moduleEnableDefine} is not enabled.` + ) ?? logger.log(`Skipping layered maps build; ${moduleEnableDefine} is not enabled.`); + return { + enabled: false, + outputMapsDir: outputMapsPath, + }; + } + + if (!(await isDirectory(upstreamMapsPath))) { + throw new Error(`Upstream maps directory not found: ${upstreamMapsPath}`); + } + + logger.info?.(`Preparing layered maps in: ${outputMapsPath}`) ?? + logger.log(`Preparing layered maps in: ${outputMapsPath}`); + + await removeTree(outputMapsPath); + await mkdirp(outputMapsPath); + + logger.info?.(`Copying: ${upstreamMapsPath} -> ${outputMapsPath}`) ?? + logger.log(`Copying: ${upstreamMapsPath} -> ${outputMapsPath}`); + await copyTree(upstreamMapsPath, outputMapsPath); + + if (await isDirectory(modulesRootPath)) { + const moduleEntries = await fsp.readdir(modulesRootPath, { withFileTypes: true }); + + for (const entry of moduleEntries) { + if (!entry.isDirectory()) { + continue; + } + + if (entry.name === removalModuleName) { + continue; + } + + const moduleMapsPath = path.join(modulesRootPath, entry.name, "_maps"); + if (!(await isDirectory(moduleMapsPath))) { + continue; + } + + logger.info?.(`Merging: ${moduleMapsPath} -> ${outputMapsPath}`) ?? + logger.log(`Merging: ${moduleMapsPath} -> ${outputMapsPath}`); + await copyTree(moduleMapsPath, outputMapsPath); + } + } + + await removeMatchesFromTree(removalMapsPath, outputMapsPath, logger); + + return { + enabled: true, + outputMapsDir: outputMapsPath, + maprootDefine: outputMapsDir, + }; +} + +export default buildLayeredMaps; diff --git a/tools/deploy.sh b/tools/deploy.sh index b7bfa4b64c5..62721c16fdd 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -4,13 +4,15 @@ #First arg is path to where you want to deploy #creates a work tree free of everything except what's necessary to run the game +MAPROOT="${MAPROOT:=_maps2eb}" + #second arg is working directory if necessary if [[ $# -eq 2 ]] ; then cd $2 fi mkdir -p \ - $1/_maps \ + $1/${MAPROOT} \ $1/icons/runtime \ $1/sound/runtime \ $1/strings \ @@ -23,7 +25,7 @@ if [ -d ".git" ]; then fi cp shiptest.dmb shiptest.rsc $1/ -cp -r _maps/* $1/_maps/ +cp -r ${MAPROOT}/* $1/${MAPROOT}/ cp -r icons/runtime/* $1/icons/runtime/ cp -r sound/runtime/* $1/sound/runtime/ cp -r strings/* $1/strings/ diff --git a/tools/maplint/source/__main__.py b/tools/maplint/source/__main__.py index dcb575e99bd..e5b171d3920 100644 --- a/tools/maplint/source/__main__.py +++ b/tools/maplint/source/__main__.py @@ -1,5 +1,6 @@ import argparse import glob +import os import pathlib import traceback import yaml @@ -13,6 +14,14 @@ def green(text): def red(text): return "\033[31m" + str(text) + "\033[0m" +def get_map_folder(): + try: + map_folder = os.environ['MAPROOT'] + except KeyError: + map_folder = '_maps' + + return map_folder + def process_dmm(map_filename, lints: dict[str, lint.Lint]) -> list[MaplintError]: problems: list[MaplintError] = [] @@ -75,7 +84,8 @@ def main(args): traceback.print_exc() any_failed = True - for map_filename in (args.maps or glob.glob("_maps/**/*.dmm", recursive = True)): + map_folder = get_map_folder() + for map_filename in (args.maps or glob.glob(f"{map_folder}/**/*.dmm", recursive = True)): print(map_filename, end = " ") success = True diff --git a/tools/starfly/ci/check_grep.sh b/tools/starfly/ci/check_grep.sh new file mode 100755 index 00000000000..08c66c8178b --- /dev/null +++ b/tools/starfly/ci/check_grep.sh @@ -0,0 +1,305 @@ +#!/bin/bash +set -euo pipefail + +#nb: must be bash to support shopt globstar +shopt -s globstar extglob + +MAPROOT="${MAPROOT:=_maps2eb}" + +#ANSI Escape Codes for colors to increase contrast of errors +RED="\033[0;31m" +GREEN="\033[0;32m" +BLUE="\033[0;34m" +NC="\033[0m" # No Color + +st=0 + +# check for ripgrep +if command -v rg >/dev/null 2>&1; then + grep=rg + pcre2_support=1 + if [ ! rg -P '' >/dev/null 2>&1 ] ; then + pcre2_support=0 + fi + code_files="code/**/**.dm" + map_files="${MAPROOT}/**/**.dmm" + code_x_515="code/**/!(__byond_version_compat).dm" +else + pcre2_support=0 + grep=grep + code_files="-r --include=code/**/**.dm" + map_files="-r --include=${MAPROOT}/**/**.dmm" + code_x_515="-r --include=code/**/!(__byond_version_compat).dm" +fi + +echo -e "${BLUE}Using grep provider at $(which $grep)${NC}" + +part=0 +section() { + echo -e "${BLUE}Checking for $1${NC}..." + part=0 +} + +part() { + part=$((part+1)) + padded=$(printf "%02d" $part) + echo -e "${GREEN} $padded- $1${NC}" +} + +section "map issues" + +part "TGM" +if $grep -U '^".+" = \(.+\)' $map_files; then + echo + echo -e "${RED}ERROR: Non-TGM formatted map detected. Please convert it using Map Merger!${NC}" + st=1 +fi; +part "comments" +if $grep '//' $map_files | $grep -v '//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE' | $grep -v 'name|desc'; then + echo + echo -e "${RED}ERROR: Unexpected commented out line detected in this map file. Please remove it.${NC}" + st=1 +fi; +part "iconstate tags" +if $grep '^\ttag = "icon' $map_files; then + echo + echo -e "${RED}ERROR: Tag vars from icon state generation detected in maps, please remove them.${NC}" + st=1 +fi; +part "invalid map procs" +if $grep '(new|newlist|icon|matrix|sound)\(.+\)' $map_files; then + echo + echo -e "${RED}ERROR: Using unsupported procs in variables in a map file! Please remove all instances of this.${NC}" + st=1 +fi; +part "common spelling mistakes" +if $grep -i 'nanotransen' $map_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of Nanotrasen detected in maps, please remove the extra N(s).${NC}" + st=1 +fi; +if $grep 'NanoTrasen' $map_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of Nanotrasen detected in maps, please uncapitalize the T(s).${NC}" + st=1 +fi; +if $grep -i'centcomm' $map_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of CentCom detected in maps, please remove the extra M(s).${NC}" + st=1 +fi; +if $grep 'Solgov' $map_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of SolGov detected in maps, please capitalize the G(s).${NC}" + st=1 +fi; +if $grep 'Solcon' $map_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of SolCon detected in maps, please capitalize the C(s).${NC}" + st=1 +fi; +if $grep -- '-Class' $map_files; then + echo + echo -e "${RED}ERROR: Misspellings(s) of -class detected in maps, please uncapitalize the C(s).${NC}" + st=1 +fi; + +section "whitespace issues" +part "space indentation" +if $grep '(^ {2})|(^ [^ * ])|(^ +)' $code_files; then + echo + echo -e "${RED}ERROR: Space indentation detected, please use tab indentation.${NC}" + st=1 +fi; +part "mixed indentation" +if $grep '^\t+ [^ *]' $code_files; then + echo + echo -e "${RED}ERROR: Mixed indentation detected, please stick to tab indentation.${NC}" + st=1 +fi; + +#section "unit tests" +#unit_test_files="code/modules/unit_tests/**/**.dm" +#part "mob/living/carbon/human usage" +#if $grep 'allocate\(/mob/living/carbon/human[,\)]' $unit_test_files || +# $grep 'new /mob/living/carbon/human\s?\(' $unit_test_files || +# $grep 'var/mob/living/carbon/human/\w+\s?=\s?new' $unit_test_files ; then +# echo +# echo -e "${RED}ERROR: Usage of mob/living/carbon/human detected in a unit test, please use mob/living/carbon/human/consistent.${NC}" +# st=1 +#fi; + +section "common mistakes" +part "global vars" +if $grep '^/*var/' $code_files; then + echo + echo -e "${RED}ERROR: Unmanaged global var use detected in code, please use the helpers.${NC}" + st=1 +fi; + +part "proc args with var/" +if $grep '^/[\w/]\S+\(.*(var/|, ?var/.*).*\)' $code_files; then + echo + echo -e "${RED}ERROR: Changed files contains a proc argument starting with 'var'.${NC}" + st=1 +fi; + +part "src as a trait source" # ideally we'd lint / test for ANY datum reference as a trait source, but 'src' is the most common. +if $grep -i '(add_trait|remove_trait)\(.+,\s*.+,\s*src\)' $code_files; then + echo + echo -e "${RED}ERROR: Using 'src' as a trait source. Source must be a string key - dont't use references to datums as a source, perhaps use 'REF(src)'.${NC}" + st=1 +fi; +if $grep -i '(add_traits|remove_traits)\(.+,\s*src\)' $code_files; then + echo + echo -e "${RED}ERROR: Using 'src' as trait sources. Source must be a string key - dont't use references to datums as sources, perhaps use 'REF(src)'.${NC}" + st=1 +fi; + +part "balloon_alert sanity" +if $grep 'balloon_alert\(".*"\)' $code_files; then + echo + echo -e "${RED}ERROR: Found a balloon alert with improper arguments.${NC}" + st=1 +fi; + +if $grep 'balloon_alert(.*span_)' $code_files; then + echo + echo -e "${RED}ERROR: Balloon alerts should never contain spans.${NC}" + st=1 +fi; + +part "balloon_alert idiomatic usage" +if $grep 'balloon_alert\(.*?, ?"[A-Z]' $code_files; then + echo + echo -e "${RED}ERROR: Balloon alerts should not start with capital letters. This includes text like 'AI'. If this is a false positive, wrap the text in UNLINT().${NC}" + st=1 +fi; + +part "update_icon_updates_onmob element usage" +if $grep 'AddElement\(/datum/element/update_icon_updates_onmob.+ITEM_SLOT_HANDS' $code_files; then + echo + echo -e "${RED}ERROR: update_icon_updates_onmob element automatically updates ITEM_SLOT_HANDS, this is redundant and should be removed.${NC}" + st=1 +fi; + +part "common spelling mistakes" +if $grep -i 'centcomm' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of CentCom detected in code, please remove the extra M(s).${NC}" + st=1 +fi; +if $grep -ni 'nanotransen' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of Nanotrasen detected in code, please remove the extra N(s).${NC}" + st=1 +fi; +if $grep 'NanoTrasen' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of Nanotrasen detected in code, please uncapitalize the T(s).${NC}" + st=1 +fi; +if $grep 'Solgov' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of SolGov detected in code, please capitalize the G(s).${NC}" + st=1 +fi; +if $grep 'Solcon' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of SolCon detected in code, please capitalize the C(s).${NC}" + st=1 +fi; +if $grep 'indestructable' $code_files; then + echo + echo -e "${RED}ERROR: Misspelling(s) of indestructible detected in code, it is indestructIBLE not indestructABLE.${NC}" + st=1 +fi; + +part "map json sanity" +if command -v jq >/dev/null 2>&1; then + for json in ${MAPROOT}/configs/*.json + do + map_path=$(jq -r '.map_path' $json) + if [ ! -f $map_path ] + then + echo + echo -e "${RED}ERROR: Found an invalid file reference to $map_path in $json ${NC}" + st=1 + fi + done +else + echo -e "${RED}jq not found, skipping map json checks${NC}" +fi + +part "updatepaths validity" +missing_txt_lines=$(find tools/UpdatePaths/Scripts -type f ! -name "*.txt" | wc -l) +if [ $missing_txt_lines -gt 0 ]; then + echo + echo -e "${RED}ERROR: Found an UpdatePaths File that doesn't end in .txt! Please add the proper file extension!${NC}" + st=1 +fi; + +number_prefix_lines=$(find tools/UpdatePaths/Scripts -type f | wc -l) +valid_number_prefix_lines=$(find tools/UpdatePaths/Scripts -type f | $grep -P "\d+_(.+)" | wc -l) +if [ $valid_number_prefix_lines -ne $number_prefix_lines ]; then + echo + echo -e "${RED}ERROR: Detected an UpdatePaths File that doesn't start with the PR number! Please add the proper number prefix!${NC}" + st=1 +fi; + +section "515 Proc Syntax" +part "proc ref syntax" +if $grep '\.proc/' $code_x_515 ; then + echo + echo -e "${RED}ERROR: Outdated proc reference use detected in code, please use proc reference helpers.${NC}" + st=1 +fi; + +if [ "$pcre2_support" -eq 1 ]; then + section "regexes requiring PCRE2" + part "empty variable values" + if $grep -PU '{\n\t},' $map_files; then + echo + echo -e "${RED}ERROR: Empty variable value list detected in map file. Please remove the curly brackets entirely.${NC}" + st=1 + fi; + part "to_chat sanity" + if $grep -P 'to_chat\((?!.*,).*\)' $code_files; then + echo + echo -e "${RED}ERROR: to_chat() missing arguments.${NC}" + st=1 + fi; + part "timer flag sanity" + if $grep -P 'addtimer\((?=.*TIMER_OVERRIDE)(?!.*TIMER_UNIQUE).*\)' $code_files; then + echo + echo -e "${RED}ERROR: TIMER_OVERRIDE used without TIMER_UNIQUE.${NC}" + st=1 + fi + part "trailing newlines" + if $grep -PU '[^\n]$(?!\n)' $code_files; then + echo + echo -e "${RED}ERROR: File(s) with no trailing newline detected, please add one.${NC}" + st=1 + fi + #part "improper atom initialize args" + #if $grep -P '^/(obj|mob|turf|area|atom)/.+/Initialize\((?!mapload).*\)' $code_files; then + # echo + # echo -e "${RED}ERROR: Initialize override without 'mapload' argument.${NC}" + # st=1 + #fi; +else + echo -e "${RED}pcre2 not supported, skipping checks requiring pcre2" + echo -e "if you want to run these checks install ripgrep with pcre2 support.${NC}" +fi + +if [ $st = 0 ]; then + echo + echo -e "${GREEN}No errors found using $grep!${NC}" +fi; + +if [ $st = 1 ]; then + echo + echo -e "${RED}Errors found, please fix them and try again.${NC}" +fi; + +exit $st diff --git a/tools/starfly/ci/check_maps_dir.sh b/tools/starfly/ci/check_maps_dir.sh new file mode 100755 index 00000000000..667468e8c2f --- /dev/null +++ b/tools/starfly/ci/check_maps_dir.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# check_maps_dir.sh + +set -euo pipefail + +count=$(fgrep -i -r "\"_maps" code | wc -l) +if [[ "$count" -ne 3 ]]; then + echo "Error: Found $count instances of '\"_maps' expected exactly 3." + fgrep -i -r "\"_maps" code + exit 1 +fi + +count=$(fgrep -i -r " _maps" code | wc -l) +if [[ "$count" -ne 11 ]]; then + echo "Error: Found $count instances of ' _maps' expected exactly 11." + fgrep -i -r " _maps" code + exit 1 +fi + +echo "Success: Hardcoded references to _maps are as expected." diff --git a/tools/starfly/ci/check_misc.sh b/tools/starfly/ci/check_misc.sh new file mode 100644 index 00000000000..54c44dd5d49 --- /dev/null +++ b/tools/starfly/ci/check_misc.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -euo pipefail + +MAPROOT="${MAPROOT:=_maps2eb}" + +find . -name "*.php" -print0 | xargs -0 -n1 php -l +find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py +find ./${MAPROOT}/configs -name "*.json" -not -path "/data/*" -print0 | xargs -0 python3 ./tools/json_schema_validator.py ./${MAPROOT}/ship_config_schema.json diff --git a/tools/starfly/ci/lint.sh b/tools/starfly/ci/lint.sh index 273da0895cb..3253a5edfe8 100755 --- a/tools/starfly/ci/lint.sh +++ b/tools/starfly/ci/lint.sh @@ -11,6 +11,9 @@ echo "# Checking shiptest.dme" echo "## Checking FILE_DIR directives in shiptest.dme" tools/starfly/ci/check_file_dir.sh +echo "## Checking codebase for hardcoded references to _maps" +tools/starfly/ci/check_maps_dir.sh + echo "## Checking include order in shiptest.dme" python3 tools/starfly/python/check_dme_order.py shiptest.dme