Pular para o conteúdo principal

Puzzle

Nove tipos de quebra-cabeças com tabuleiros no cliente, temporizadores, tentativas, cadeias e fatos.

Gratuitasv0.6Missões e narrativa
RequerTypeWriter0.9Basic (TypeWriter extension)

Visão geral​

O Puzzle transforma um lugar do seu mundo em um quebra-cabeça solucionável. Você escolhe uma entre nove mecânicas: empurrar blocos para dentro de buracos, repetir uma sequência, acionar alavancas em ordem, redirecionar feixes de laser e mais. Cada puzzle é uma entry de audience que você coloca no painel web. Ele informa o resultado ao resto do TypeWriter por meio de triggers (onStart, onComplete, onFail, onTimeout, onLifespanExpire) e de um fact opcional.

A maior parte do tabuleiro é desenhada no cliente: blocos, destaques, prévias e partículas de laser são pacotes enviados ao jogador que resolve o puzzle, de modo que dois jogadores podem trabalhar no mesmo tabuleiro sem ver o progresso um do outro. Algumas mecânicas tocam o mundo: o puzzle de item frame gira um item frame real, e o puzzle de padrão coloca blocos reais, a menos que ghostBlocks esteja ativado.

Um puzzle pertence ao lugar onde você o construiu. Ele só funciona para um jogador que esteja no mundo de suas posições, a até activationRadius blocos de uma delas. Chegar ao tabuleiro inicia uma sessão; afastar-se a encerra e limpa o tabuleiro no cliente.

Recursos​

  • Nove tipos de puzzle — empurrar blocos, sequência de memória, grade de laser, ordem de alavancas, colocação de padrão, placas de pressão cooperativas, item frame, fechadura de combinação e oferenda em pedestal.
  • Ciclo de vida compartilhado — limite de tempo, máximo de tentativas erradas, cooldown após falha, duração de vida, dicas e uma mensagem de conclusão em todo puzzle.
  • Triggers em toda parte — início, conclusão, falha, timeout e expiração da duração de vida podem iniciar uma entry do TypeWriter cada um.
  • Recompensa em fact — um fact é aumentado em amount quando o puzzle é resolvido.
  • Cadeias de puzzles — execute vários puzzles em ordem e reaja à cadeia inteira.
  • Restrição espacial — uma verificação de mundo e um raio de ativação impedem que um tabuleiro apareça em outra dimensão ou muito longe.
  • Estatísticas — tentativas, resoluções e melhor tempo por jogador, com um comando de ranking.
  • Facts de status — leia se um puzzle está resolvido ou ativo para um jogador.
  • Compatível com Folia — o acesso ao mundo roda na região dona do puzzle.

Instalação​

  1. Instale a extensão oficial Basic do TypeWriter, que fornece os tipos compartilhados usados pelos puzzles (sons, itens, variáveis).
  2. Coloque o JAR do Puzzle em plugins/Typewriter/extensions/ e reinicie o servidor.
  3. Opcional: adicione uma entry Puzzle Artifact às suas pages se quiser que tentativas, resoluções e melhores tempos sejam salvos (veja o aviso em Configuração).

Primeiros passos​

Monte um puzzle de porta com três alavancas:

  1. No painel web do TypeWriter, abra uma page manifest e adicione uma entry Lever Order.
  2. Em levers, adicione três alavancas. Para cada uma, capture no jogo a position de um bloco de alavanca e defina orderIndex como 0, 1 e 2, a ordem em que o jogador deve acioná-las.
  3. Defina amount como 3 para que a dica mostre 1/3, 2/3, 3/3. Ative resetOnWrong e defina cooldownOnFail como 5 se quiser uma pausa após um erro.
  4. Ligue onComplete a uma sequence que abre a porta e fact a um fact armazenável em cache que guarda a recompensa. Esse fact também é a forma confiável de lembrar que o puzzle foi resolvido.
  5. Opcionalmente, coloque o puzzle sob um filtro de audience, como uma audience de quest, para que ele só funcione para os jogadores certos.
  6. Publique, reinicie ou recarregue a extensão e aproxime-se das alavancas. Acioná-las na ordem certa resolve o puzzle. Acionar a alavanca errada redefine o estado das alavancas e dispara onFail.
Novos puzzles

