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.EntityDamageByEntityEvent;
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@@ -478,6 +479,23 @@ public final class Canalhandia extends JavaPlugin implements Listener {
|
|||||||
}, settings.joinDelaySeconds() * 20L);
|
}, 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. */
|
/** "Press F" — a mourning button under each death message. */
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onDeath(PlayerDeathEvent event) {
|
public void onDeath(PlayerDeathEvent event) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ enum Module {
|
|||||||
RANKING("ranking", "Rankings"),
|
RANKING("ranking", "Rankings"),
|
||||||
MARCOS("marcos", "Marcos e conquistas"),
|
MARCOS("marcos", "Marcos e conquistas"),
|
||||||
MORTES("mortes", "Mortes com humor e coordenadas"),
|
MORTES("mortes", "Mortes com humor e coordenadas"),
|
||||||
|
ZOACAO("zoacao", "Zoa de quem manda só 'f' no chat"),
|
||||||
IA("ia", "Perguntas para a IA");
|
IA("ia", "Perguntas para a IA");
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
|
|||||||
@@ -344,6 +344,27 @@ final class Settings {
|
|||||||
set("ia.estatisticas-jogador", value);
|
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 ------------------------------------------------------------
|
// --- content ------------------------------------------------------------
|
||||||
|
|
||||||
boolean categoryEnabled(Category category) {
|
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
|
# Mensagem de morte engraçada + coordenadas da morte mandadas em privado
|
||||||
# só para quem morreu (para correr buscar os itens).
|
# só para quem morreu (para correr buscar os itens).
|
||||||
mortes: true
|
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
|
ia: true # /ia <pergunta> — só para quem tem canalhandia.ia
|
||||||
|
|
||||||
# --- Curiosidades ------------------------------------------------------------
|
# --- Curiosidades ------------------------------------------------------------
|
||||||
@@ -69,6 +71,17 @@ janela-reacao-segundos: 90
|
|||||||
luto:
|
luto:
|
||||||
cabeca: true
|
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".
|
# 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
|
# O resumo é sempre UMA linha, por mais gente que reaja; para ver a lista
|
||||||
# completa use /reacoes (privado, não polui o chat).
|
# 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