Um bom primeiro mod deve ensinar mais do que copiar um arquivo pronto. Neste guia, você transformará uma ideia simples em um pequeno programa: quando uma mensagem contiver uma palavra configurada, substituir essa palavra inteira por caracteres #.
O mod comunitário real que inspirou a lição é Roblox-Like Swear Filter. Seu criador é creditado como Gamecube, cujo nome de usuário é Blither Dev. Os dois nomes identificam a mesma pessoa. Não reproduziremos a lista extensa do mod. Vamos reconstruir a ideia com termos neutros para entender a estrutura e depois criar regras próprias com responsabilidade.
O que você aprenderá
- Uma tabela Lua armazena dados relacionados.
- Uma função transforma uma entrada em uma saída.
- Um laço aplica a mesma regra a cada item.
- Uma condição decide se a mensagem original deve continuar.
- Um hook conecta sua função a um evento do SM64CoopDX.
- Um segundo valor de retorno informa se algo mudou.
Antes de começar
Pré-requisitos
- SM64CoopDXSoftware
Use sua própria instalação funcional. Este tutorial cria somente um arquivo Lua.
- Editor de textoSoftware
Qualquer editor de texto simples que preserve a extensão
.luaé suficiente. - Pasta de modsPermissões
Você precisa criar uma pasta e um arquivo
main.luaem um local compatível.
A referência oficial informa que uma pasta de mod pode conter vários arquivos Lua, desde que um deles se chame main.lua. Ela também documenta HOOK_ON_CHAT_MESSAGE: o evento recebe o MarioState do remetente e o texto da mensagem. Retornar false impede o envio da mensagem original.
Referência oficial de hooks do SM64CoopDX
Define hook_event, HOOK_ON_CHAT_MESSAGE, seus parâmetros e o comportamento de false usado neste guia.
Planeje o programa antes de escrever
Pense no mod como um fluxo curto:
- Evento: o SM64CoopDX entrega uma nova mensagem ao callback.
- Dados: uma tabela contém as palavras escolhidas.
- Lógica: um laço verifica cada palavra e substitui correspondências completas.
- Decisão: mensagens intactas continuam normalmente.
- Resultado: mensagens modificadas aparecem filtradas e a original é interrompida.
Essa separação evita misturar regras de texto com a forma como o jogo exibe o chat.
Construa o mod em partes pequenas
Crie a pasta e o arquivo de entrada
Crie
chat-filterdentro da pastamodse adicionemain.luanela.Verificação: O caminho termina em chat-filter/main.lua.
Comece com uma tabela pequena
Uma tabela agrupa valores do mesmo conceito:
local blocked_words = { "spoiler", "secret", }Verificação: A tabela contém somente termos neutros de teste.
Transforme uma palavra em um padrão completo
Esta função cria alternativas maiúsculas e minúsculas. Os marcadores de fronteira impedem que
secretcorresponda dentro de uma palavra maior.local function whole_word_pattern(word) local letters = string.gsub(word, "%a", function(letter) return string.format( "[%s%s]", string.lower(letter), string.upper(letter) ) end) return "%f[%a]" .. letters .. "%f[%A]" endVerificação: A função auxiliar retorna um padrão Lua.
Crie a função de transformação
O laço aplica a operação a cada palavra.
string.gsubretorna o novo texto e a quantidade de substituições.local function filter_message(message) local result = message local changed = false for _, word in ipairs(blocked_words) do local replacement = string.rep("#", string.len(word)) local count result, count = string.gsub( result, whole_word_pattern(word), replacement ) if count > 0 then changed = true end end return result, changed endVerificação: A função retorna o texto e um indicador de mudança.
Conecte a lógica ao chat
O callback deixa mensagens intactas passarem. Quando encontra uma correspondência, cria a linha filtrada, toca um som documentado e retorna
falsepara interromper a original.-- name: Learning Chat Filter -- description: A small chat filter built for learning Lua logic. local blocked_words = { "spoiler", "secret", } local function whole_word_pattern(word) local letters = string.gsub(word, "%a", function(letter) return string.format("[%s%s]", string.lower(letter), string.upper(letter)) end) return "%f[%a]" .. letters .. "%f[%A]" end local function filter_message(message) local result = message local changed = false for _, word in ipairs(blocked_words) do local replacement = string.rep("#", string.len(word)) local count result, count = string.gsub(result, whole_word_pattern(word), replacement) if count > 0 then changed = true end end return result, changed end local function on_chat_message(_sender, message) local filtered, changed = filter_message(message) if not changed then return end play_sound(SOUND_MENU_MESSAGE_APPEAR, gGlobalSoundSource) djui_chat_message_create(filtered) return false end hook_event(HOOK_ON_CHAT_MESSAGE, on_chat_message)Verificação: A última linha registra HOOK_ON_CHAT_MESSAGE.
Teste uma regra por vez
Teste
this is a spoiler, depoisspoilerse por fim uma mensagem sem palavras configuradas. Assim você observará a correspondência de palavras inteiras e o caminho sem mudanças.Verificação: O texto normal continua e uma palavra configurada vira símbolos.
Leia a lógica como programador
blocked_words representa os dados. whole_word_pattern prepara uma regra. filter_message é a lógica que pode ser entendida sem abrir o jogo. on_chat_message é o limite de integração com a API do SM64CoopDX.
Ao adicionar uma palavra, você altera dados. Ao mudar a correspondência, edita a função do padrão. Se a API mudar, revisa o callback do evento.
Melhore por meio de experimentos
- Troque
#por outro símbolo neutro. - Adicione uma única palavra e preveja o resultado antes de executar o jogo.
- Retorne a quantidade de substituições como terceiro resultado.
- Separe a tabela em outro arquivo somente quando entender a versão atual.
- Escreva casos de teste: sem correspondência, uma correspondência, maiúsculas e uma palavra mais longa.
Não comece colando uma lista enorme. Uma tabela pequena permite compreender o algoritmo e encontrar erros.
Resultado esperado
Resultado esperado
Agora você tem um mod orientado a eventos com dados, transformação e integração claramente separados.
- O mod aparece na lista do SM64CoopDX
- Mensagens sem palavras configuradas continuam normalmente
- Uma palavra inteira é substituída pela mesma quantidade de símbolos
- O padrão aceita formas maiúsculas e minúsculas
- A mensagem original é interrompida somente depois de criar a linha filtrada
O que aprender depois
Você já usou estruturas de dados, variáveis locais, transformação, iteração, condições, múltiplos valores de retorno e integração por eventos. O próximo passo útil não é uma lista maior, mas aprender a testar cada função com entradas previsíveis e separar configuração de comportamento.