As entries de puzzle são registradas quando a extensão carrega. Depois de adicionar um puzzle, recarregue o TypeWriter ou reinicie antes de usar /typewriter puzzle start.

Como funciona​

Sessões. Uma sessão começa quando o jogador entra no raio. Ela limpa o progresso, as tentativas erradas e o cooldown de falha, inicia timeLimit e lifespan e dispara onStart. Assim, maxAttempts é um orçamento por sessão: um jogador que esgotá-lo pode se afastar e voltar. Um puzzle já resolvido por um jogador nunca é reaberto para ele.

Um puzzle resolvido fica inerte. Depois que um jogador resolve um Block Push, Combination Lock, Lever Order ou Laser Grid, ele deixa de desenhar o tabuleiro para esse jogador e de cancelar suas interações, mesmo que ele volte à sua audiência (um filtro que oscila, uma reconexão). As alavancas e os botões de um puzzle resolvido funcionam como blocos comuns, e um Pedestal resolvido não engole mais a coleta do seu item.

Cliques cancelados. O servidor responde a um clique cancelado com o estado real do bloco clicado, o que apagaria um bloco desenhado no cliente. Por isso o tabuleiro é redesenhado um tick após cada clique cancelado (botões do Memory, grade do Pattern, colocações recusadas, empurrões recusados) e quando um jogador bate com o botão esquerdo em um espelho ou alavanca desenhados.

A conclusão dispara uma única vez. A gravação do fact, a mensagem de conclusão, onComplete e o avanço da cadeia vêm de um único resultado aceito, então um clique repetido não pode dispará-los duas vezes.

Progresso. Cada passo correto aumenta o progresso em um, até amount. {progress} e {total} em hintMessage mostram o progresso e amount. Os puzzles não definem amount a partir do próprio tamanho, então informe você mesmo o número real de passos.

Opções compartilhadas​

Todo puzzle tem estes campos.

CampoSignificado
factUm fact armazenável em cache aumentado em amount quando o puzzle é resolvido.
amountProgresso máximo e recompensa adicionada ao fact.
timeLimitSegundos antes de o puzzle expirar por tempo. 0 desativa.
cooldownOnFailSegundos que o jogador deve esperar após uma falha.
maxAttemptsTentativas erradas permitidas por sessão. 0 desativa o limite.
resetOnWrongSe um passo errado limpa o progresso.
showHints, hintMessageUma dica no chat após cada passo, com {progress} e {total}. Em branco não envia nada.
completionMessageEnviada uma vez quando resolvido. Em branco desativa. O padrão é <green>Puzzle completed!.
onStart, onComplete, onFail, onTimeout, onLifespanExpireEntries disparadas para o jogador.
lifespanSegundos até o puzzle expirar para o jogador, faça ele o que fizer. 0 desativa.
activationRadiusBlocos ao redor das posições do puzzle. 0 remove a verificação de distância, mas a verificação de mundo sempre vale. O padrão é 16.
criteriaCondições que um jogador deve cumprir para participar do puzzle.

Puzzles compartilhados​

Quando isShared está ativado e o fact do puzzle tem um grupo (party, equipe), o grupo joga um único puzzle: cada passo, erro e cooldown de um jogador é copiado para os jogadores online desse grupo. O primeiro membro que o resolve o resolve para o grupo: o fact é aumentado em amount uma única vez, e cada membro recebe uma vez a mensagem de conclusão, onComplete e a etapa da cadeia. Um membro ausente os recebe quando volta. Um jogador recebe a conclusão de um puzzle no máximo uma vez, mesmo que mude de grupo; somente um reset de administrador que o afete permite que ele a receba novamente.

  • A resolução é guardada por grupo. Morrer ou se reconectar não a reinicia e não recompensa nada de novo, ao contrário de um puzzle solo, que pode ser jogado de novo após uma morte ou uma desconexão.
  • As estatísticas e o tabuleiro de cada jogador continuam pessoais. Sem grupo no fact, ou para um jogador que não pertence a nenhum grupo, nada é compartilhado. Coop Pressure ignora isShared: ele já conclui o puzzle para cada participante.
  • Para jogá-lo de novo, use /typewriter puzzle admin reset <player> <id>, que o reabre para todo o grupo desse jogador.
Um Puzzle Artifact é obrigatório

