Packet Listeners

Interceptar e modificar pacotes de rede via reflection

O sistema de Packet Listeners permite interceptar e modificar pacotes de rede antes de serem processados pelo servidor ou enviados aos clientes. Suporta mais de 200 tipos de pacotes através de um sistema dinâmico baseado em reflection.

Sintaxe

Receive Packets (Client → Server)

Escuta pacotes enviados do cliente para o servidor:

on receive packet TextPacket:
    # Handle incoming chat packet
    set {message} to packet field "message"
    broadcast "Player sent: %{message}%"

Send Packets (Server → Client)

Escuta pacotes enviados do servidor para o cliente:

on send packet PlaySoundPacket:
    # Handle outgoing sound packet
    set {sound} to packet field "soundName"
    log "Playing sound: %{sound}%"

Prioridade

Você pode especificar uma prioridade para o listener:

on receive packet MovePlayerPacket with priority highest:
    # This runs before other listeners
    cancel packet

Prioridades disponíveis:

  • lowest - Executa primeiro
  • low
  • normal (padrão)
  • high
  • highest - Executa por último

Dados Disponíveis

Dentro de um packet listener, você tem acesso a:

ExpressãoTipoDescrição
playerPlayerO player associado ao pacote
packetPacketO objeto raw do pacote
packet typeStringNome curto do pacote (ex: "TextPacket")
packet field "nome"MixedAcessa qualquer campo do pacote dinamicamente

Efeitos

cancel packet

Impede o pacote de ser processado ou enviado:

on receive packet TextPacket:
    set {msg} to packet field "message"
    if {msg} contains "badword":
        cancel packet
        send "Watch your language!" to player

set packet field

Modifica campos do pacote antes do processamento:

on send packet SetTitlePacket:
    set packet field "text" to "&6Modified Title"

Tipos de Pacotes Comuns

Movimento

  • MovePlayerPacket - Movimento do player
  • MoveActorAbsolutePacket - Movimento de entidades
  • PlayerAuthInputPacket - Input do player

Chat & Comunicação

  • TextPacket - Mensagens de chat
  • CommandRequestPacket - Execução de comandos

Inventário

  • InventoryTransactionPacket - Transações de itens
  • ContainerOpenPacket / ContainerClosePacket
  • ItemStackRequestPacket - Operações de item stack

Interação com o Mundo

  • BlockActorDataPacket - Updates de block entities
  • LevelSoundEventPacket - Eventos de som
  • LevelEventPacket - Eventos do mundo
  • AnimatePacket - Animações do player

Estado do Player

  • PlayerActionPacket - Ações como pular, agachar
  • InteractPacket - Interações com entidades
  • EmotePacket - Emotes do player

UI & Forms

  • ModalFormRequestPacket - Exibição de forms
  • ModalFormResponsePacket - Respostas de forms
  • ServerSettingsRequestPacket - Requisição de settings

Exemplos Avançados

Anti-Cheat de Movimento

anticheat-movement.lzl
on receive packet MovePlayerPacket with priority highest:
    set {y} to packet field "position.y"
    set {lastY} to variable "player.%player%.lastY" or 0
    
    if {y} - {lastY} > 5:
        cancel packet
        teleport player to player's last location
        send "&cMovement anomaly detected!" to player
    
    set variable "player.%player%.lastY" to {y}

Filtro de Chat

chat-filter.lzl
on receive packet TextPacket:
    set {type} to packet field "type"
    if {type} == 1:  # Chat message
        set {message} to packet field "message"
        
        if {message} contains "spam":
            cancel packet
            send "&cYour message was blocked." to player

Substituição de Som

sound-replace.lzl
on send packet PlaySoundPacket:
    set {sound} to packet field "soundName"
    
    if {sound} == "mob.pig.say":
        set packet field "soundName" to "mob.cow.say"

Interceptação de Forms

form-intercept.lzl
on receive packet ModalFormResponsePacket:
    set {formId} to packet field "formId"
    set {formData} to packet field "formData"
    
    log "Form %{formId}% response: %{formData}%"

Acesso a Campos do Pacote

Lazuli usa reflection para acessar dinamicamente campos de pacotes. Isso significa que você pode acessar qualquer campo público ou protegido de qualquer classe de pacote.

Campos Aninhados

Para estruturas complexas de pacotes, você pode acessar campos aninhados:

# Access nested position data
set {x} to packet field "position.x"
set {y} to packet field "position.y"
set {z} to packet field "position.z"

Campos Array

Alguns pacotes contêm arrays. Você pode acessá-los como um todo:

on receive packet InventoryTransactionPacket:
    set {actions} to packet field "actions"
    # {actions} is an array of transaction actions

Considerações de Performance

Dicas de Performance

  • Use tipos específicos - Não escute todos os pacotes se precisar apenas de um tipo
  • Use prioridade alta com moderação - Só use highest/lowest quando necessário
  • Minimize acesso a campos - Cache valores em variáveis locais
  • Cancele cedo - Se for cancelar, faça antes de processamento pesado

Diferenças de Eventos

CaracterísticaEventosPacket Listeners
NívelAlto nível, semânticoBaixo nível, dados raw
TimingApós processamentoAntes do processamento
CancelamentoPode ou não funcionarPrevine processamento completamente
DadosParseados, tipadosCampos raw do pacote
Caso de usoLógica de jogoManipulação de rede

Notas Importantes

  • Packet listeners executam antes de eventos, então cancelar um pacote prevenirá o evento correspondente de disparar
  • Nem todos os pacotes disparam eventos - alguns são internos à camada de rede
  • Modificar pacotes requer entender sua estrutura
  • O mapa de classes de pacotes é construído dinamicamente da biblioteca bedrock-protocol