Saltar para o conteúdo principal

Módulos de comportamento de mascotes

Um módulo de comportamento de mascote é um ficheiro Lua que diz às mascotes o que fazer: seguir o dono, flutuar, rodear uma fogueira, picar. Cada ficheiro de espécie de mascote lista os módulos que as suas mascotes executam e dá-lhes definições. Esta página destina-se aos autores de criaturas que querem alterar um módulo ou escrever um novo. Para usar e ajustar os módulos incluídos, consulte Mascotes.

Os módulos usam o mesmo dialeto Lua dos programas de comportamento do EliteMobs: ai.module, ai.behavior, ai.sensor, ai.controls, memórias tipadas e o contexto c.memory, c.perception, c.actuator e c.entity. Essa página descreve as regras partilhadas. Esta descreve o que as mascotes acrescentam: os ficheiros dos módulos, c.pet, c.settings e os limites em que as mascotes são executadas.

Ficheiros​

  • Os módulos ficam em plugins/FreeMinecraftModels/pet_behaviors/, nessa pasta ou em qualquer subpasta. Todos os ficheiros .lua aí são módulos.
  • O nome de um módulo é o nome do seu ficheiro sem .lua, em minúsculas. Só pode usar letras, dígitos, ., _ e -. Os ficheiros de mascotes listam os módulos por este nome.
  • O id de um módulo tem de ser fmm:pet/ seguido do seu nome, pelo que pet_behaviors/mine/slow_drift.lua declara id = 'fmm:pet/slow_drift'. Um módulo cujo id não corresponda ao nome do ficheiro é ignorado com um aviso.
  • Quando dois ficheiros têm o mesmo nome, carrega aquele cujo caminho vem primeiro por ordem, e a consola avisa Duplicate content filename sobre o outro. Uma cópia idêntica byte a byte é ignorada sem aviso.
  • Um ficheiro ou pasta que aponte para fora de pet_behaviors/ é ignorado.
  • O FreeMinecraftModels escreve cada um dos seus 15 módulos incluídos quando não existe em lado nenhum da pasta um ficheiro com esse nome. Um módulo eliminado volta no carregamento seguinte, com a versão incluída atual. Um ficheiro que já lá esteja nunca é substituído, editado ou não, mesmo depois de o mover para uma subpasta, pelo que mantém as suas alterações e também não recebe as atualizações posteriores do módulo incluído.
  • /fmm reload volta a ler todos os módulos e ficheiros de mascotes, recolhe as mascotes e trá-las de volta com os novos módulos. As suas memórias começam vazias. Não é preciso aumentar a revision de um módulo depois de o editar.

Comece por uma cópia​

Os módulos incluídos são os melhores exemplos: drift.lua move uma voadora, wander.lua anda, night_glow.lua é um único sensor e sting.lua tem dois. Comece pelo que estiver mais perto do que pretende.

  1. Copie-o com um novo nome, por exemplo pet_behaviors/mine/slow_drift.lua a partir de drift.lua.
  2. Altere o seu id para fmm:pet/slow_drift.
  3. Mude o nome das suas memórias, comportamentos e sensores para que comecem pelo novo nome: drift_to passa a slow_drift_to, em memories e em todas as chamadas c.memory, e o id = 'fmm:pet/drift' do comportamento passa a fmm:pet/slow_drift. Dois módulos na mesma criatura não podem partilhar um nome de memória, um id de comportamento nem um id de sensor; o segundo listado fica de fora com um aviso. Mudar os nomes permite que a cópia seja executada ao lado do original.
  4. Liste-o no ficheiro da mascote no lugar do original: - slow_drift, ou com definições, - slow_drift: { speed: 0.03 }.
  5. Execute /fmm reload e verifique a consola.

Editar um módulo incluído no próprio sítio também funciona, mas altera todas as espécies que o listam.

Um ficheiro de módulo​

Este módulo é pequeno mas completo. À noite, a mascote assenta num sítio perto da sua âncora em vez de flutuar e, a cada 10 segundos desde o momento em que escolhe esse sítio, reproduz uma animação.