A resolução do grupo é salva no Puzzle Artifact. Sem ele, o registro existe apenas na memória: após reiniciar o servidor, o grupo pode resolver o puzzle de novo e ser pago de novo. Adicione o artifact antes de usar isShared. Voltar a uma build mais antiga da extensão também perde o registro compartilhado, porque essa build salva o artifact sem ele, e as recompensas são pagas de novo. A resolução é gravada no próximo salvamento (a cada 30 segundos): uma falha do servidor nessa janela pode perdê-la.

Tipos de puzzle​

EntryO que o jogador fazCampos principais
Block PushClica com o botão esquerdo ou direito em um bloco para empurrá-lo um bloco na direção para onde o jogador olha, até cada buraco de destino ser preenchido.pushBlocks, targetHoles (com acceptedMaterial), blockMaterial, holeMaterial. O número de blocos deve ser igual ao número de buracos. allowPull não tem efeito (puxar ainda não está implementado).
Memory SequenceObserva os botões acenderem e depois clica neles na mesma ordem. A sequência é aleatória a cada sessão.buttons (pelo menos 2), sequenceLength, highlightDuration, stepGap, inputDelay (ticks), highlightMaterial.
Laser GridClica com o botão direito em espelhos para girá-los até cada receptor ser atingido por um feixe da sua cor.emitters (cor, direção), mirrors (rotatable, initialDirection), receivers (requiredColor), maxReflections, maxBeamLength, beamDensity.
Lever OrderClica com o botão direito nas alavancas na ordem do seu orderIndex. Uma alavanca errada redefine todas.levers (position, orderIndex).
Pattern PlacementColoca blocos em uma grade para reproduzir um padrão.pattern, gridOrigin, columns, previewOffsetY, ghostBlocks, tolerance.
Coop PressureVários jogadores ficam em placas diferentes e seguram por alguns segundos.plates, requiredPlayers, holdDuration (segundos).
Item FrameColoca um item em um item frame existente e depois o gira até o ângulo de destino.frameTargets (correctRotation 0 a 7, requiredItem), checkItem.
Combination LockClica em blocos de dígitos na ordem de um código.digits (posições), code (índices dos dígitos, contados a partir de 0).
PedestalClica com o botão direito no bloco do pedestal segurando um item, ou solta ou pega o item perto dele.targetPosition, requiredItem, consumeItem, pickupRadius, consumeDroppedItem.

