Plugin de espita: forma genérica de la clase principal del plugin -- java campo con minecraft camp codereview Relacionados El problema

Spigot Plugin: Generic form of the plugin's main class


4
vote

problema

Español

He creado muchos complementos de espiga en mi "carrera" como desarrollador para un montón de servidores Minecraft, pero cada vez que empiezo a escribir un nuevo plugin, básicamente me "reinventé" la estructura de mi clase principal de complemento, siempre Así que se ajusta mejor a lo que considero un complemento legible, que también otros desarrolladores que trabajarán con estos complementos después de mí pueden hacerlo sin tener un dolor de cabeza.

Mi clase principal más reciente parece esto:

  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();         }      }  }   

Sería genial obtener una idea fresca de lo que se puede mejorar, tal vez no solo con respecto a las cosas relacionadas con la espiga, sino también tal vez algunos malos hábitos generales que pueda tener. ¡Muchas gracias por adelantado! Si tiene alguna pregunta a alguna funcionalidad de las clases, no dude en preguntarme al respecto en los comentarios :)

Original en ingles

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 :)

     

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Su formato está parcialmente desactivado, use un formato de código.


  public class Main extends JavaPlugin {   

Ya no estoy familiarizado con las convenciones de nombramiento de Bukkit, pero es más probable que se llame más SpigotPlugin . Main está un poco reservado para las principales clases que son el punto de entrada principal para aplicaciones.


¿Necesita el mecánico de la instancia estática? Si puedes, debes evitarlo.


  public static HashMap<Player, Long> lastUseOfCommand = new HashMap<Player, Long>();   

Esto parece nunca ser usado.

Además, dado que es un mapa estático, es probable que uno pueda ocurrir una mejor API cuando sea necesario. Por ejemplo, entregando la instancia actual a los oyentes creados.


  System.out.println(MessageManager.disabledPluginConsoleMessage());   

Si recuerdo bien, Bukkit deporte una solución de registro, debe usar eso.


  this.getCommand("clan").setExecutor(new ClanCommand());   

Usted es inconsistente con respecto a su this uso.


  PlayerConnectListener.joinTimes.put(player, System.currentTimeMillis());   

No estoy seguro de si eso es parte de su código, pero tenga en cuenta que currentTimeMillis es el tiempo de la pared. Eso significa que observa los segundos de salto, los cambios en la zona horaria y similares. Así que dada la siguiente configuración:

  long start = System.currentTimeMillis();  // Let 5 seconds pass.  long elapsed = System.currentTimeMillis() - start;   

SpigotPlugin0 puede ser cualquier valor, de lo más probable "5000" a "500000" o incluso "-25000".


  SpigotPlugin1  

¿Cuáles son estas construcciones? No soy amigo de "Cuerdas vacías", si puede, ser explícito al respecto, por ejemplo, con SpigotPlugin2 , o use 99887776655443313 o similar:

  SpigotPlugin4  

  SpigotPlugin5  

No hay realmente un punto en observar esto solo para construir la cadena de manera diferente, solo Alw3ays use la ruta más.


  SpigotPlugin6  

Como se dijo anteriormente, desea registrar errores correctamente.

  SpigotPlugin7  

mismo aquí.

 

Your formatting is partly off, use a code-formatter.


public class Main extends JavaPlugin { 

I'm not familiar anymore with the Bukkit naming convetions, but this should most likely be called SpigotPlugin. Main is kinda reserved for main classes which are the main entry point for applications.


Do you require the static instance mechanic? If you can, you should avoid it.


public static HashMap<Player, Long> lastUseOfCommand = new HashMap<Player, Long>(); 

This seems to be never used.

Also, given that is a static map, one can most likely come up with a better API when required. For example, handing the current instance to the created listeners.


System.out.println(MessageManager.disabledPluginConsoleMessage()); 

If I remember right, Bukkit does sport a logging solution, you should use that.


this.getCommand("clan").setExecutor(new ClanCommand()); 

You're inconsistent regarding your this usage.


PlayerConnectListener.joinTimes.put(player, System.currentTimeMillis()); 

I'm not sure if that is part of your code, but be aware that currentTimeMillis is wall-clock time. That means it observes leap-seconds, time zone changes and the like. So given the following setup:

long start = System.currentTimeMillis();  // Let 5 seconds pass.  long elapsed = System.currentTimeMillis() - start; 

elapsed can be any value, from most likely "5000" to "500000" or even "-25000".


board.getTeam("onlineplayers").setPrefix(" " + "0" + "/" + "" + Bukkit.getServer().getMaxPlayers()); // ... board.getTeam("onlineplayers")                     .setPrefix("" + Bukkit.getOnlinePlayers().size() + "/" + Bukkit.getServer().getMaxPlayers()); 

What are these constructs? I'm not a friend of "empty string casts", if you can, be explicit about it, for example with Integer.toString(), or use String.format() or similar:

board.getTeam("onlineplayers").setPrefix(String.format("0/%i",     Bukkit.getServer().getMaxPlayers())); // ... board.getTeam("onlineplayers").setPrefix(String.format("%i/%i",     Integer.valueOf(Bukkit.getOnlinePlayers().size()),     Integer.valueOf(Bukkit.getServer().getMaxPlayers())); 

if (Bukkit.getOnlinePlayers().size() == 0) { 

There's not really a point in observing this just to build the string differently, just alw3ays use the else path.


        try {             board.getTeam("Kontostandcheck")                     .setPrefix("" + Economy.getMoneyExact(player.getName()).setScale(2, RoundingMode.DOWN) + "$");         } catch (IllegalStateException | IllegalArgumentException | UserDoesNotExistException e) {             e.printStackTrace();         } 

As said previously, you want to log errors properly.

        } catch (Exception e) {             System.out.println("[ClanSystem] This is not the live environement or the scoreboard configuration has changed. Please review carefully.");             e.printStackTrace();         } 

Same here.

 
 

Relacionados problema

3  Esquema de base de datos para un complemento de registro Minecraft  ( Database schema for a minecraft logging plugin ) 
Este es mi intento de crear un esquema de base de datos para un complemento de registro Minecraft. No estoy de ninguna manera un experto en SQL, por lo que la...

7  Constructor - un clon de 2D Minecraft  ( Builder a 2d minecraft clone ) 
Me estaba asomando en mi PI de la frambuesa que no había encendido o usado en un tiempo, y me topé con este script de Python que escribí hace ~ 1.5 años, y me...

3  Algoritmo de malla para generar caras en Minecraft  ( Meshing algorithm for generating faces in minecraft ) 
Para generar caras de un mundo similar al Minecraft desde una matriz tridimensional, desarrollé el siguiente algoritmo de malla. Las caras tienen vértices e í...

4  Plugin Vanisher para Minecraft (escrito con la API de Bukkit)  ( Vanisher plugin for minecraft written with the bukkit api ) 
¿Este código para mi complemento VAISHER para el juego Minecraft, escrito con la API de Bukkit, será optimizada y convencionalmente correcta? vaishapi: ...

3  Utilidad Minecraft Auto-Backup  ( Minecraft auto backup utility ) 
Vivo en un país donde ocurre un apagón de electricidad después de cada hora, lo que corrompe los archivos de guardado de Minecraft, así que se me ocurrió con ...

2  Aplicación Personal Minecraft Android  ( Personal minecraft android app ) 
Esto no será liberado públicamente, pero eso no significa que quiera tener hábitos de codificación de malos. No estaba demasiado lejos en esto antes de darme ...

1  Documentación para un complemento de servidor Minecraft  ( Documentation for a minecraft server plugin ) 
Estoy trabajando en un complemento Minecraft para mi Spigot Minecraft Server. Tengo una clase que funciona como se esperaba. He hecho mi mejor esfuerzo pa...

2  SafeBlockPopulator para garantizar que los trozos vecinos se generen antes de la población  ( Safeblockpopulator to ensure neighboring chunks are generated before population ) 
Bukkit / CraftBukkit / Spigot son extensores de servidor Minecraft que permiten crear y usar complementos. Un tipo particular de plugin es un generador, que c...

2  Plugin para encontrar bloques colocados y si están en cierta secuencia  ( Plugin for finding placed blocks and if they are in a certain sequence ) 
Esto es para un complemento que estoy haciendo para el juego llamado Minecraft. El Código es responsable de descubrir los bloques colocados por el jugador y, ...

4  Video Frame to Minecraft Map Colors  ( Video frame to minecraft map colors ) 
Todavía soy algo nuevo en C, así que perdóname por cualquier error tonto que he hecho. Estoy tratando de convertir los marcos de video en los colores del ma...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos