[Minecraft/Java] Resumão de spigot

O que é o spigot ??

O spigot consiste em uma modificação de minecraft feita apenas do lado do servidor, ou seja, ele é responsável por adicionar conteúdos customizados aos servidores de minecraft e ainda por cima não exige que o usuário instale programas adicionais, pois como dito antes a modificação é feita apenas do lado do servidor.

Forge, Spigot, Bukkit... tantos nomes...

O Spigot é uma evolução de um sistema antigo, porém com uma história muito consolidada, chamado "Bukkit", que basicamente tinha a mesma função de spigot.

O Spigot também possui outros "filhos", como paperspigot, purpur e entre outros, porém eu recomendo a aprender principalmente o spigot, pois ele é mais consolidado entre a comunidade de plugins.

O Forge é uma modificação feita do lado tanto do cliente, quanto do servidor, ele é muito mais poderoso, pois é capaz de criar mods com diversos conteúdos como itens e dimensões. porém o usuário precisará baixar os mesmos mods para entrar no servidor, pois ele modifica também o client, porém não abordarei o forge neste tópico.

Porque aprender spigot

A comunidade de plugins e servidores de minecraft é uma comunidade bem ativa, com vários fóruns onde você pode tirar dúvidas, (como por exemplo Este) e também existem vários donos de servidor dispostos a pagar por um plugin customizado. Também é possível gerar renda passiva através de um site onde você possa vender seus plugins onde donos de servidor posssam comprar, ou talvez você possa criar um servidor e vender VIPs (cargo especial dentro de um servidor).

Como começar

Existem vários tutoriais bons e em português no youtube sobre bukkit/spigot e até cursos na udemy, mas uma boa forma, é ler a Documentação e a JavaDoc. Mas eu darei um bom resumo pra vocês neste tópico

Main

Para criar a classe main no spigot você precisa importar o spigot usando gradle,maven ou até a jar e criar uma classe que herda de JavaPlugin e Sobrescrever os métodos OnEnable() e OnDisable() AutoExplicativo

public class TestPlugin extends JavaPlugin{
	@Override
	public void onEnable() {}
}

A parte do código por incrível que pareça é só isso, mas precisa de um documento chamado plugin.yml, você precisa cria-lo dentro da pasta do projeto, este é o arquivo que o servidor do spigot precisa para "enchergar" seu plugin

name: PluginTest
version: 1.0
main: br.com.pemei.testplugin.TestPlugin #Nome completo da classe main
author: [PeMei]
description: Test

Comando

Pronto agora você criou seu primeiro plugin, mas infelizmente ele não ainda não faz nada, vamos adicionar um comando que cure o jogador, mas vamos ter um pouco de organização e escreve-lo em outra classe, crie uma classe nova e implemente a interface CommandExecutor, o classe ficará assim:

package br.com.pemei.testplugin.commands;
//imports ocultados

public class ComandoCurar implements CommandExecutor{

	@Override
	public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) {
		// TODO Auto-generated method stub
		return false;
	}
	
}

O método tem quatro parâmetros, mas vamos focar em 2, o sender é uma referência a entidade que executou o comando e o args são uma lista de parâmetros passados na hora de executar o comando, agora vamos brincar um pouco com eles. Primeiro tenho que verificar se quem executou o comando foi um player ou um console, depois dar um cast e finalmente setar a vida do player para 20

@Override
public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) {
    //verificando se tem é admin
    if(!sender.isOp())
        return false;   
    //verificando se é um player
    if(!(sender instanceof Player))
        return false;     
    //cast
    Player player = (Player) sender;
    //setar vida
    player.setHealth(20);
    //mandar mensagem
    player.sendMessage(ChatColor.GREEN + "Você foi curado");
    return true;
}
}

Ainda não estou satisfeito, eu quero brincar um pouco mais com argumentos. Agora quero que dê para um admin curar outro player. Se ele der /curar PeMei vai curar outro player e se ele der /curar vai curar ele mesmo.

@Override
public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) {
        //verificando se é um player
    if(!(sender instanceof Player)){
        sender.sendMessage("Você não é um player");
        return false;
    }
    //verificando se tem é admin
    if(!sender.isOp()){
        sender.sendMessage(ChatColor.RED + "Você não é admin!");
        return false;
    }
    if(args.length > 1) {
        sender.sendMessage(ChatColor.RED + "Argumentos inválidos");
        return false;
    }
    //cast
    Player player = (Player) sender;
    //se não tiver parâmentro, vai curar ele mesmo
    if(args.length == 0) {
            //setar vida
            player.setHealth(20);
            //mandar mensagem
            player.sendMessage(ChatColor.GREEN + "Você foi curado");
            return true;
    }else{
        //procurar player
        Player targetPlayer = Bukkit.getPlayer(args[0]); //spigot é uma fork do bukkit, então tem esse método
        //verificando se player é nulo
        if(targetPlayer == null) {
                player.sendMessage(ChatColor.RED + "Este player não existe ou está offline");
                return false;
        }
        //curar player e mandar mensagem para ambos
        targetPlayer.setHealth(20);
        targetPlayer.sendMessage(ChatColor.GREEN + "Você foi curado por " + ChatColor.GOLD + player.getDisplayName());
        player.sendMessage(ChatColor.GREEN + "Você curou o player com sucesso");

    }
    return true;
}