Detalhes de cada tipo:

  • Laser Grid. Um feixe começa a um bloco do emissor e segue em linha reta. Um espelho o envia na direção para a qual o espelho está virado. Clicar com o botão direito em um espelho define sua direção como o oposto da face em que você clicou, ou o gira no sentido horário se você clicar em seu topo ou base. Um bloco sólido interrompe o feixe. O puzzle é resolvido quando cada receptor é atingido por um feixe do seu requiredColor. Os feixes são exibidos com partículas. Um espelho não some ao clicar com o botão direito: o tabuleiro é redesenhado após o clique. Os feixes são desenhados pelo centro dos blocos e viram exatamente sobre cada espelho; beamDensity é o número de partículas por bloco. Um feixe tem no máximo maxBeamLength blocos (64 por padrão; 0 ou menos equivale a 64, nunca ilimitado) e nunca carrega um chunk: ele para na borda do mundo carregado. Um tabuleiro com feixe mais longo deve aumentar maxBeamLength.
  • Block Push. Cada empurrão move um bloco uma casa na direção em que o jogador olha. Um bloco empurrado de volta para a sua casa inicial é sempre aceito ali, e um buraco-alvo é desenhado de novo quando um bloco foi empurrado sobre ele e além. Deixe as casas iniciais vazias (ar) no mundo. Um bloco real ali fica oculto no cliente, mas continua sólido para o servidor, então ninguém poderia ficar em cima dele. Um empurrão recusado (uma parede, outro bloco) conta um erro por bloco e casa-alvo até um empurrão ter sucesso, então manter o clique contra uma parede não consome maxAttempts.
  • Lever Order. Uma alavanca fica no estado que tem no mundo quando o jogador chega ao tabuleiro, é acionada a partir dali e volta a esse estado por um reset ou após uma ordem errada, mesmo que fique ligada. Um clique durante o cooldown de falha não alcança uma alavanca real.
  • Combination Lock. A numeração começa em 0: a primeira posição listada em digits é o dígito 0, a segunda o dígito 1, e assim por diante. code lista esses índices na ordem dos cliques. Por exemplo, com quatro botões em digits, o código [2, 0, 3] significa: terceiro botão, primeiro botão, quarto botão. Um valor de code fora dos dígitos faz a fechadura ignorar todos os toques; o log do servidor nomeia o valor errado.
  • Pattern Placement. pattern lista os materiais linha por linha, com columns de largura, e seu comprimento deve ser um múltiplo de columns. A grade fica no plano horizontal no Y de gridOrigin, com colunas ao longo de X e linhas ao longo de Z. Uma prévia flutua previewOffsetY blocos acima. Com ghostBlocks ativado, uma versão translúcida é desenhada na própria grade e os blocos corretos são exibidos no cliente, retirando o item do jogador. Uma colocação errada é sempre cancelada. tolerance é o número de colocações erradas permitidas antes de o progresso ser redefinido.
  • Coop Pressure. Uma placa conta quando os pés de um jogador estão nesse bloco ou no bloco acima dele. Um jogador por placa. Todos os jogadores da audience participam, então adicione-os com /typewriter puzzle join <entry id>. Quando as placas forem seguradas por holdDuration, todos os participantes concluem o puzzle.
  • Item Frame. O frame já deve existir na posição configurada; o puzzle nunca cria um. Um frame vazio aceita apenas o requiredItem, retirado da mão do jogador. Cada clique em um frame preenchido o gira um passo (45 graus), e correctRotation é a contagem de passos de 0 a 7 em que ele está correto. O frame é uma entidade real, então a rotação é visível para todos.
  • Pedestal. O requiredItem pode ser entregue com o botão direito ou solto a até pickupRadius blocos do pedestal. Um item correspondente solto é removido quando consumeDroppedItem está ativado.

Comandos​

Todos os comandos são subcomandos de /typewriter (alias /tw). <id> é o entry id de um puzzle. Apenas os comandos admin exigem permissão.

ComandoDescrição
/typewriter puzzleAbre o menu de chat da primeira entry Puzzle Menu, ou informa que nenhuma existe.
/typewriter puzzle listLista os puzzles registrados e seus tipos.
/typewriter puzzle start <id>Adiciona você à audience de um puzzle. Recusa se você já o resolveu.
/typewriter puzzle join <id>Entra em um puzzle que já está em execução, por exemplo um puzzle cooperativo.
/typewriter puzzle chain <id>Inicia uma cadeia de puzzles pelo entry id ou nome.
/typewriter puzzle statusMostra o seu estado em cada puzzle: ativo, concluído, parado ou inativo.
/typewriter puzzle leaderboard <id>Mostra suas estatísticas e os dez melhores jogadores de um puzzle.
/typewriter puzzle stop [id]Interrompe um puzzle ou todos os seus puzzles ativos e redefine o progresso deles.
/typewriter puzzle closeFecha o seu inventário aberto.
/typewriter puzzle admin reset <player> <id>Redefine o estado de um jogador em um puzzle e o reinicia. Para um puzzle compartilhado, reabre-o para todo o grupo do jogador.
/typewriter puzzle admin reloadLimpa todos os estados e cadeias em tempo de execução.

Permissões​

PermissãoConcede
puzzle.adminOs comandos /typewriter puzzle admin.

Configuração​

Persistência. Sem um Puzzle Artifact, nada é salvo. Com um, a extensão salva o estado e as estatísticas a cada 30 segundos e ao desligar, e os carrega ao iniciar. Crie exatamente um artifact e mantenha o artifactId gerado. O artifact é obrigatório para puzzles compartilhados (veja Puzzles compartilhados).

O que sobrevive a uma desconexão

Quando um jogador se desconecta, o estado do puzzle dele é removido da memória, e o próximo salvamento não o contém. As estatísticas permanecem. Para lembrar de forma definitiva um puzzle resolvido, defina o fact do puzzle e leia esse fact nos seus criteria. O Puzzle Solved Fact só reflete o estado em memória. Um puzzle compartilhado é a exceção: sua resolução pertence ao grupo e é salva no artifact.

