I have created a lot of spigot plugins in my "career" as a developer for a bunch of Minecraft servers, but every time I start writing a new plugin, I basically "reinvent" the structure of my main plugin class, always so it fits best into what I consider to be a readable plugin, that also other developers that will work with these plugins after me can do so without getting a headache.
My most recent Main-Class looks like this:
package com.clanplugin;
import java.math.RoundingMode;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scoreboard.Scoreboard;
import com.earth2me.essentials.api.UserDoesNotExistException;
import com.clanplugin.commands.ClanCommand;
import com.clanplugin.commands.CommandRegistry;
import com.clanplugin.commands.implementation.AcceptCommand;
import com.clanplugin.commands.implementation.CreateCommand;
import com.clanplugin.commands.implementation.DeleteCommand;
import com.clanplugin.commands.implementation.DerankCommand;
import com.clanplugin.commands.implementation.InfoCommand;
import com.clanplugin.commands.implementation.InviteCommand;
import com.clanplugin.commands.implementation.InvitesCommand;
import com.clanplugin.commands.implementation.KickCommand;
import com.clanplugin.commands.implementation.LeaveCommand;
import com.clanplugin.commands.implementation.ListCommand;
import com.clanplugin.commands.implementation.MoneyCommand;
import com.clanplugin.commands.implementation.UprankCommand;
import com.clanplugin.commands.implementation.RejectCommand;
import com.clanplugin.commands.implementation.RevokeCommand;
import com.clanplugin.commands.implementation.SetCbCommand;
import com.clanplugin.commands.implementation.SetLeaderCommand;
import com.clanplugin.commands.implementation.SetNameCommand;
import com.clanplugin.commands.implementation.SetTagCommand;
import com.clanplugin.commands.implementation.ShowMaxClanMemberCommand;
import com.clanplugin.commands.implementation.ToggleMoneyCommand;
import com.clanplugin.commands.implementation.ToplistCommand;
import com.clanplugin.database.DatabaseConnector;
import com.clanplugin.database.DatabaseMethods;
import com.clanplugin.listener.PlayerConnectListener;
import com.clanplugin.listener.PlayerDisconnectListener;
import com.clanplugin.listener.TagSetterListener;
import com.clanplugin..manager.ClantagCache;
import com.clanplugin..manager.MessageManager;
import net.ess3.api.Economy;
public class Main extends JavaPlugin {
private static CommandRegistry commandRegistry;
private static Main plugin;
public static HashMap<Player, Long> lastUseOfCommand = new HashMap<Player, Long>();
public void onEnable() {
plugin = this;
saveDefaultConfig();
registerCommands();
registerListeners();
loadDatabase();
setDataUponReload();
}
public void onDisable() {
DatabaseConnector.disconnect();
System.out.println(MessageManager.disabledPluginConsoleMessage());
plugin = null;
}
public static Main getInstance() {
return plugin;
}
private void loadDatabase() {
DatabaseConnector.connect();
DatabaseMethods.initialiseDatabaseTables();
}
private void registerCommands() {
this.getCommand("clan").setExecutor(new ClanCommand());
commandRegistry = new CommandRegistry();
commandRegistry.registerCommand(new ShowMaxClanMemberCommand());
commandRegistry.registerCommand(new ListCommand());
commandRegistry.registerCommand(new LeaveCommand());
commandRegistry.registerCommand(new DeleteCommand());
commandRegistry.registerCommand(new InvitesCommand());
commandRegistry.registerCommand(new ToplistCommand());
commandRegistry.registerCommand(new MoneyCommand());
commandRegistry.registerCommand(new ToggleMoneyCommand());
commandRegistry.registerCommand(new InviteCommand());
commandRegistry.registerCommand(new AcceptCommand());
commandRegistry.registerCommand(new RejectCommand());
commandRegistry.registerCommand(new KickCommand());
commandRegistry.registerCommand(new RevokeCommand());
commandRegistry.registerCommand(new InfoCommand());
commandRegistry.registerCommand(new SetTagCommand());
commandRegistry.registerCommand(new SetNameCommand());
commandRegistry.registerCommand(new SetLeaderCommand());
commandRegistry.registerCommand(new UprankCommand());
commandRegistry.registerCommand(new DerankCommand());
commandRegistry.registerCommand(new SetCbCommand());
commandRegistry.registerCommand(new CreateCommand());
}
public static CommandRegistry getCommandRegistry() {
return commandRegistry;
}
private void registerListeners() {
getServer().getPluginManager().registerEvents(new PlayerConnectListener(), this);
getServer().getPluginManager().registerEvents(new PlayerDisconnectListener(), this);
getServer().getPluginManager().registerEvents(new TagSetterListener(), this);
}
private void setDataUponReload() {
for(Player player : Bukkit.getOnlinePlayers()) {
if (DatabaseMethods.isPlayerInClan(player.getUniqueId())) {
String playerUUID = DatabaseMethods.getPlayerUUID(player.getUniqueId());
if (playerUUID.equals(player.getUniqueId().toString()))
DatabaseMethods.addPlayerName(player.getName(), player.getUniqueId());
ClantagCache.put(player, DatabaseMethods.getClanTagByClanID(DatabaseMethods.getClanIDByPlayerUuid(player.getUniqueId())));
}
PlayerConnectListener.joinTimes.put(player, System.currentTimeMillis());
}
}
@SuppressWarnings("deprecation")
public static void updateScoreBoard(Player player) {
try {
if (player == null || player.getScoreboard() == null) {
return;
}
Scoreboard board = player.getScoreboard();
if (Bukkit.getOnlinePlayers().size() == 0) {
board.getTeam("onlineplayers").setPrefix(" " + "0" + "/" + "" + Bukkit.getServer().getMaxPlayers());
} else {
board.getTeam("onlineplayers")
.setPrefix("" + Bukkit.getOnlinePlayers().size() + "/" + Bukkit.getServer().getMaxPlayers());
}
try {
board.getTeam("Kontostandcheck")
.setPrefix("" + Economy.getMoneyExact(player.getName()).setScale(2, RoundingMode.DOWN) + "$");
} catch (IllegalStateException | IllegalArgumentException | UserDoesNotExistException e) {
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("[ClanSystem] This is not the live environement or the scoreboard configuration has changed. Please review carefully.");
e.printStackTrace();
}
}
}
It would be great to get some fresh idea's what can be improved, maybe not only regarding the spigot-related stuff, but also maybe some general bad habits I might have. Thanks a lot in advance! If you have any questions to some functionality of the classes feel free to ask me about it in the comments :)