-- At night: settles on one spot near its anchor (its owner, or home when wild) and plays an animation now and then.
return ai.module {
id = 'fmm:pet/night_rest', revision = 1,
-- radius: blocks around the anchor. speed: blocks per tick for a flyer, at species speed 1.
settings = { radius = 3, speed = 0.04, animation = 'interact' },
memories = { night_rest_to = 'position', night_rest_retry = 'integer' },
behaviors = {
ai.behavior {
id = 'fmm:pet/night_rest', priority = 12, probe_interval = 10,
controls = { ai.controls.move, ai.controls.look },
can_start = function(c)
return c.pet.night and not c.pet.staying and c.pet.anchor ~= nil
and c.tick >= (c.memory:get('night_rest_retry') or 0)
end,
can_continue = function(c)
return c.pet.night and not c.pet.staying and c.memory:contains('night_rest_to')
end,
start = function(c)
local anchor = c.pet.anchor
local to = anchor and c.pet:rest_point(anchor, c.settings.radius)
if to ~= nil then
c.memory:set('night_rest_to', to)
else
-- Nothing fits here: look again in 5 seconds instead of every tick.
c.memory:set('night_rest_retry', c.tick + 100)
end
end,
tick = function(c)
local to = c.memory:get('night_rest_to')
if to ~= nil then c.pet:steer_to(to, c.settings.speed * c.pet.species.speed) end
end,
stop = function(c)
c.memory:forget('night_rest_to')
c.pet:stop()
end
}
},
sensors = {
ai.sensor {
id = 'fmm:pet/night_rest_animation', interval = 200,
sense = function(c)
if c.memory:contains('night_rest_to') then c.pet:play_animation(c.settings.animation) end
end
}
}
}

Um ficheiro de mascote lista-o então como - night_rest, ou - night_rest: { radius: 5, animation: idle }.

CampoNotas
idObrigatório. fmm:pet/ e o nome do ficheiro
revisionObrigatório. Qualquer número inteiro positivo
settingsOpcional. As predefinições que os ficheiros de mascotes podem alterar. O tipo de cada predefinição é o tipo que um ficheiro de mascote tem de dar: um número, true/false, texto ou uma lista de textos. Consulte Valores das definições
memoriesOpcional. O que o módulo recorda para cada mascote, por nome e tipo: integer, number, boolean, string, uuid ou position. Comece cada nome pelo nome do módulo. Consulte Memórias
dependenciesOpcional. IDs de outros módulos de pet_behaviors/ de que este precisa. São executados em todas as criaturas que listam este, com as suas definições predefinidas, a menos que o ficheiro da mascote também os liste
behaviorsOpcional. Entradas ai.behavior { ... }, que movem ou viram a mascote
sensorsOpcional. Entradas ai.sensor { ... }, que nunca movem a mascote

O código acima de return, como funções locais e constantes, é permitido; wander.lua e idle_look.lua têm alguns.

O que recebe um callback​

NomeO que é
c.petA mascote, só de leitura. Consulte c.pet
c.settingsAs definições deste módulo: as suas predefinições com os valores do ficheiro da mascote e da variante por cima, como em c.settings.radius. Cada mascote tem a sua própria cópia, pelo que escrever nela altera apenas essa mascote
c.memoryget(name), set(name, value), forget(name) e contains(name) para os nomes em memories. Cada mascote tem a sua
c.tickO tick atual do jogo, para temporizadores
c.perception, c.actuator, c.entityO contexto Mind do MagmaCore, como nos programas de comportamento do EliteMobs. c.entity é o corpo oculto, não o modelo. Consulte Contexto de um programa Mind. idle_look.lua usa c.perception:nearest_player(range) e c.actuator:look_at(point)

c.pet​

Um ponto é uma tabela com x, y e z, e opcionalmente world, como c.pet.position. Um ponto sem world está no mundo da mascote. Um ponto noutro mundo conta como nada: os métodos respondem nil, false ou 0, e distance_to responde math.huge. Os pontos que c.pet devolve estão sempre no mundo da mascote, e um que ficasse noutro lado é lido como nil.

  • Os métodos são chamados com dois pontos: c.pet:distance_to(point).
  • Os argumentos numéricos têm de ser finitos. Os raios, profundidades, alturas, amplificadores, durações e os outros intervalos têm os limites indicados abaixo. Nenhum método carrega um chunk.
  • c.pet e c.pet.species são só de leitura. Atribuir-lhes gera um erro; guarde os valores por mascote em c.memory.
  • As propriedades e route_target() são um instantâneo: cada uma é lida uma vez por tick da mascote e mantém-se igual em todos os callbacks desse tick. c.pet:teleport_near_owner e c.pet:stop atualizam-nas. Um movimento feito de outra forma, como c.entity:teleport, aparece no tick seguinte. speed é a exceção e é sempre lida de novo.
  • Cada leitura de uma posição dá uma tabela nova, que o módulo pode alterar.

Propriedades​

