Add zoacao chat gag: bare 'f' replaced with a random line
New module keyed 'zoacao'. An AsyncPlayerChatEvent listener swaps any bare 'f'/'F' (trimmed, nothing else) for a random line from the configurable zoacao.mensagens list (default Sou gay + 5 others). Pure chat swap — player name still prefixes it; luto tribute untouched (still needs the [F] button or /f command). Gated by modulos.zoacao (default on). Zoacao.replace is pure for unit tests; ZoacaoTest covers bare f, case, whitespace, f-with-extra-text, empty/null lists. 124 tests green. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -478,6 +479,23 @@ public final class Canalhandia extends JavaPlugin implements Listener {
|
||||
}, settings.joinDelaySeconds() * 20L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat gag: a bare "f" (or "F", trimmed, nothing else) gets replaced with a
|
||||
* random line from {@code zoacao.mensagens}. Pure chat swap — the player's
|
||||
* name still prefixes it as normal. Independent of {@code luto}: paying
|
||||
* respects still needs the {@code [F]} button (Java) or {@code /f} command.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onChatF(AsyncPlayerChatEvent event) {
|
||||
if (!settings.moduleEnabled(Module.ZOACAO)) {
|
||||
return;
|
||||
}
|
||||
String gag = Zoacao.replace(event.getMessage(), settings.zoacaoMessages(), random);
|
||||
if (gag != null) {
|
||||
event.setMessage(gag);
|
||||
}
|
||||
}
|
||||
|
||||
/** "Press F" — a mourning button under each death message. */
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent event) {
|
||||
|
||||
@@ -10,6 +10,7 @@ enum Module {
|
||||
RANKING("ranking", "Rankings"),
|
||||
MARCOS("marcos", "Marcos e conquistas"),
|
||||
MORTES("mortes", "Mortes com humor e coordenadas"),
|
||||
ZOACAO("zoacao", "Zoa de quem manda só 'f' no chat"),
|
||||
IA("ia", "Perguntas para a IA");
|
||||
|
||||
private final String key;
|
||||
|
||||
@@ -344,6 +344,27 @@ final class Settings {
|
||||
set("ia.estatisticas-jogador", value);
|
||||
}
|
||||
|
||||
// --- zoacao (f-gag) -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Lines a bare "f" in chat gets replaced with, picked at random. Defaults
|
||||
* to a small built-in list if unset/empty so the feature works out of the
|
||||
* box; operators edit {@code zoacao.mensagens} in config.yml to customise.
|
||||
*/
|
||||
List<String> zoacaoMessages() {
|
||||
List<String> messages = plugin.getConfig().getStringList("zoacao.mensagens");
|
||||
if (messages == null || messages.isEmpty()) {
|
||||
return List.of(
|
||||
"Sou gay",
|
||||
"Gosto de anime",
|
||||
"Jogo no celular",
|
||||
"Tenho 12 anos",
|
||||
"Sou noob",
|
||||
"Uso Windows");
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
// --- content ------------------------------------------------------------
|
||||
|
||||
boolean categoryEnabled(Category category) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.marcospaulo.canalhandia;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Pure logic for the {@code zoacao} chat gag: when a player sends a bare
|
||||
* {@code "f"} (or {@code "F"}, trimmed, nothing else) their message is swapped
|
||||
* for a random line from a configurable list. Extracted so the trigger rule is
|
||||
* unit-testable without a server.
|
||||
*
|
||||
* <p>This is a standalone chat gag. It does not interact with the {@code luto}
|
||||
* tribute — paying respects still happens via the {@code [F]} button (Java) or
|
||||
* the {@code /f} command (Bedrock), neither of which is a chat message.
|
||||
*/
|
||||
final class Zoacao {
|
||||
|
||||
private Zoacao() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message the chat message as sent by the player
|
||||
* @param gags the configured replacement lines; if null/empty, no gag
|
||||
* @param random shared random used to pick a line
|
||||
* @return the replacement line if the message is a bare "f", otherwise null
|
||||
* (meaning "leave the message alone")
|
||||
*/
|
||||
static String replace(String message, List<String> gags, Random random) {
|
||||
if (message == null || gags == null || gags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (!message.trim().equalsIgnoreCase("f")) {
|
||||
return null;
|
||||
}
|
||||
return gags.get(random.nextInt(gags.size()));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ modulos:
|
||||
# Mensagem de morte engraçada + coordenadas da morte mandadas em privado
|
||||
# só para quem morreu (para correr buscar os itens).
|
||||
mortes: true
|
||||
# Quem manda só "f" no chat (sem mais nada) leva uma zoada no lugar da mensagem.
|
||||
zoacao: true
|
||||
ia: true # /ia <pergunta> — só para quem tem canalhandia.ia
|
||||
|
||||
# --- Curiosidades ------------------------------------------------------------
|
||||
@@ -69,6 +71,17 @@ janela-reacao-segundos: 90
|
||||
luto:
|
||||
cabeca: true
|
||||
|
||||
# Frases que substituem um "f" sozinho no chat (módulo zoacao). Uma é sorteada
|
||||
# por mensagem. Edite à vontade — a graça é ser inesperado.
|
||||
zoacao:
|
||||
mensagens:
|
||||
- "Sou gay"
|
||||
- "Gosto de anime"
|
||||
- "Jogo no celular"
|
||||
- "Tenho 12 anos"
|
||||
- "Sou noob"
|
||||
- "Uso Windows"
|
||||
|
||||
# Quantos nomes cabem no resumo de reações antes do resto virar "+N".
|
||||
# O resumo é sempre UMA linha, por mais gente que reaja; para ver a lista
|
||||
# completa use /reacoes (privado, não polui o chat).
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.marcospaulo.canalhandia;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ZoacaoTest {
|
||||
|
||||
private static final List<String> GAGS = List.of(
|
||||
"Sou gay", "Gosto de anime", "Jogo no celular");
|
||||
|
||||
@Test
|
||||
void bareLowercaseFIsReplacedWithAGagFromTheList() {
|
||||
String gag = Zoacao.replace("f", GAGS, new Random(0L));
|
||||
assertTrue(GAGS.contains(gag), "expected a gag from the list, got " + gag);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bareUppercaseFIsReplaced() {
|
||||
// A single-element list makes the random pick deterministic.
|
||||
String gag = Zoacao.replace("F", List.of("alvo"), new Random(0L));
|
||||
assertEquals("alvo", gag);
|
||||
}
|
||||
|
||||
@Test
|
||||
void surroundingWhitespaceStillCountsAsBareF() {
|
||||
assertEquals("alvo", Zoacao.replace(" f ", List.of("alvo"), new Random(0L)));
|
||||
assertEquals("alvo", Zoacao.replace("\tF\n", List.of("alvo"), new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fWithAnythingElseIsLeftAlone() {
|
||||
assertNull(Zoacao.replace("f lol", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("ff", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("f.", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("pra você f", GAGS, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonFMessagesAreLeftAlone() {
|
||||
assertNull(Zoacao.replace("oi", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("F para o morto", GAGS, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyOrNullGagsLeaveMessageAlone() {
|
||||
assertNull(Zoacao.replace("f", List.of(), new Random(0L)));
|
||||
assertNull(Zoacao.replace("f", null, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullMessageLeftAlone() {
|
||||
assertNull(Zoacao.replace(null, GAGS, new Random(0L)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user