Guia do MagmaCore para programadores
A referência Java gerada permite pesquisar classes, métodos e assinaturas, com a versão e o commit do código registados para cada módulo.
O MagmaCore é uma biblioteca incorporada por shading nos plugins que a utilizam. Não é um plugin de servidor autónomo e não deve aparecer em depend como se os jogadores pudessem instalar um JAR de plugin MagmaCore.
Dependência e empacotamento
A coordenada de desenvolvimento atual é com.magmaguy:MagmaCore:2.2.0-SNAPSHOT. É publicada no repositório de releases do MagmaGuy, e não no repositório de snapshots, que contém apenas snapshots 1.x mais antigos. Os snapshots podem mudar sem alterar essa versão, e a compilação publicada não é renovada a cada lançamento de plugin, pelo que pode ser mais antiga do que o MagmaCore incorporado nos plugins atuais. A compilação publicada a 5 de outubro de 2026 inclui as APIs de atualização sem reinício e de partidas descritas abaixo. Para compilar contra alterações mais recentes ainda não publicadas, compile o MagmaCore a partir do código-fonte e publique-o no Maven Local, como descrito em Compilar um plugin após alterações à biblioteca. Registe o artefacto resolvido se precisar de compilações reproduzíveis.
repositories {
maven("https://repo.magmaguy.com/releases")
}
dependencies {
implementation("com.magmaguy:MagmaCore:2.2.0-SNAPSHOT")
}
<repositories>
<repository>
<id>magmaguy-releases</id>
<url>https://repo.magmaguy.com/releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>MagmaCore</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
</dependencies>
Estas declarações resolvem a dependência. Configure a tarefa de shading para a incluir no JAR final do plugin. Siga as regras de relocação de um plugin existente com as mesmas necessidades de integração e verifique as pesquisas por reflexão baseadas em strings ao alterar nomes de pacotes. A distribuição reloca org.luaj, org.reflections e javassist para com.magmaguy.shaded e exclui as classes javax.annotation usadas apenas na compilação.
Cada plugin pode ter a sua própria cópia carregada da biblioteca. Classes Java com o mesmo nome carregadas por classloaders de plugins diferentes são tipos distintos. Use os contratos explícitos entre plugins, como o serviço de poderes Lua do EliteMobs e os adaptadores do registo de localizações. Não converta um objeto MagmaCore privado de outro plugin para o tipo da sua cópia.
Módulos e responsabilidades
| Módulo | Responsabilidade |
|---|---|
core | Ciclo de vida do plugin, configuração, comandos, menus, partidas, consultas de localização, scripts Lua, conteúdo Nightbreak e utilitários partilhados |
nms:core | NMSManager, NMSAdapter e as interfaces EasyMinecraftGoals independentes da versão |
nms:v* | Implementações do contrato NMS para cada versão do servidor |
dist | Distribuição com shading que contém o núcleo e os adaptadores ativos |
Os encantamentos partilhados, ações de itens, gestão de contas, menus de configuração, catálogos e atualizações pertencem aos serviços do núcleo. Reutilize o componente responsável ao acrescentar comportamento a um plugin que use a biblioteca.
Ciclo de vida do plugin
O ciclo de vida mínimo do núcleo segue o padrão dos plugins existentes:
package example;
import com.magmaguy.magmacore.MagmaCore;
import org.bukkit.plugin.java.JavaPlugin;
public final class CoreConsumer extends JavaPlugin {
@Override
public void onLoad() {
MagmaCore.createInstance(this);
}
@Override
public void onEnable() {
MagmaCore.onEnable(this);
}
@Override
public void onDisable() {
MagmaCore.shutdown(this);
}
}
Esta inicialização faz mais do que obter um objeto utilitário. Inicializa a gestão de contas, comandos partilhados, listeners e suporte para blocos temporários. A sobrecarga createInstance(plugin, NightbreakPluginSpec) fornece os textos específicos do plugin para os comandos partilhados.
Prefira métodos que recebam explicitamente o plugin proprietário. getInstance() refere-se ao singleton da cópia carregada da biblioteca. O plugin associado é definido quando essa instância é criada. Não o use para inferir o proprietário de todos os plugins que utilizam a biblioteca.
shutdown(plugin) limpa os registos de descargas, atualização de conteúdo, inicialização e atualização desse plugin. Depois, também encerra o sistema de execução partilhado da cópia carregada. Não se limita a remover uma entrada de registo. Chame-o para a sua própria biblioteca incorporada durante o encerramento do plugin. Nunca encerre a biblioteca de outro plugin para reiniciar a integração.
Chame createInstance em onLoad para registar o proprietário do arquivo de configurações do plugin antes de outro plugin poder importar conteúdo para ele. O arquivamento usa a implementação incorporada no plugin de destino; não interprete as regras de retirada de configurações desse plugin com a sua cópia do MagmaCore.
Para um arranque por fases, startInitialization aceita trabalho assíncrono, trabalho síncrono e callbacks de sucesso e de falha. Arquiva os ficheiros de configuração que correspondam a formatos retirados antes de executar a inicialização assíncrona. Mantenha as operações sobre mundos e entidades Bukkit na fase síncrona. Trabalho assíncrono demorado deve consultar isShutdownRequested(plugin) entre fases. getInitializationState e isPluginReady expõem o estado do gestor de inicialização.
Atualizações do plugin sem reinício
NightbreakPluginBootstrap.registerStandardCommands regista applypluginupdate juntamente com os outros subcomandos partilhados. Este instala uma atualização transferida desativando o plugin, substituindo o seu jar e voltando a ativá-lo na mesma sessão do servidor, pelo que onDisable tem de cancelar tarefas, remover o registo dos listeners e libertar todas as referências que manteriam vivo o classloader antigo. Os plugins ativos cuja classe principal esteja em com.magmaguy. e que dependam do seu, diretamente ou por soft-depend, são recarregados com ele. Qualquer outro plugin que dependa do seu faz com que a substituição seja recusada e peça um reinício. Consulte Aplicar atualizações sem reiniciar para a perspetiva do dono do servidor.
Se parte do plugin não puder ser recarregada no local, chame NightbreakPluginHotSwap.requireRestartForUpdates(plugin, reason) antes de as verificações de atualização começarem e passe false como segundo argumento de NightbreakPluginUpdater.setAutoDownloadConfigDefault, para que config.yml não ofereça applyPluginUpdatesWithoutRestart. O plugin continua a ser recarregado com o jar atual quando um plugin de que depende é substituído. NightbreakPluginUpdater.onPluginUpdateDownloaded(plugin, listener) executa um listener na thread de transferência depois de uma atualização validada chegar à pasta update.
NMS e entidades por pacotes
Inicialize NMS apenas se o plugin precisar dele, usando NMSManager.initializeAdapter(plugin) de com.magmaguy.easyminecraftgoals. Verifique NMSManager.isEnabled() antes de usar comportamento dependente do adaptador. A inicialização pode falhar ou encontrar uma versão de servidor não suportada.
A distribuição inclui estas famílias de adaptadores:
| Adaptador | Versões de Minecraft |
|---|---|
v1_21_R3 | 1.21.4 |
v1_21_R4 | 1.21.5 |
v1_21_R5 | 1.21.6, 1.21.7, 1.21.8 |
v1_21_R6 | 1.21.9, 1.21.10 |
v1_21_R7_spigot, v1_21_R7_paper | 1.21.11, com implementações separadas para Spigot e Paper |
v26 | 26.1 e a família atual de adaptadores 26.x |
A seleção de um adaptador não garante compatibilidade com todas as versões futuras do servidor. O seletor de execução em NMSManager determina se o servidor instalado pode carregar um adaptador. Versões anteriores à 1.21.4 estão fora do conjunto atual.
O EasyMinecraftGoals gere as entidades que existem apenas através de pacotes, a sua visibilidade, o encaminhamento das interações e os utilitários de movimento e procura de caminhos. Estas não são entidades normais do mundo. Gira-as através da API responsável e limpe os objetos criados pelo seu plugin enquanto o adaptador ainda estiver disponível.
Consultas de localização e proteção
com.magmaguy.magmacore.location.LocationQueryRegistry disponibiliza consultas sobre masmorras e proteção de regiões, incluindo isInAnyDungeon, isInAnyProtectedRegion e canBuild.
Registe fornecedores personalizados com registerDungeonLocator ou registerProtectionProvider e remova o mesmo fornecedor quando o proprietário for desativado. O registo inclui adaptadores para plugins existentes e descobre fornecedores de masmorras entre plugins sem exigir que todos partilhem um classloader do MagmaCore.
Escolha a consulta correspondente à ação. Estar fora de uma masmorra não equivale a ter permissão para construir nesse local. Execute as consultas que acedem ao Bukkit ou a plugins de proteção na thread do servidor.
Partidas
O ciclo de vida das partidas encontra-se em com.magmaguy.magmacore.match. Chame MatchCore.enable(plugin) uma vez durante a ativação, depois estenda Match, passe ao seu construtor um MatchSettings obtido de MatchSettings.builder() e chame open() quando a subclasse terminar a construção. A lógica de jogo fica nos hooks protegidos, como onJoin, onStart, onDeath e onLeave. MagmaCore.shutdown(plugin) destrói as partidas restantes do plugin.
O núcleo não emite eventos Bukkit próprios. Chama a MatchApi definida nas definições, pelo que é o seu plugin que decide que eventos expor. Uma callback cancelável veta o passo devolvendo false ou lançando uma exceção. A cópia de cada plugin só acompanha as suas próprias partidas; um marcador de metadados do jogador, magmacore_match, indica às outras cópias que o jogador já está numa partida.
MatchSettings.builder().permission(...) define a permissão de que um jogador precisa para entrar. Substitua hasJoinPermission(player) para decidir jogador a jogador, por exemplo para deixar entrar sem ela os membros da equipa do servidor. Um participante que sai por ter morrido (LeaveReason.DIED) recupera a vida toda antes de ser retirado, para que um bónus de vida máxima removido na saída mantenha a proporção completa. As outras saídas durante a partida mantêm o dano, e os jogadores ainda na partida quando esta termina recuperam a vida. Os dois comportamentos são mais recentes do que a build publicada a 5 de outubro de 2026.
As classes de partidas antigas em com.magmaguy.magmacore.instance, incluindo MatchInstance, foram removidas. InstanceProtector permanece nesse pacote e é registado por MagmaCore.enableWorldProtections(plugin).
Hosts Lua Mind
O MagmaCore compila programas Mind escritos em Lua para os plugins anfitriões. O formato dos scripts está descrito em Programas de comportamento. Um anfitrião cria o seu próprio LuaMindModuleRegistry, abre um proprietário para o seu espaço de nomes com openOwner(namespace), regista módulos com o registerModule do proprietário e obtém um LuaMindDefinition a partir do validateProgram do proprietário. Cada chamada a instantiate na definição constrói um programa novo, com o seu próprio ambiente Lua, para uma entidade. Os hooks abaixo são mais recentes do que a compilação publicada a 5 de outubro de 2026.
- Inspecionar um módulo.
LuaMindModuleRegistry.inspectModule(sourceName, source)lê o ID, a revisão, as dependências e as predefinições desettingsde um módulo sem o registar.LuaMindModuleDescriptor.settings()contém valoresDouble,Boolean,StringouList<String>. O MagmaCore não entrega as definições aos scripts. Um anfitrião que queira valores por criatura combina os seus sobre estas predefinições e expõe-nos, como as mascotes do FreeMinecraftModels fazem comc.settings. - Estender os contextos dos callbacks.
LuaMindDefinition.instantiate(LuaMindContextExtension)acrescenta os seus campos à tabela de contexto de cada callback.extend(table, context, contribution)recebe a tabela antes de o Lua a ver, oMindContextdo callback e o ID do módulo que declarou o callback, ou o ID do próprio programa. É executado na thread do servidor, dentro do orçamento de execução do callback, pelo que o seu tempo de CPU conta para ocpu_microsdo programa e uma exceção faz o callback falhar. Acrescente campos comrawset, ou comLuaTableSupport.lazyField, que mantém o__indexexistente da tabela para todas as outras chaves. Não substitua a metatabela da tabela nem o seu__index, porque as secções incorporadas são lidas através deles, e não substituatick,generation,entity,memory,perception,actuatornemactions. Ler uma secção incorporada a partir deextendconstrói-a para esse callback. Passe uma extensão separada a cada chamada ainstantiatequando ela guarda estado por entidade. - Intervalo de verificação. Um comportamento Java pode substituir
MindBehavior.probeInterval(), o equivalente doprobe_intervaldo Lua, para chamarcanStarta cada N ticks enquanto está parado. Tem de ir de 1 aMindBehavior.MAX_PROBE_INTERVAL(200); oMindProgramrecusa outros valores. A predefinição 1 pergunta a cada tick. UmMindSensordeteta no primeiro tick em que o seu corpo é processado e depois a cadaintervalTicks()ticks, numa fase própria de cada entidade. - Voo.
MindActuator.steerFlight(Vector), que já estava nessa compilação, faz voar um corpoFLYINGpor essa velocidade durante um tick e precisa das reservas MOVE e LOOK. São novos o seu limite e osteer_flightdo Lua:MindActuator.MAX_FLIGHT_SPEEDé 4 blocos por tick, e uma velocidade superior é reduzida a esse valor.RouteFlighttambém limita aí a sua velocidade, pelo que uma rota definida acima de 80 blocos por segundo voa a 80.
Compilar um plugin após alterações à biblioteca
Use JDK 21 e publique o MagmaCore no Maven Local com ./gradlew publishToMavenLocal, ou .\gradlew.bat publishToMavenLocal no Windows. Confirme que o plugin que usa a biblioteca resolve esse repositório e a versão pretendida, e volte a compilar o seu JAR com shading. Substituir uma biblioteca no Maven Local não atualiza um plugin já compilado.
Consulte o índice para programadores para APIs de plugins instalados. Essas integrações usam normalmente provided ou compileOnly. O MagmaCore segue o contrato de uma biblioteca incorporada.