From fa92191fc03048da8197f21b69c10b05336e7702 Mon Sep 17 00:00:00 2001 From: AyeZeeBB Date: Sat, 3 Oct 2026 02:04:15 -0500 Subject: [PATCH] badword fix --- Engine/Core/Text/Test/word_filter_tests.cpp | 8 ++++++++ Engine/Core/Text/bad_words.txt | 8 ++++++++ Engine/Core/Text/word_filter.cpp | 20 ++++++++++--------- .../Multiplayer/Session/session_commands.cpp | 8 +++++++- Extension/Multiplayer/Steam/steam_lobbies.cpp | 8 ++++++-- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/Engine/Core/Text/Test/word_filter_tests.cpp b/Engine/Core/Text/Test/word_filter_tests.cpp index 52285f52..1cdae7c3 100644 --- a/Engine/Core/Text/Test/word_filter_tests.cpp +++ b/Engine/Core/Text/Test/word_filter_tests.cpp @@ -37,6 +37,9 @@ int main() { bad("f u c k"); bad("F.U.C.K. yeah"); bad("b17ch"); + bad("evil ass rape server"); + bad("Rapist Crew"); + bad("gangrape lobby"); // Ordinary words that contain a listed word, and server names people use. clean("Hello World"); clean("Shell Shock Skatepark"); @@ -56,6 +59,11 @@ int main() { clean("Essex Street League"); clean("Pakistan Plaza"); clean("Scrapyard DIY"); + clean("Grape Street Bowl"); + clean("Scraped Knees Crew"); + clean("Trapeze Transfers"); + clean("Draping the rails"); + clean("Physical Therapist Pipe"); clean("ReSkate server"); clean(""); // Masking keeps everything else and the length. diff --git a/Engine/Core/Text/bad_words.txt b/Engine/Core/Text/bad_words.txt index 6dd62a8c..07859417 100644 --- a/Engine/Core/Text/bad_words.txt +++ b/Engine/Core/Text/bad_words.txt @@ -194,6 +194,8 @@ gayboy gaygirl gays gayz +gangrape +gangraped gook guiena h00r @@ -343,6 +345,12 @@ queerz qweers qweerz qweir +rape +raped +rapes +raping +rapist +rapists rautenberg recktum rectum diff --git a/Engine/Core/Text/word_filter.cpp b/Engine/Core/Text/word_filter.cpp index fab27dde..d566e649 100644 --- a/Engine/Core/Text/word_filter.cpp +++ b/Engine/Core/Text/word_filter.cpp @@ -32,16 +32,18 @@ char fold(char c) { } // Longer list words that are common inside ordinary ones ("hell" in hello, "arse" in parse, -// "puta" in reputation, "turd" in saturday): these only count as a whole word. +// "puta" in reputation, "turd" in saturday, "rapist" in therapist): these only count as a +// whole word. constexpr std::string_view whole_word_only[]{ - "anus", "arse", "ayir", "bich", "breasts", "cawk", "cawks", "chuj", "cipa", "crap", - "dego", "dike", "dupa", "ekto", "faen", "faig", "faigs", "fanny", "fart", "fitt", - "flipping", "gays", "gayz", "gook", "hell", "hells", "hoar", "hoer", "hoor", "hore", - "injun", "jiss", "kawk", "knob", "knobs", "knobz", "kraut", "kunt", "kunts", "kuntz", - "kusi", "merd", "muie", "nasty", "nastt", "packi", "packie", "packy", "paki", "pakie", - "paky", "paska", "perse", "picka", "pillu", "polac", "polak", "poop", "pric", "prik", - "pron", "pula", "pule", "pusse", "puta", "puto", "rautenberg", "schaffer", "screw", "screwing", - "semen", "shiz", "smut", "teets", "teez", "tits", "titt", "turd", "woose"}; + "anus", "arse", "ayir", "bich", "breasts", "cawk", "cawks", "chuj", "cipa", "crap", + "dego", "dike", "dupa", "ekto", "faen", "faig", "faigs", "fanny", "fart", "fitt", + "flipping", "gays", "gayz", "gook", "hell", "hells", "hoar", "hoer", "hoor", "hore", + "injun", "jiss", "kawk", "knob", "knobs", "knobz", "kraut", "kunt", "kunts", "kuntz", + "kusi", "merd", "muie", "nastt", "nasty", "packi", "packie", "packy", "paki", "pakie", + "paky", "paska", "perse", "picka", "pillu", "polac", "polak", "poop", "pric", "prik", + "pron", "pula", "pule", "pusse", "puta", "puto", "rape", "raped", "rapes", "raping", + "rapist", "rapists", "rautenberg", "schaffer", "screw", "screwing", "semen", "shiz", "smut", "teets", + "teez", "tits", "titt", "turd", "woose"}; // Ordinary words with a bad word inside; a match that one of these covers does not count. constexpr std::string_view allowed_words[]{ diff --git a/Extension/Multiplayer/Session/session_commands.cpp b/Extension/Multiplayer/Session/session_commands.cpp index cdf76aa6..21abce09 100644 --- a/Extension/Multiplayer/Session/session_commands.cpp +++ b/Extension/Multiplayer/Session/session_commands.cpp @@ -6,6 +6,7 @@ #include "Extension/Objects/network_object_runtime.h" #include "Extension/Objects/ParkEditor/park_editor_runtime.h" #include "Engine/Core/Platform/launcher_support.h" +#include "Engine/Core/Text/word_filter.h" #include "Engine/Game/Multiplayer/session_tools.h" #include #include @@ -739,6 +740,9 @@ std::string command(std::string_view action, std::string_view argument, std::str if (lobby_name.size() > 128 || std::any_of(lobby_name.begin(), lobby_name.end(), [](unsigned char c) { return c < 32 || c == 127; })) return "Lobby names must be at most 128 bytes with no control characters."; + // A lobby browsers refuse to list is no use to anyone: say so while it can be fixed. + if (text::contains_bad_words(lobby_name)) + return "That lobby name contains blocked words. Choose another one."; } std::optional invitation; if (action == "join") { @@ -768,7 +772,9 @@ std::string command(std::string_view action, std::string_view argument, std::str } s.mode = Mode::host; s.host_id = s.transport.status().local_id; - s.lobby_name = lobby_name.empty() ? s.transport.name(s.host_id) : std::string(lobby_name); + // Falling back to the Steam name: that one is not the player's to retype, so mask it. + s.lobby_name = lobby_name.empty() ? text::mask_bad_words(s.transport.name(s.host_id)) + : std::string(lobby_name); if (s.lobby_name.empty()) s.lobby_name = "ReSkate session"; s.invite = format_invite({s.host_id, s.secret}); s.public_host = visibility == "public"; diff --git a/Extension/Multiplayer/Steam/steam_lobbies.cpp b/Extension/Multiplayer/Steam/steam_lobbies.cpp index fb7fc9fd..8be11470 100644 --- a/Extension/Multiplayer/Steam/steam_lobbies.cpp +++ b/Extension/Multiplayer/Steam/steam_lobbies.cpp @@ -1,4 +1,5 @@ #include "steam_lobbies.h" +#include "Engine/Core/Text/word_filter.h" #include "Engine/Game/Build/supported_build.h" #include #include @@ -248,11 +249,14 @@ void SteamLobbies::tick(std::uint64_t now) { state_.browser = "Steam lobby search failed. Refresh to retry."; return; } + // Lobbies named with bad words are never listed, like dedicated servers; the host + // can still share the join code. for (std::uint32_t i = 0; i < std::min(result.count, 50U); ++i) { const auto id = api_->at(static_cast(i)); const auto row = read_lobby(id, 0, [&](const char *key) { return api_->data(id, key); }); - if (row && std::none_of(state_.rows.begin(), state_.rows.end(), - [id](const auto &v) { return v.id == id; })) + if (row && !text::contains_bad_words(row->name) && + std::none_of(state_.rows.begin(), state_.rows.end(), + [id](const auto &v) { return v.id == id; })) state_.rows.push_back(*row); } state_.browser = state_.rows.empty()