Agora com o comando feito, é preciso registrar-lo no plugin.yml para o servidor spigot poder enchergar esse comando

commands:
  curar:
    aliases: [heal,cura] #aliases é uma lista de 'apelidos' pro comando
    description: Cura

O comando está registrado, mas por enquanto ele não faz nada pois ele não está linkado com a classe, para linkar você precisa fazer esse comando no OnEnable():

@Override
public void onEnable() {
        this.getCommand("curar").setExecutor(new ComandoCurar());
}

Pronto agora o comando está linkado com com a classe

Eventos

Os eventos são certas "ocorrências" que ocorrem no servidor, por exemplo, quando o player quebra um bloco ele dispara um evento de quebrar bloco para todos os plugins dentro do servidor usando por debaixo dos panos o padrão GoF Chain of Responsability (Handler)

Neste exemplo nós vamos bloquear o PvP neste servidor usando apenas eventos

Para colocar seu ouvido num evento, primeiro vamos criar uma classe com a interface listener (cuidado com imports), esse é uma interface vazia e sem métodos, mas que é necessário colocar para que o spigo compreenda que é um classe de escuta

public class Escuta implements Listener{}

Agora vamos adicionar um método void com um objeto event de parâmentro para que ele seja executado toda vez que "ouvir" o evento, o parêmetro é importante para definir qual vai ser o evento

public void onEscutar(EntityDamageByEntityEvent e) {}

Agora vamos adicionar a lógica ao evento, primeiro vamos verificar se são dois player e se for, vamos anular o evento

public void onEscutar(EntityDamageByEntityEvent e) {
        //verifica se são dois players
        if(e.getEntity() instanceof Player && e.getDamager() instanceof Player) {
                //anula o evento
                e.setCancelled(true);
        }
}

Mas para a classe poder reconhecer o evento, precisa adiconar a anotação @EventHandler no método, mas antes de darmos uma olhada a fundo nessa anotação, temos que lembrar que esse evento vai passar por todos os plugins do servidor, incluindo o seu e qualquer outro plugin feito por terceiros

A anotação tem duas propriedades, a priority, que basicamente é a prioridade e a importância do evento e ignoreCancelled que define se seu evento vai ser ignorado ou não se ele foi previamente cancelado por outro plugin @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

ATENÇÃO: Não alterar ou cancelar eventos na prioridade monitor

Agora com o evento feito devemos registrar a classe de escuta

@Override
public void onEnable() {
        this.getCommand("curar").setExecutor(new ComandoCurar());
        Bukkit.getPluginManager().registerEvents(new Escuta(), this);
}

Testando o plugin

Você deve primeiro criar um servidor spigot, primeiro você deve seguir as instruções para compilar o jar do servidor. Depois você deve pegar o jar e colocar em uma pasta separada e renome-lo para "Server.jar" para facilitar, depois disso você deve criar um arquivo de texto com o seguinte código e salvar como start.bat

@echo off
java -Xms2G -Xmx2G -XX:+UseG1GC -jar Server.jar nogui
pause

Na primeira vez que executar ele vai instalar o servidor automagicamente naquela pasta, depois ele vai dar um "erro" falando que precisa de um tal de EULA, para proseguir é simples, vai no arquivo eula.txt que gerou e troca de false para true e execute denovo. Agora como eu acredito que você muito provavelmente não tenha duas contas originais para testar seu plugin, você precisa habilitar para minecraft pirata. isso é muito fácil Você deve editar o arquivo server.properties e deve alterar online-mode=true para online-mode=false e pronto, ainda se você quiser você pode alterar o server-ip= e colocar seu ipv4 do hamachi ou radmin para compartilhar o servidor. Para colocar Plugins no servidor é facil, primeiro você precisa exportar seu plugin em .jar e simplesmento coloca-lo na pasta plugins/ que gerou e depois fechar e abrir o servidor dando stop

Conclusão

Escrever este tópico me deu muito trabalho, mas escrevi mesmo assim pois eu quero facilitar a jornada para muito iniciantes que estão aprendendo o spigot. Pois quando eu era iniciante tudo que eu queria era um tópico como este para me guiar nessa imensa comunidade de plugins e servidores. Se este tópico ajudou você nesta jornada, peço que contribua este post com tabcoins.

E se você que é mais experiente e puder melhorar este código (pois fiz as pressas para este tópico) ou dar dicas de programação de plugins em java, encorajo muito você a contribuir com comentários agregando este tópico para que possa compartilhar seu conhecimento com todos aqui

Otimo conteudo!!! Mas não faz muita diferença sobre qual aprender, paper, spigot... todos são do spigot, porém o mais utilizado na criação de servidores é o Paper, pois possui um desempenho muito superior, já os forks do paper, prometem ainda mais desempenho

eu já fui um desenvolvedor de plugins de Minecraft, foi por onde comecei a jornada na programação, muito obrigado!