NomeTipoValor
wildbooltrue numa mascote selvagem, false numa com dono
stayingboolTem ordem para ficar quieta
settledboolNão está a ficar quieta, e é selvagem ou está a menos de follow.distance do dono
babyboolÉ uma cria
migratingboolEstá a voar um percurso de migração noturna
modelstringO modelo da sua variante. Uma cria que veste babyModel continua a ler a sua variante
positionpointOnde está o seu corpo
homepoint/nilOnde vive uma mascote selvagem; nil numa mascote com dono
anchorpoint/nilAquilo à volta do qual vagueia: o dono ou, numa mascote selvagem, a sua casa, ou o sítio onde está se não tem nenhuma. nil quando o dono está offline ou noutro mundo
stay_anchorpoint/nilO sítio onde lhe mandaram ficar; nil quando não está a ficar quieta
owner_locationpoint/nilnil numa mascote selvagem, ou quando o dono está offline, morto ou noutro mundo
owner_distancenumberBlocos até ao dono; math.huge quando não há nenhum neste mundo
night, dayboolday só à luz do dia num mundo normal; o anoitecer, o amanhecer, o Nether e o End contam como night
rainingboolA chuva cai sobre a mascote, verificado no máximo a cada 10 ticks
speednumberA velocidade atual do seu corpo, em blocos por tick
route_cruisenumberA velocidade de cruzeiro do seu bando numa migração, caso contrário 0
speciestableOs números do ficheiro da mascote, abaixo

c.pet.species contém:

CampoChave do ficheiro da mascote
idspecies
speedfollow.speed
hover_heightfloat.hoverHeight
hover_variancefloat.hoverVariance
roam_radiusfollow.roamRadius
follow_distancefollow.distance
leash_distancefollow.leashDistance
teleport_distancefollow.teleportDistance
scalescale
baby_scalebabyScale

Movimento​

Chame-os apenas a partir de start, tick ou stop de um comportamento, num comportamento cujo controls liste o que precisam. A partir de can_start ou de um sensor, steer_to e stop geram um erro que indica onde pertencem.

MétodoDevolveO que faz
steer_to(point, cruise)boolUm tick em direção ao ponto, por isso chame-o a cada tick. Precisa de move e look. Uma voadora voa a cruise blocos por tick (0 a 4), abrandando à chegada. Uma caminhante ou nadadora segue até lá nativamente a 4 × cruise vezes a velocidade de movimento do seu tipo de corpo, nunca abaixo de um quarto dela; um cruise de 0 imobiliza-a e devolve false. false quando não pode ir para lá
stop()nilPara de se mover. Precisa de move
teleport_near_owner(radius)boolColoca o corpo junto do dono, a até radius blocos (até 64), no meio em que se desloca; uma nadadora procura água num raio de radius ou de 6 blocos, o que for maior. Uma caminhante ou nadadora aterra a pelo menos um bloco do dono. false quando o dono está longe ou noutro mundo, nada serve, ou o sítio não fica pelo menos um bloco mais perto do dono do que a mascote está. Não precisa de nenhum controlo, mas chame-o a partir de um comportamento que detenha move, como follow_owner faz, para não afastar a mascote de outro comportamento

Sítios e distâncias​

Funcionam a partir de qualquer callback. Os que devolvem um ponto devolvem nil quando nada serve ou o chunk não está carregado. Os raios vão até 64.

MétodoDevolveO que faz
hover_point(center, radius)point/nilUm ponto na sua faixa de pairar a até radius
rest_point(center, radius)point/nilUm sítio onde descansar no meio em que se desloca: a faixa de pairar numa voadora, chão onde se possa estar de pé numa caminhante ou num corpo estacionário, água numa nadadora (à altura de center quando center está na água, caso contrário 0,5 a 2 blocos abaixo da superfície), e chão ou, na falta dele, água num corpo anfíbio
ground_point(center, radius)point/nilUm sítio onde estar de pé, desde cerca de 5 blocos abaixo até 4 acima de center. nil sobre líquido ou uma queda longa
water_point(center, radius, min_depth, max_depth)point/nilUm sítio de nado entre as duas profundidades abaixo da superfície (0 a 16)
ground_below(point, depth)number/nilA altura do topo do chão a até depth blocos abaixo (1 a 64). Uma superfície de água ou lava conta como chão, a menos que a espécie seja AQUATIC. Sem chão ao alcance, a altura do ponto menos depth
trail_point(back, height)point/nilback blocos atrás de onde o dono está virado, height acima dos seus pés numa espécie FLYING e aos seus pés nas outras. nil quando o dono está longe ou noutro mundo
distance_to(point)numberBlocos desde o seu corpo
route_target()point/nilOnde o seu percurso de migração a quer neste tick. nil quando não está a migrar ou o percurso terminou
find_perch(height, radius)point/nilheight blocos (0 a 8) acima da folhagem mais próxima por baixo dela, até radius blocos (0 a 4) para o lado, ou acima do chão mesmo por baixo. Uma mascote com dono só obtém um poiso a menos de follow.distance do dono
nearest_campfire(radius, keep_ticks, blocks, soul_variants, height)point/nilO bloco da fogueira acesa mais próxima que pode usar a até radius (1 a 32). blocks lista os tipos de fogueira que aceita, CAMPFIRE, SOUL_CAMPFIRE ou ambos, e uma lista que não nomeie nenhum aceita ambos; soul_variants lista os modelos que aceitam apenas fogueiras de almas, e todos os outros modelos aceitam então apenas as normais. Uma mascote com dono só aceita uma fogueira cujo sítio, height acima dela, esteja a menos de follow.distance menos 1 do dono. A procura de cada chunk é mantida durante keep_ticks (20 a 1200) e partilhada por todas as mascotes
campfire_usable(fire, blocks, soul_variants, height)boolSe uma fogueira encontrada antes continua acesa e continua a servir