Mensagens. Nenhum texto exibido no jogo está fixo no código. Os textos de um puzzle são campos da sua entrada, e as respostas dos comandos e as duas mensagens compartilhadas por todos os puzzles são snippets. Veja Textos editáveis.

Textos editáveis​

Os textos são MiniMessage, então você pode reescrevê-los, traduzi-los ou mudar as cores. Um {name} em um texto é substituído pelo valor indicado nas tabelas abaixo; um placeholder que não existe permanece como escrito. Os placeholders do PlaceholderAPI (%...%) são lidos para o jogador que recebe o texto. Só o log do console do servidor permanece fixo, em inglês.

Campos das entradas​

Esses campos ficam na entrada, no painel web. Cada um é um texto por jogador, então aceita variáveis, e um valor em branco não envia nada. As páginas existentes mantêm os textos que já armazenam; os padrões abaixo valem para entradas novas e para páginas que nunca armazenaram o campo.

EntradaCampoPadrãoPlaceholders
Todos os puzzleshintMessageA dica de cada tipo de puzzle, por exemplo <yellow>Repeat the sequence! {progress}/{total}.{progress}, {total}
Todos os puzzlescompletionMessage<green>Puzzle completed!nenhum
Puzzle MenutitleText<gold><bold>Puzzles</bold> <gray>-nenhum
Puzzle MenupuzzleLineText<green>{puzzle} <gray>- <aqua>click to start{puzzle}, o id da entrada do puzzle
Puzzle MenufooterText<gray>Use <white>/typewriter puzzle stop<gray> to stop all active puzzles.nenhum
Memory SequencememorizeMessage<gold>Memorize the sequence…nenhum
Memory SequenceyourTurnMessage<green>Your turn! <white>{progress}/{total}{progress}, {total}
Memory SequencestepCorrectMessage<green>Well done! <white>{progress}/{total}{progress}, {total}
Lever OrderwrongOrderMessage<red>Wrong order — the levers have been reset.nenhum
Pattern PlacementprogressMessage<green>Pattern <white>{progress}/{total}{progress}, {total}
Item FramemissingFrameMessage<red>No item frame at <white>{x} {y} {z}{x}, {y}, {z}
Item FramewrongItemMessage<red>That is not the right item in the frame.nenhum
Item FrameinsertingMessage<gray>Inserting the item…nenhum
Item FramemissingItemMessage<yellow>First place the requested item in the frame.nenhum
Item FrameitemPlacedMessage<green>Item placed — rotate the frame.nenhum
Item FramerotationMessage<gray>Rotation {current}/{total}{current}, {total}

hintMessage, completionMessage e os campos do menu de chat são enviados no chat; os demais campos aparecem na action bar. Alguns desses padrões eram em francês em versões anteriores; agora são em inglês, e uma página que armazenou o texto em francês o mantém.

Snippets​

Tudo o que os comandos /typewriter puzzle imprimem, os de administração incluídos, e as duas mensagens compartilhadas por todos os puzzles, é um snippet do TypeWriter. Abra plugins/Typewriter/snippets.yml, encontre a chave em content.puzzle, altere o valor e execute /tw reload. A extensão registra todos os seus snippets com o texto padrão ao iniciar, então eles aparecem no arquivo após a primeira inicialização.

