Ghost
Visão geral
Em uma rede com vários servidores backend, dois jogadores no mesmo mapa em servidores diferentes não conseguem se ver. O Ghost resolve isso visualmente: cada servidor publica a posição, a rotação e a skin de seus jogadores pelo Redis, e os outros servidores os desenham como fantasmas em forma de jogador usando pacotes. Nada é adicionado ao mundo, e um fantasma não tem entidade no lado do servidor, então não pode ser atingido, empurrado nem alvejado.
Cada jogador decide se vê fantasmas. A escolha é armazenada em um fact do TypeWriter, então sobrevive a reinícios e acompanha o jogador de servidor em servidor. Os fantasmas só aparecem entre servidores que compartilham o mesmo redis.group-id na configuração do MySQL, e um servidor nunca desenha os próprios jogadores como fantasmas.
Recursos
- Fantasmas entre servidores — jogadores de outros servidores backend aparecem com sua skin, posição e rotação.
- Renderização apenas por pacotes — construído sobre o PacketEvents, nenhuma entidade no lado do servidor é criada.
- Compatível com Folia — cada captura e cada renderização roda no scheduler do jogador em questão.
- Chave de visibilidade —
/ghost toggle, uma ação do TypeWriter ou um botão de menu liga e desliga os fantasmas por jogador. - Escolha persistente — a preferência é um fact persistível compartilhado entre servidores.
- Tag de servidor — um sufixo configurável como
[survival-2]mostra de onde vem um fantasma. - Limites — distância de visão, máximo de fantasmas por espectador, taxa de atualização e filtragem de mundos mantêm o custo limitado.
- Nameplates — se o UiCore estiver instalado, os fantasmas recebem uma nameplate acima da cabeça.
- Placeholders — visibilidade e contagem de fantasmas para texto MiniMessage.
Instalação
- Instale o PacketEvents em todos os servidores.
- Instale a extensão MySQL e ative o Redis (ou Valkey) em todos os servidores. Dê a cada servidor um
redis.server-nameúnico e o mesmoredis.group-id. O Ghost não tem configurações próprias de Redis. - Coloque o JAR do Ghost em
plugins/Typewriter/extensions/e reinicie. O arquivoplugins/Typewriter/ghost_player/config.ymlé criado na primeira inicialização. - Conceda a permissão
typewriter.ghost.useaos jogadores que podem usar/ghost. Sem um plugin de permissões, apenas operadores podem. - Opcional: instale o UiCore para desenhar nameplates acima dos fantasmas.
Primeiros passos
Deixe os jogadores alternarem os fantasmas a partir de um menu ou de um NPC de quest:
- No painel web do TypeWriter, abra uma page e adicione uma entry de fact Ghost Visibility Fact. Mantenha o
idpadrão,ghost_visibility_fact: a extensão lê e grava o fact por esse id. - Adicione uma ação Ghost Toggle Visibility em uma sequence ou em um item de menu. Preencha
showMessageehideMessagecom texto MiniMessage, ou deixe-os vazios para usar as mensagens padrão. - Opcionalmente, adicione um criteria no fact Ghost Visibility (o valor
1significa visível,0oculto) para mostrar um ícone diferente em um menu. - Publique e entre em dois servidores do mesmo grupo. Cada jogador vê o outro como um fantasma com o sufixo do servidor.
Um servidor ignora as próprias transmissões. Para testar, inicie dois servidores com o mesmo redis.group-id e redis.server-name diferentes, e fique em mundos que possam corresponder (veja abaixo).
Como funciona
Cada servidor publica um snapshot de cada jogador local na taxa configurada, além de um heartbeat para que jogadores parados continuem ativos. Um fantasma desaparece quando seu dono sai ou quando nenhuma atualização chega dentro de timeout-millis. Cada mensagem carrega um id de sessão e um número de sequência, então mensagens atrasadas ou duplicadas são ignoradas.
Um fantasma é desenhado para um espectador quando o espectador tem os fantasmas ativados, os mundos são compatíveis, o fantasma está dentro de view-distance e o espectador tem menos de max-ghosts-per-viewer fantasmas, começando pelos mais próximos.
Configuração
O arquivo é plugins/Typewriter/ghost_player/config.yml. Seu schema-version deve ser 1 ou 2.
schema-version: 2
settings:
update-rate: 4
server-suffix: " <gray>[%server%]</gray>"
team-prefix: "Ghosts"
view-distance: 64.0
max-ghosts-per-viewer: 128
timeout-millis: 10000
allowed-worlds:
- "world"
- "dungeon_"
- "hub"
messages:
no-permission: "<red>You do not have permission to use ghost visibility."
players-only: "<red>This command can only be used by a player."
enabled: "<green>Ghost visibility enabled."
disabled: "<yellow>Ghost visibility disabled."
usage: "<gray>Usage: <white>/ghost toggle"
command:
permission: "typewriter.ghost.use"
| Chave | Significado |
|---|---|
settings.update-rate | Ticks entre capturas de posição. Limitado de 1 a 20. |
settings.server-suffix | Texto MiniMessage adicionado após o nome do fantasma. %server% vira o nome do servidor de origem. |
settings.team-prefix | Prefixo do time de scoreboard exibido para cada servidor de origem. |
settings.view-distance | Distância máxima em blocos, de 0 a 256. 0 desativa o limite de distância. |
settings.max-ghosts-per-viewer | Fantasmas desenhados por espectador, de 0 a 2000. 0 não mostra nenhum. |
settings.timeout-millis | Atraso sem atualização antes de um fantasma ser removido, de 2000 a 120000. |
settings.allowed-worlds | Padrões de nomes de mundos que contam como o mesmo mapa entre servidores. Até 64 entradas. |
messages.* | Textos MiniMessage usados por /ghost. |
command.permission | Permissão exigida por /ghost. |
Mundos. Um fantasma é visível quando o espectador e o fantasma estão em mundos com o mesmo nome, ou quando ambos os nomes de mundo contêm o mesmo padrão de allowed-worlds (por exemplo, dungeon_ corresponde a dungeon_1 e dungeon_2). A distância só pode ser medida dentro de um mesmo mundo, então, com um view-distance acima de 0, os fantasmas de um mundo com nome diferente ficam ocultos. Defina view-distance como 0 se você depende da correspondência por padrão.
A conexão Redis, o nome do servidor e o group id são lidos da configuração do MySQL. O arquivo é lido uma vez na inicialização: reinicie o servidor depois de editá-lo.
Comandos
| Comando | Descrição |
|---|---|
/ghost toggle | Liga ou desliga a visibilidade de fantasmas para você. |
Aliases: /ghosts, /ghostplayer. Apenas para jogadores. A permissão é command.permission, typewriter.ghost.use por padrão.
Permissões
| Permissão | Concede |
|---|---|
typewriter.ghost.use | /ghost toggle. O nome pode ser alterado com command.permission. A permissão não é registrada com um valor padrão, então precisa ser concedida. |
A ação Ghost Toggle Visibility não verifica esta permissão.
Placeholders
Tags do MiniPlaceholders para texto MiniMessage. O PlaceholderAPI não é suportado.
| Placeholder | Retorna |
|---|---|
<ghost_visibility> | true quando o jogador vê fantasmas, false caso contrário. |
<ghost_visible> | 1 quando o jogador vê fantasmas, 0 caso contrário. |
<ghost_count> | Número de fantasmas remotos atualmente conhecidos por este servidor. |
Entries
2 entradas, geradas a partir do código-fonte da extensão.
Ações1
- Ghost Toggle VisibilityToggle Ghost Visibility
Fatos1
- Ghost Visibility FactGhost Visibility
Solução de problemas
Nenhum fantasma aparece. Verifique, nesta ordem: ambos os servidores usam o mesmo redis.group-id não vazio e valores de redis.server-name diferentes, o Redis está conectado (caso contrário o log diz "BTC RedisService is not connected; Ghost updates will remain inactive"), o espectador tem os fantasmas ativados e os dois jogadores estão em mundos compatíveis (mesmo nome de mundo, ou um padrão compartilhado de allowed-worlds com view-distance: 0).
Jogadores do mesmo servidor nunca aparecem como fantasmas. É o esperado: um servidor ignora as mensagens que ele mesmo publicou.
A extensão falha ao iniciar com "Unsupported Ghost custom config schema". schema-version em ghost_player/config.yml está fora de 1..2. Defina-o como 2.
A extensão falha com um erro de nome de servidor. redis.server-name na configuração do MySQL deve conter apenas letras, dígitos, ., _ ou -, com até 64 caracteres.
/ghost diz que você não tem permissão. A permissão não tem valor padrão. Conceda typewriter.ghost.use (ou a permissão que você definiu em command.permission) com o seu plugin de permissões.
Os fantasmas somem após alguns segundos. Nenhuma atualização chegou dentro de timeout-millis. Verifique a latência do Redis e se o servidor de origem está executando o Ghost com o mesmo redis.group-id.
Os fantasmas não têm nameplate. As nameplates vêm do UiCore. Instale-o no servidor do espectador. Sem ele, apenas o sufixo do servidor no nome é exibido.