Efeitos​

Funcionam a partir de qualquer callback; os sensores são o sítio habitual.

MétodoDevolveO que faz
set_glow(light, lantern_bone, animation)nilIlumina os ossos de apresentação do modelo a light (0 a 15), para jogadores Java. Um modelo com um osso chamado lantern_bone repete também animation. Os dois últimos são opcionais
clear_glow()nilVolta à luz do mundo, terminando essa animação
scale_toward(target, span, ticks, elapsed)nilAproxima suavemente o tamanho do corpo de target vezes o seu tamanho base. Uma mudança completa de 1 para span demora ticks (no mínimo 2); elapsed são os ticks desde a última chamada. Multiplicadores de 0.1 a 16
sting_contacts(on, effect, duration, amplifier, damage, cooldown)numberPica os jogadores cujo toque atingiu o modelo de uma mascote selvagem no último segundo, nunca um em modo Criativo ou Espectador, e devolve quantos. Limpa os toques mesmo quando on é false. As mascotes com dono não registam toques
sting_enemies(reach, effect, duration, amplifier, damage, cooldown)numberPica os mobs hostis a até reach blocos (0 a 4) da hitbox do modelo, nunca jogadores nem mascotes, e devolve quantos
drizzle(depth, chance)boolQuando a mascote paira imóvel sobre uma cultura a até depth blocos (1 a 8), partículas de água e uma probabilidade chance (0 a 1) de a cultura crescer uma fase. true quando está sobre uma cultura
owner_effect(effect, duration, amplifier, range)boolDá ao dono o efeito de poção durante duration ticks (1 a 6000) quando ele está a até range blocos, sem partículas. Um efeito que o dono já tenha com pelo menos a mesma força e duração é deixado em paz. false quando o dono está longe, noutro mundo ou fora do alcance, ou o efeito não existe
play_animation(name)boolReproduz uma vez uma das animações do modelo. false quando o modelo não a tem

Em ambas as picadas, effect é um nome de efeito de poção ou NONE, duration é em ticks (1 a 6000), amplifier 0 é o nível I (até 255), damage é em meios corações, e cooldown são os ticks (no mínimo 1) até esta mascote poder picar de novo a mesma vítima. Uma picada mostra faíscas e reproduz um som de picada de abelha, e um adulto reproduz a sua animação attack. Um nome de efeito de poção que não exista gera um aviso uma vez por espécie e nome, e não aplica nada.

