Fazendo nevar numa fazenda de planície: fingindo clima de inverno no Minecraft Bedrock

O Bedrock não tem clima de neve e decide entre chuva e neve pelo bioma. Como o LLS Seasons monta um dia de neve com neblina, uma partícula e uma camada de neve própria, e o congelamento de verão que uma varredura de neve causou.

· 7 min de leitura

Neve caindo num campo limpo do LLS Farm Sim Pack no inverno

O Farm Sim Pack tem um ano de 28 dias, e o calendário só convence se o mundo muda junto. O verão é limpo, o outono tem tempestades e o inverno neva, inclusive numa fazenda de planície. É nessa última parte que o Bedrock mais resiste.

O Bedrock não neva quando você quer

Um script consegue colocar o clima numa de três coisas: Clear, Rain ou Thunder (limpo, chuva ou tempestade). Não tem neve. Se a precipitação que cai parece chuva ou neve é decidido no cliente de cada jogador pela temperatura do bioma, e nenhum script consegue mudar isso.

Então num bioma frio, Rain mostra neve. Em todo o resto, Rain mostra chuva. Meu primeiro plano era usar a chuva normal nos dias de neve, o que funciona numa taiga e fica errado numa fazenda de planície: você ganha gotas de chuva caindo e neve no chão ao mesmo tempo.

A resposta foi parar de usar o clima normal para a neve de vez.

Um dia de neve são três efeitos

Num dia de neve o céu fica em Clear, então o jogo normal não desenha nenhuma precipitação, e três coisas fazem o papel da neve:

  1. Neblina de céu nublado. A chuva escurece o céu; o Clear não. Uma neblina cinza que vem no pacote de texturas é aplicada em cada jogador durante o dia, então o céu fecha como deve.
  2. Neve caindo. Um efeito de partículas solta flocos em volta de cada jogador que está ao ar livre. Jogadores em biomas quentes são pulados, e essa verificação de bioma fica guardada por jogador em vez de ser repetida duas vezes por segundo.
  3. Neve no chão. Uma camada de blocos de neve é colocada em volta dos jogadores e das fazendas no primeiro dia do inverno e sobe um nível a cada dia de neve, até seis oitavos de bloco. Parei antes de um bloco inteiro de propósito: neve quase inteira deixa a caminhada bem mais lenta, e seis já parece funda.

A neblina também não é um tipo de clima normal, então ela tem o próprio sorteio. Cada estação sorteia as chances de forma separada a cada dia do calendário:

EstaçãoO céu
Primavera20% de chuva, senão limpo
VerãoLimpo, todo dia
Outono25% de tempestade com raios, senão 60% de chuva; 40% de neblina em cima de qualquer coisa; o último dia sempre neva
Inverno60% de neve; 20% de neblina em cima

O sorteio do dia fica guardado, então recarregar o mundo dá o mesmo céu. Se algo fora do pacote mudar o clima (o próprio ciclo de clima do jogo, ou dormir durante uma tempestade), o pacote coloca o clima do dia de volta assim que percebe.

A camada não parava de derreter

Colocar neve é fácil. Manter, não. O jogo normal derrete snow_layer com as atualizações aleatórias (random ticks) onde o bioma é quente ou a luz é forte, que é em todo lugar numa fazenda de planície. Uma camada recém-colocada ficava cheia de quadrados pelados em minutos.

A primeira correção foi uma passada de conserto: de tempos em tempos, achar os buracos e preencher. Funcionava, e parecia quebrado. As atualizações aleatórias são espalhadas, então o degelo levava o campo um bloco por vez, e cada buraco ficava pelado até a próxima passada colocar de volta, muitas vezes bem na frente do jogador. Derreter e depois repintar não parece clima. Parece bug.

Primeira correção: desligar as atualizações aleatórias

A primeira correção de verdade parou o degelo na fonte. Enquanto o inverno tinha neve no chão, o pacote colocava randomtickspeed em 0, e devolvia o valor do próprio mundo no degelo. É uma marretada no mundo inteiro, então ela ficava na janela mais curta possível: o inverno, e só enquanto tivesse camada no chão.

Só dava para bancar porque as plantações do Farm Sim não crescem com atualizações aleatórias; elas rodam num contador de dias, um estágio à meia-noite. Mas todo o resto que usa isso parava durante a semana: mudas, cana-de-açúcar, cacto, bambu, cacau, fungo do Nether, cogumelos, o fogo se espalhando, o cobre oxidando, as folhas caindo. Uma árvore cortada no inverno ficava com as folhas até a primavera. Funcionava, e mexia em muito mais coisa do mundo do que a neve tem direito.

A correção de verdade: neve própria