Snippet (em content.puzzle.)PadrãoPlaceholders
command.no_menu<red>No puzzle menu configured.nenhum
command.list.none<red>No puzzles configured.nenhum
command.list.header<gold>=== Available Puzzles ===nenhum
command.list.line<green>{puzzle} <gray>- {type}{puzzle}, {type}
command.puzzle_not_found<red>Puzzle not found: <white>{puzzle}{puzzle}
command.start.already_completed<yellow>Puzzle already completed. Use <white>/typewriter puzzle admin reset {player} {puzzle}<yellow> to replay it.{player}, {puzzle}
command.start.started<green>Starting puzzle: <white>{type}{type}
command.join.already_completed<yellow>Puzzle already completed for you: <white>{puzzle}{puzzle}
command.join.joined<green>Joined puzzle: <white>{type}{type}
command.stop.not_active<gray>Puzzle is not active: <white>{puzzle}{puzzle}
command.stop.stopped<yellow>Stopped puzzle: <white>{puzzle}{puzzle}
command.stop.all_none<gray>No active puzzle.nenhum
command.stop.all_stopped<yellow>Stopped <white>{count} <yellow>puzzle(s).{count}
command.status.header<gold>=== Puzzle Status ===nenhum
command.status.line<gray>{puzzle}: {status} <dark_gray>progress={progress}{puzzle}, {status}, {progress}
command.status.active<green>ACTIVEnenhum
command.status.completed<aqua>COMPLETEDnenhum
command.status.stopped<yellow>STOPPEDnenhum
command.status.inactive<gray>INACTIVEnenhum
command.chain.not_found<red>Chain not found: <white>{chain}{chain}
command.chain.invalid<red>Chain is invalid or contains unresolved puzzles: <white>{chain}{chain}
command.chain.empty<red>Chain has no resolvable puzzle entries.nenhum
command.chain.started<green>Starting puzzle chain: <white>{chain}{chain}
command.leaderboard.header<gold>=== Puzzle Stats: <white>{puzzle} <gold>==={puzzle}
command.leaderboard.attempts<gray>Attempts: <white>{attempts}{attempts}
command.leaderboard.solves<gray>Solves: <white>{solves}{solves}
command.leaderboard.best_time<gray>Best time: <white>{seconds}s{seconds}
command.leaderboard.rows_header<gold>--- Leaderboard ---nenhum
command.leaderboard.row<gray>#{rank} <white>{player} <gray>- <white>{solves} solves{rank}, {player}, {solves}
command.leaderboard.row_timed<gray>#{rank} <white>{player} <gray>- <white>{solves} solves <gray>{seconds}s{rank}, {player}, {solves}, {seconds}
command.admin.reset.player_not_found<red>Player not found: <white>{player}{player}
command.admin.reset.done<green>Reset puzzle <white>{puzzle} <green>for <white>{player}{puzzle}, {player}
command.admin.reset.done_group<green>Reset puzzle <white>{puzzle} <green>for <white>{player} <green>and its group (<white>{count}<green> online){puzzle}, {player}, {count}
command.admin.reload.done<green>Puzzle runtime states cleared.nenhum
play.cooldown_wait<red>Puzzle on cooldown — <white>{seconds}s{seconds}
play.max_attempts<red>Too many mistakes — restart the puzzle to try again.nenhum

{type} é o nome do tipo de puzzle (Memory Sequence, Lever Order, ...) e {status} é um dos quatro snippets command.status.*, então ambos mantêm suas cores. Qualquer outro placeholder é texto simples: o que um jogador digita em um comando não pode adicionar formatação à resposta.

Entries​

14 entradas, geradas a partir do código-fonte da extensão.

Ações1
Fatos2
Audiências9
Artefatos1
Outras entradas1

Solução de problemas​

O tabuleiro não aparece. Você deve estar no mundo das posições do puzzle e a até activationRadius de uma delas. Posições deixadas em 0, 0, 0 são ignoradas, então um puzzle sem posições definidas não tem âncora.

Nada acontece quando clico. Verifique se você está na audience (os criteria devem corresponder e um filtro de audience deve incluir você) e se o puzzle ainda não foi resolvido por você: use /typewriter puzzle status e /typewriter puzzle admin reset <player> <id> para jogar de novo. Cliques durante o cooldown de falha são ignorados; a action bar mostra o tempo restante.

/typewriter puzzle start diz que o puzzle não foi encontrado. Os puzzles são registrados quando a extensão carrega, por entry id. Recarregue depois de adicionar um puzzle e use o entry id, não o nome.

O puzzle de memória nunca inicia. buttons precisa de pelo menos 2 entradas, e cada uma precisa de uma posição.

O puzzle de padrão ignora meus blocos. pattern deve ter um comprimento múltiplo de columns, e você deve colocar os blocos na grade no Y de gridOrigin. Um material errado é cancelado.

O puzzle de item frame diz que não há frame. Coloque primeiro um item frame na posição configurada. O log também imprime um aviso com as coordenadas.

O progresso se perde após reconectar. Veja o aviso em Configuração: use fact para manter o resultado.

Um puzzle cooperativo nunca conclui. Todos os jogadores devem estar na audience (/typewriter puzzle join <id>), ficar em uma placa diferente e permanecer ali por holdDuration. Itens soltos nas placas não contam.