Comportamentos e sensores​

  • Um comportamento move ou vira a mascote. Lista os controlos de que precisa, ai.controls.move e ai.controls.look para as chamadas de movimento de c.pet, e só um comportamento detém um controlo de cada vez. Enquanto está parado, o MagmaCore pergunta o seu can_start. Quando devolve true e os controlos estão livres, assume-os e executa start, depois tick a cada tick enquanto can_continue devolver true (sem can_continue, decide can_start), depois stop. Consulte Ciclo de vida.
  • O número de priority mais baixo vai primeiro. Um comportamento tira os controlos a um comportamento em execução com um número mais alto, cujo stop é então executado. O 12 do exemplo mantém seguir e ficar quieta à sua frente e coloca-o à frente de flutuar e pairar, mas também à frente de campfire, pelo que uma mascote que liste ambos nunca visita uma fogueira à noite. Um número acima de 15 deixaria a fogueira vencer.
  • Um comportamento só compete pelos controlos que lista. idle_look ocupa apenas look, pelo que é executado enquanto nenhum comportamento detiver o olhar; todos os comportamentos de movimento incluídos ocupam também look, pelo que mover-se vence sempre.
  • Um ficheiro de mascote não pode alterar uma prioridade. Para reordenar, copie o módulo e altere o número.
  • probe_interval é opcional, em ticks: enquanto o comportamento está parado, can_start só é perguntado a cada esse número de ticks, na fase própria de cada mascote. Poupa tempo do servidor quando há muitas mascotes fora, à custa de o comportamento arrancar até esse número de ticks mais tarde. Por predefinição é 1 e conta como 200 acima disso. Um comportamento em execução continua a ser executado a cada tick.
  • Um sensor nunca move a mascote. Executa sense no primeiro tick em que o corpo da mascote é processado e depois a cada interval ticks na fase própria da mascote, seja o que for que os comportamentos estejam a fazer. O brilho, o inchaço, as picadas, o chuvisco e os efeitos no dono são sensores.

Os módulos incluídos usam:

MóduloPrioridadeprobe_intervalinterval do sensor
migrate110
stay54
follow_owner104
campfire1510
day_perch1810
rain_bloom19104 (inchaço)
drift, wander, swim2010
hover304
idle_look3010
night_glow40
sting4 (jogadores), 10 (mobs)
crop_drizzle20
owner_effect20

Regras​

  • Chame steer_to e stop apenas a partir de start, tick ou stop de um comportamento, num comportamento que liste os controlos de que precisam.
  • Guarde o estado por mascote em c.memory, declarado em memories, com nomes que comecem pelo nome do módulo.
  • Não escreva em c.pet; atribuir-lhe gera um erro.
  • Mantenha os callbacks curtos. Todas as mascotes são executadas com estes limites fixos, que os módulos e os ficheiros de mascotes não podem alterar:
LimiteValor
Um callback1,5 ms
Os callbacks de uma mascote num tick3 ms, no máximo 32 callbacks
Os callbacks de todas as mascotes num tick10 ms
Tempo de CPU de um callback, limite rígido20 ms
Instruções Lua de um callback, limite rígido20.000

Quando uma mascote atinge um dos três primeiros limites, os seus callbacks restantes esperam pelo tick seguinte. Um callback que ultrapasse um limite rígido é interrompido e falha como um erro. Consulte Orçamentos.

Quando algo está errado​

Nenhum destes problemas para o servidor nem as outras criaturas. Procure na consola por pet behavior, pet_behaviors e .pet.yml para encontrar estes avisos.

  • Um módulo não carrega. Um módulo que não compila, cujo id não corresponde ao nome do ficheiro, ou cujo nome de ficheiro tem outros caracteres, é ignorado com um aviso que indica o ficheiro e, num erro Lua, a linha. Todos os outros módulos continuam a carregar.
  • Um ficheiro de mascote indica um módulo que não existe. O aviso indica o ficheiro da mascote e sugere o nome de módulo mais próximo quando há um com uma ou duas letras de diferença. A criatura carrega sem ele. Quando o módulo existe mas falhou ao carregar, o aviso remete para o aviso sobre o seu ficheiro.
  • Uma definição está errada. Uma definição que o módulo não tem, ou um valor do tipo errado, é comunicada com o nome do ficheiro da mascote, e a predefinição mantém-se. Consulte Valores das definições.
  • Dois módulos entram em conflito. Quando dois módulos na mesma criatura declaram o mesmo nome de memória, id de comportamento ou id de sensor, a criatura mantém o primeiro da lista e é executada sem o outro, com um aviso.
  • Um callback falha enquanto as mascotes são executadas. É registado uma vez por programa, callback e tipo de falha até ao recarregamento seguinte. Os programas chamam-se fmm:pet/creature/<species>/<variant>, e os callbacks pelo id do seu comportamento ou sensor, como fmm:pet/drift.tick. Um comportamento que falhou é parado, ou não arranca, e é tentado de novo a partir do tick seguinte; enquanto continuar a falhar, os comportamentos com números de prioridade mais altos que movem ou viram a mascote podem não ser executados. Um sensor que falhou é executado de novo no seu intervalo seguinte.
  • Uma chamada c.pet falha dentro do FreeMinecraftModels. A causa é registada uma vez por espécie e chamada, com o respetivo stack trace, e o callback falha com c.pet:<method> failed; the server log has the cause.
  • Um nome de efeito de poção não existe. É avisado uma vez por espécie e nome, e a chamada não aplica nenhum efeito.

Depois de uma correção, execute /fmm reload.