Desde a 0.6.5, a camada não é mais neve normal. É llss:snow_layer, um bloco do próprio pacote com as mesmas oito alturas da neve normal e sem comportamento de atualização aleatória. Nada derrete ela a não ser o próprio pacote, então as atualizações aleatórias ficam ligadas o inverno todo e as mudas continuam crescendo.

Isso resolveu um segundo problema também. As passadas antigas colocavam e tiravam minecraft:snow_layer, então o degelo da primavera também podia tirar neve normal: a de um bioma frio, a de um golem de neve, ou neve que um jogador colocou de propósito. Agora cada passada só mexe no próprio bloco, e a neve normal nunca é tocada.

Mundos que rodaram a versão antiga voltam sozinhos para o próprio randomtickspeed: o valor guardado durante um inverno antigo é restaurado, não o padrão do Bedrock.

A passada de conserto continua lá como rede de segurança para buracos que o jogo não fez: um pedaço que um jogador cavou, um chunk que carregou depois da passada que colocou a neve, uma camada levada pela água.

Fazendo um trabalho grande não travar o jogo

Uma temporada de fazenda cobre muito terreno, e colocar ou derreter neve em tudo isso são centenas de milhares de colunas de blocos. Feito de uma vez, isso trava o servidor.

Cada passada roda como um trabalho: um gerador entregue ao system.runJob, que o Bedrock avança um pouco a cada tick. O problema é que um trabalho anda um passo por tick que recebe, não importa quanto trabalho cada passo faça. Com uma coluna por passo, um degelo completo foi medido num ritmo que levaria mais que um ano de verdade. Então cada passo cuida de um lote de colunas antes de ceder. O tamanho do lote é o único botão entre “visivelmente lento” e “o servidor engasga”.

O pacote também precisa lembrar onde colocou neve, ou nunca vai conseguir derreter. Toda vez que um jogador anda meio raio para dentro de terreno novo, o lugar novo é adicionado como um “centro de camada”. São guardados até 300 centros, o que cobre uma temporada de fazenda de verdade numa lista pequena o bastante para guardar junto com o mundo.

Biomas quentes e frios

Não devia nevar num deserto, e só os biomas frios deveriam manter a neve quando a primavera chega. A versão da API de scripts para a qual este pacote foi feito não tem uma chamada getBiome(), então o clima é lido como um bloco de comando faria: execute if biome contra uma lista curta de IDs de biomas quentes e frios, tentando até um bater.

Isso é lento se você faz para cada coluna, então é feito uma vez por centro de camada e guardado nele. No pior caso, um centro bem na borda de um bioma recebe a decisão errada, o que é um problema muito menor do que travar o servidor conferindo cada bloco.

A primavera, e o congelamento que ela causou

O degelo roda nos primeiros dias da primavera: alguns dias visíveis da camada ficando mais rasa um nível por vez, e depois uma passada final tira o que sobrou fora dos biomas frios.

Depois disso, uma proteção mantém a neve fora dos biomas quentes até o outono acabar, caso um chunk que estava descarregado no degelo carregue depois com neve ainda em cima. A primeira versão dessa proteção me custou uma semana de confusão. A cada 15 segundos ela apagava de novo a neve em volta de cada centro de camada guardado (até 300, de 64 blocos cada) e de cada jogador, tudo de uma vez, sem nunca ceder, e dava erro em cada coluna de um chunk descarregado.

No jogo isso era um congelamento de três segundos a cada dezoito segundos o verão inteiro. Parecia um bug dos cavalos e lag de outros pacotes. A pista estava no registro de conteúdo: linhas repetidas de [Watchdog] Spike, com o mesmo espaço entre elas. O espaço entre os picos é o período do temporizador mais o próprio travamento, porque os ticks do jogo não andam durante um travamento. Dezoito segundos menos um travamento de três segundos são quinze, que era exatamente esse temporizador.

A proteção agora roda como um trabalho pequeno próprio num temporizador de dois segundos: só os centros perto de um jogador, uma verificação barata de que o chunk está carregado antes de mexer nas colunas dele, o chunk mais próximo primeiro, algumas centenas de colunas por tick, e um centro é riscado da lista de vez quando todos os chunks dele já foram varridos. O congelamento sumiu desde a 0.6.5.

Alguns números deste sistema só estão certos porque foram medidos num mundo de fazenda de verdade. O alcance em volta de cada jogador (64 blocos) é limitado pela distância de simulação: chunks mais longe não estão carregados, então o script não consegue colocar neve neles, e uma leitura de depuração conta essas falhas para eu saber se um raio maior ajudaria de verdade.

Experimente

As estações, a neve e o calendário de plantio estão no Farm Sim Pack. O guia do primeiro ano é um plano estação por estação para uma fazenda nova. Se você usa /time set e não entende por que o inverno não acaba: ele move o sol, não o calendário. Use /scriptevent llss:setseason spring.

O mod

Mais do devlog

← Todo o devlog