From f57851e5f650ec8fc4c5ff05aa3175716433a421 Mon Sep 17 00:00:00 2001 From: Bloop <13398309+vinylspiders@users.noreply.github.com> Date: Wed, 3 Apr 2024 03:03:15 -0400 Subject: [PATCH 1/2] [MISSED MIRROR] Lint with OpenDream (#81892) (#1791) * Lint with OpenDream (#81892) ## About The Pull Request Courtesy of https://github.com/ParadiseSS13/Paradise/pull/21099 and https://github.com/goonstation/goonstation/pull/18127 * Fixes the errors caught by this in our module files --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> --- .github/workflows/ci_suite.yml | 19 +++++++++++ .gitignore | 3 ++ __odlint.dm | 10 ++++++ code/__DEFINES/_helpers.dm | 4 +++ code/__HELPERS/type2type.dm | 8 ++--- code/_compile_options.dm | 17 +++++++--- code/_onclick/item_attack.dm | 4 +-- code/datums/components/food/edible.dm | 2 +- code/datums/wounds/burns.dm | 3 ++ code/game/atom/atom_defense.dm | 9 ++--- .../game/atom/atoms_initializing_EXPENSIVE.dm | 3 +- code/game/machinery/doors/airlock.dm | 5 ++- code/modules/logging/log_holder.dm | 2 +- code/modules/projectiles/projectile.dm | 1 + .../reagents/drinks/drink_reagents.dm | 2 -- .../code/game/objects/items/holy_weapons.dm | 6 ++-- .../modules/borgs/code/robot_model.dm | 2 -- .../modules/mob/living/carbon/human/human.dm | 4 +-- .../code/additionalemotes/turf_emote.dm | 4 +-- tgstation.dme | 1 + tools/ci/od_lints.dm | 33 +++++++++++++++++++ 21 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 __odlint.dm create mode 100644 tools/ci/od_lints.dm diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml index faeb59ba295..9c3eff67f60 100644 --- a/.github/workflows/ci_suite.yml +++ b/.github/workflows/ci_suite.yml @@ -115,6 +115,25 @@ jobs: if: steps.linter-setup.conclusion == 'success' && !cancelled() run: tools/build/build --ci lint tgui-test + odlint: + if: ( !contains(github.event.head_commit.message, '[ci skip]') ) + name: "Lint with OpenDream" + runs-on: ubuntu-22.04 + concurrency: + group: odlint-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v4 + - uses: robinraju/release-downloader@v1.9 + with: + repository: "OpenDreamProject/OpenDream" + tag: "latest" + fileName: "DMCompiler_linux-x64.tar.gz" + extract: true + - name: Run OpenDream + run: | + ./DMCompiler_linux-x64/DMCompiler tgstation.dme --suppress-unimplemented --define=CIBUILDING + compile_all_maps: if: ( !contains(github.event.head_commit.message, '[ci skip]') ) name: Compile Maps diff --git a/.gitignore b/.gitignore index 4c7657fc03c..acd33544c90 100644 --- a/.gitignore +++ b/.gitignore @@ -247,3 +247,6 @@ define_sanity_output.txt # ezdb /db/ /config/ezdb.txt + +# Running OpenDream locally +tgstation.json diff --git a/__odlint.dm b/__odlint.dm new file mode 100644 index 00000000000..b7c120514a1 --- /dev/null +++ b/__odlint.dm @@ -0,0 +1,10 @@ +// This file is included right at the start of the DME. +// Its purpose is to enable multiple lints (pragmas) that are supported by OpenDream to better validate the codebase +// These are essentially nitpicks the DM compiler should pick up on but doesnt + +#if !defined(SPACEMAN_DMM) && defined(OPENDREAM) +// This is in a separate file as a hack to avoid SpacemanDMM +// evaluating the #pragma lines, even if its outside a block it cares about +// (Also so people can code-own it. Shoutout to AA) +#include "tools/ci/od_lints.dm" +#endif diff --git a/code/__DEFINES/_helpers.dm b/code/__DEFINES/_helpers.dm index f1b1b21df33..d9f75fe8e9d 100644 --- a/code/__DEFINES/_helpers.dm +++ b/code/__DEFINES/_helpers.dm @@ -32,3 +32,7 @@ // Custom types that we define don't get a unique id, but this is useful for identifying // types that don't normally have a way to run istype() on them. #define TYPEID(thing) copytext(REF(thing), 4, 6) + +/// A null statement to guard against EmptyBlock lint without necessitating the use of pass() +/// Used to avoid proc-call overhead. But use sparingly. Probably pointless in most places. +#define EMPTY_BLOCK_GUARD ; diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 7e97724b562..9eb1a491f42 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -36,8 +36,8 @@ return "northwest" if(SOUTHWEST) return "southwest" - else - return + + return NONE //Turns text into proper directions /proc/text2dir(direction) @@ -58,8 +58,8 @@ return SOUTHEAST if("SOUTHWEST") return SOUTHWEST - else - return + + return NONE //Converts an angle (degrees) into a ss13 direction GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST,WEST,NORTHWEST)) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 8768a1e3622..0d534fac9a3 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -112,7 +112,7 @@ #warn compiling in TESTING mode. testing() debug messages will be visible. #endif -#ifdef CIBUILDING +#if defined(CIBUILDING) && !defined(OPENDREAM) #define UNIT_TESTS #endif @@ -137,10 +137,17 @@ #define CBT #endif -#if !defined(CBT) && !defined(SPACEMAN_DMM) -#warn Building with Dream Maker is no longer supported and will result in errors. -#warn In order to build, run BUILD.bat in the root directory. -#warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build. +#if defined(OPENDREAM) + #if !defined(CIBUILDING) + #warn You are building with OpenDream. Remember to build TGUI manually. + #warn You can do this by running tgui-build.cmd from the bin directory. + #endif +#else + #if !defined(CBT) && !defined(SPACEMAN_DMM) + #warn Building with Dream Maker is no longer supported and will result in errors. + #warn In order to build, run BUILD.cmd in the root directory. + #warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build. + #endif #endif /// Runs the game in "map test mode" diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index f996e96d36e..eb5de5971d8 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -25,7 +25,7 @@ if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) return TRUE if (SECONDARY_ATTACK_CONTINUE_CHAIN) - // Normal behavior + EMPTY_BLOCK_GUARD // Normal behavior else CRASH("pre_attack_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm") else @@ -43,7 +43,7 @@ if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) return TRUE if (SECONDARY_ATTACK_CONTINUE_CHAIN) - // Normal behavior + EMPTY_BLOCK_GUARD // Normal behavior else CRASH("attackby_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm") else diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index ded8b8c4161..85a6a7e386b 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -251,7 +251,7 @@ Behavior that's still missing from this component that original food items had t if(!(food_flags & FOOD_IN_CONTAINER)) switch(bitecount) if(0) - // pass + pass() if(1) examine_list += span_notice("[owner] was bitten by someone!") if(2, 3) diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 18d710ca0d3..9911ce60714 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -81,11 +81,14 @@ infestation += infestation_rate * seconds_per_tick switch(infestation) if(0 to WOUND_INFECTION_MODERATE) + return + if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) if(SPT_PROB(15, seconds_per_tick)) victim.adjustToxLoss(0.2) if(prob(6)) to_chat(victim, span_warning("The blisters on your [limb.plaintext_zone] ooze a strange pus...")) + if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) if(!disabling) if(SPT_PROB(1, seconds_per_tick)) diff --git a/code/game/atom/atom_defense.dm b/code/game/atom/atom_defense.dm index 8b398313616..3fb69678b36 100644 --- a/code/game/atom/atom_defense.dm +++ b/code/game/atom/atom_defense.dm @@ -94,17 +94,14 @@ CRASH("/atom/proc/run_atom_armor was called on [src] without being implemented as a type that uses integrity!") if(damage_flag == MELEE && damage_amount < damage_deflection) return 0 - switch(damage_type) - if(BRUTE) - if(BURN) - else - return 0 + if(damage_type != BRUTE && damage_type != BURN) + return 0 var/armor_protection = 0 if(damage_flag) armor_protection = get_armor_rating(damage_flag) if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor. armor_protection = clamp(PENETRATE_ARMOUR(armor_protection, armour_penetration), min(armor_protection, 0), 100) - return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION) + return round(damage_amount * (100 - armor_protection) * 0.01, DAMAGE_PRECISION) ///the sound played when the atom is damaged. /atom/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm index ea8bf9b125d..a55666aed9a 100644 --- a/code/game/atom/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -1,5 +1,6 @@ /// Init this specific atom /datum/controller/subsystem/atoms/proc/InitAtom(atom/A, from_template = FALSE, list/arguments) + var/the_type = A.type if(QDELING(A)) @@ -24,7 +25,7 @@ switch(result) if (INITIALIZE_HINT_NORMAL) - // pass + EMPTY_BLOCK_GUARD // Pass if(INITIALIZE_HINT_LATELOAD) if(arguments[1]) //mapload late_loaders += A diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index e38afc75294..87acada7793 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1538,9 +1538,8 @@ if(!disassembled) A?.update_integrity(A.max_integrity * 0.5) - else if(obj_flags & EMAGGED) - //no electronics nothing - else + + else if(!(obj_flags & EMAGGED)) var/obj/item/electronics/airlock/ae if(!electronics) ae = new/obj/item/electronics/airlock(loc) diff --git a/code/modules/logging/log_holder.dm b/code/modules/logging/log_holder.dm index b378e4b8ef3..1102df45f4f 100644 --- a/code/modules/logging/log_holder.dm +++ b/code/modules/logging/log_holder.dm @@ -340,7 +340,7 @@ GENERAL_PROTECT_DATUM(/datum/log_holder) var/datum/data = data_list[key] if(isnull(data)) - // do nothing - nulls are allowed + pass() // nulls are allowed else if(islist(data)) data = recursive_jsonify(data, semvers) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 14abc29de8a..7d345e47ee1 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -361,6 +361,7 @@ organ_hit_text = " in \the [parse_zone(hit_limb_zone)]" if(suppressed == SUPPRESSED_VERY) //playsound(loc, hitsound, 5, TRUE, -1) NOVA EDIT REMOVAL - IMPACT SOUNDS + organ_hit_text = organ_hit_text // NOVA EDIT ADDITION -- this is just so we don't have to nova edit the TG control statements. Otherwise will error in linters for being an empty block else if(suppressed) //playsound(loc, hitsound, 5, TRUE, -1) NOVA EDIT REMOVAL - IMPACT SOUNDS to_chat(living_target, span_userdanger("You're shot by \a [src][organ_hit_text]!")) diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index 23cec75806a..f733bc686f0 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -55,8 +55,6 @@ affected_mob.adjust_temp_blindness(-2 SECONDS * REM * seconds_per_tick) var/need_mob_update switch(current_cycle) - if(1 to 20) - //nothing if(21 to 110) if(SPT_PROB(100 * (1 - (sqrt(110 - current_cycle) / 10)), seconds_per_tick)) need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_EYES, -2 * REM * seconds_per_tick) diff --git a/modular_nova/master_files/code/game/objects/items/holy_weapons.dm b/modular_nova/master_files/code/game/objects/items/holy_weapons.dm index 3abc61d0b76..d952dddde8d 100644 --- a/modular_nova/master_files/code/game/objects/items/holy_weapons.dm +++ b/modular_nova/master_files/code/game/objects/items/holy_weapons.dm @@ -77,8 +77,7 @@ var/narsian = FALSE /obj/item/nullrod/cultdagger/attack_self(mob/user) - if(narsian) - else if(user.mind && (user.mind.holy_role)) + if(!narsian && user.mind && (user.mind.holy_role)) to_chat(user, span_cult_large("\"Partake in the language of blood..\"")) user.grant_language(/datum/language/narsie, source = LANGUAGE_MIND) special_desc_requirement = NONE // No point in keeping something that can't no longer be used @@ -91,8 +90,7 @@ var/narsian = FALSE /obj/item/nullrod/claymore/darkblade/attack_self(mob/user) - if(narsian) - else if(user.mind && (user.mind.holy_role)) + if(!narsian && user.mind && (user.mind.holy_role)) to_chat(user, span_cult_large("\"Partake in the language of blood..\"")) user.grant_language(/datum/language/narsie, source = LANGUAGE_MIND) special_desc_requirement = NONE // No point in keeping something that can't no longer be used diff --git a/modular_nova/modules/borgs/code/robot_model.dm b/modular_nova/modules/borgs/code/robot_model.dm index 3b738c748b2..e979736ab98 100644 --- a/modular_nova/modules/borgs/code/robot_model.dm +++ b/modular_nova/modules/borgs/code/robot_model.dm @@ -19,8 +19,6 @@ switch(cyborg_base_icon) if("mekamine") cyborg.AddComponent(/datum/component/robot_smoke) - else - else cyborg.maptext_height = initial(cyborg.maptext_height) cyborg.RemoveElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE, 2, -6, sound_vary = TRUE) diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/human.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/human.dm index 93f2b8186c9..504979c1112 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/human.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/human.dm @@ -168,12 +168,12 @@ var/list/choices = list() for(var/choice in available_selection) var/datum/radial_menu_choice/option = new - var/image/part_image = image(icon = HIDING_RADIAL_DMI, icon_state = initial(choice)) + var/image/part_image = image(icon = HIDING_RADIAL_DMI, icon_state = choice) option.image = part_image if(choice in try_hide_mutant_parts) part_image.underlays += image(icon = HIDING_RADIAL_DMI, icon_state = "module_unable") - choices[initial(choice)] = option + choices[choice] = option // Radial choices sort_list(choices) var/pick = show_radial_menu(usr, src, choices, custom_check = FALSE, tooltips = TRUE) diff --git a/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm b/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm index ede2feb952c..1a9379b8dcf 100644 --- a/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm +++ b/modular_nova/modules/emotes/code/additionalemotes/turf_emote.dm @@ -81,9 +81,9 @@ for(var/choice in user.allowed_turfs) var/datum/radial_menu_choice/option = new - option.image = image(icon = 'modular_nova/master_files/icons/effects/turf_effects_icons.dmi', icon_state = initial(choice)) + option.image = image(icon = 'modular_nova/master_files/icons/effects/turf_effects_icons.dmi', icon_state = choice) - display_turf[initial(choice)] = option + display_turf[choice] = option sort_list(display_turf) var/chosen_turf = show_radial_menu(user, user, display_turf, custom_check = CALLBACK(src, PROC_REF(check_menu), user)) diff --git a/tgstation.dme b/tgstation.dme index 5d3eca2f650..a43f6cf47b2 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -12,6 +12,7 @@ // END_PREFERENCES // BEGIN_INCLUDE +#include "__odlint.dm" #include "_maps\_basemap.dm" #include "code\__byond_version_compat.dm" #include "code\_compile_options.dm" diff --git a/tools/ci/od_lints.dm b/tools/ci/od_lints.dm new file mode 100644 index 00000000000..e339f5acb2d --- /dev/null +++ b/tools/ci/od_lints.dm @@ -0,0 +1,33 @@ +//1000-1999 +#pragma FileAlreadyIncluded error +#pragma MissingIncludedFile error +#pragma MisplacedDirective error +#pragma UndefineMissingDirective error +#pragma DefinedMissingParen error +#pragma ErrorDirective error +#pragma WarningDirective warning +#pragma MiscapitalizedDirective error + +//2000-2999 +#pragma SoftReservedKeyword error +#pragma DuplicateVariable error +#pragma DuplicateProcDefinition error +#pragma TooManyArguments error +#pragma PointlessParentCall error +#pragma PointlessBuiltinCall error +#pragma SuspiciousMatrixCall error +#pragma FallbackBuiltinArgument error +#pragma MalformedRange error +#pragma InvalidRange error +#pragma InvalidSetStatement error +#pragma InvalidOverride error +#pragma DanglingVarType error +#pragma MissingInterpolatedExpression error +#pragma AmbiguousResourcePath error + +//3000-3999 +#pragma EmptyBlock error +#pragma EmptyProc disabled +#pragma UnsafeClientAccess disabled +#pragma SuspiciousSwitchCase error +#pragma AssignmentInConditional error From a78b678893711a7283c3f0329edc0e1f7e823ccc Mon Sep 17 00:00:00 2001 From: Iajret Date: Thu, 4 Apr 2024 01:03:23 +0300 Subject: [PATCH 2/2] demodularization --- code/modules/admin/create_mob.dm | 6 ++++++ tff_modular/modules/blooper/atoms_movable.dm | 7 ------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 6eef8e8f7d1..6bf718de810 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -35,3 +35,9 @@ // Snowflake for Ethereals human.updatehealth() human.updateappearance(mutcolor_update = TRUE) + // FLUFFY FRONTIER ADDITION START + human.set_blooper(pick(GLOB.blooper_list)) + human.blooper_pitch = BLOOPER_PITCH_RAND(human.gender) + human.blooper_pitch_range = BLOOPER_VARIANCE_RAND + human.blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED) + // FLUFFY FRONTIER ADDITION END diff --git a/tff_modular/modules/blooper/atoms_movable.dm b/tff_modular/modules/blooper/atoms_movable.dm index a7446f60efb..26c92cb0310 100644 --- a/tff_modular/modules/blooper/atoms_movable.dm +++ b/tff_modular/modules/blooper/atoms_movable.dm @@ -59,13 +59,6 @@ blooper_pitch_range = BLOOPER_VARIANCE_RAND blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED) -/randomize_human(mob/living/carbon/human/human, randomize_mutations = FALSE) - . = ..() - human.set_blooper(pick(GLOB.blooper_list)) - human.blooper_pitch = BLOOPER_PITCH_RAND(human.gender) - human.blooper_pitch_range = BLOOPER_VARIANCE_RAND - human.blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED) - /mob/living/send_speech(message_raw, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language = null, list/message_mods = list(), forced = null, tts_message, list/tts_filter) . = ..() if(client)