diff --git a/pom.xml b/pom.xml index 80cd5f3..759f3ad 100644 --- a/pom.xml +++ b/pom.xml @@ -41,12 +41,6 @@ 6.0.54 provided - - org.projectlombok - lombok - 1.18.32 - provided - com.lishid openinvplugin diff --git a/src/main/java/de/minebench/syncinv/MapData.java b/src/main/java/de/minebench/syncinv/MapData.java index 7e0723f..f01ce0a 100644 --- a/src/main/java/de/minebench/syncinv/MapData.java +++ b/src/main/java/de/minebench/syncinv/MapData.java @@ -18,14 +18,14 @@ * along with this program. If not, see . */ -import lombok.Data; import org.bukkit.map.MapView; +import java.io.Serial; import java.io.Serializable; import java.util.UUID; -@Data public class MapData implements Serializable { + @Serial private static final long serialVersionUID = 4376356835175363489L; private final int id; private final UUID worldId; @@ -36,4 +36,97 @@ public class MapData implements Serializable { private boolean locked; private boolean trackingPosition; private boolean unlimitedTracking; + + public MapData(int id, UUID worldId, int centerX, int centerZ, MapView.Scale scale, byte[] colors) { + this.id = id; + this.worldId = worldId; + this.centerX = centerX; + this.centerZ = centerZ; + this.scale = scale; + this.colors = colors; + } + + /** + * @return The id of the map + */ + public int getId() { + return id; + } + + /** + * @return the unique id of the world the map is in + */ + public UUID getWorldId() { + return worldId; + } + + /** + * @return the x coordinate of the center of the map + */ + public int getCenterX() { + return centerX; + } + + /** + * @return the z coordinate of the center of the map + */ + public int getCenterZ() { + return centerZ; + } + + /** + * @return the scale of the map + */ + public MapView.Scale getScale() { + return scale; + } + + /** + * @return the colors of the map + */ + public byte[] getColors() { + return colors; + } + + /** + * @return if the map is locked + */ + public boolean isLocked() { + return locked; + } + + /** + * @param locked if the map should be locked + */ + public void setLocked(boolean locked) { + this.locked = locked; + } + + /** + * @return if the map should track position + */ + public boolean isTrackingPosition() { + return trackingPosition; + } + + /** + * @param trackingPosition if the map should track position + */ + public void setTrackingPosition(boolean trackingPosition) { + this.trackingPosition = trackingPosition; + } + + /** + * @return Whether the map will show a smaller position cursor (true), or no position cursor (false) when cursor is outside of map's range. + */ + public boolean isUnlimitedTracking() { + return unlimitedTracking; + } + + /** + * @param unlimitedTracking Whether the map will show a smaller position cursor (true), or no position cursor (false) when cursor is outside of map's range. + */ + public void setUnlimitedTracking(boolean unlimitedTracking) { + this.unlimitedTracking = unlimitedTracking; + } } diff --git a/src/main/java/de/minebench/syncinv/PlayerData.java b/src/main/java/de/minebench/syncinv/PlayerData.java index 87fc85d..2dad6ad 100644 --- a/src/main/java/de/minebench/syncinv/PlayerData.java +++ b/src/main/java/de/minebench/syncinv/PlayerData.java @@ -20,9 +20,6 @@ import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.Statistic; @@ -35,6 +32,7 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.util.Vector; +import java.io.Serial; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; @@ -43,10 +41,8 @@ import java.util.Set; import java.util.UUID; -@ToString -@Getter -@Setter public class PlayerData implements Serializable { + @Serial private static final long serialVersionUID = -5703536933548893803L; private final long timeStamp = System.currentTimeMillis(); private final int dataVersion; @@ -75,10 +71,10 @@ public class PlayerData implements Serializable { private final float fallDistance; private final Vector velocity; private final int heldItemSlot; - private byte[] persistentData = null; private final Map> advancementProgress = new HashMap<>(); private final Table statistics = HashBasedTable.create(); private final long lastSeen; + private byte[] persistentData = null; PlayerData(Player player, long lastSeen) { this.dataVersion = player.getServer().getUnsafe().getDataVersion(); @@ -109,14 +105,6 @@ public class PlayerData implements Serializable { this.lastSeen = lastSeen; } - public ItemStack[] getInventoryContents() { - return deserializeItems(inventory); - } - - public ItemStack[] getEnderchestContents() { - return deserializeItems(enderchest); - } - private static byte[][] serializeItems(ItemStack[] items) { byte[][] itemByteArray = new byte[items.length][]; for (int i = 0; i < items.length; i++) { @@ -155,4 +143,243 @@ private static ItemStack[] deserializeItems(byte[][] items) { } return maps; } + + public ItemStack[] getInventoryContents() { + return deserializeItems(inventory); + } + + public ItemStack[] getEnderchestContents() { + return deserializeItems(enderchest); + } + + /** + * @return The timestamp, when this data was created + */ + public long getTimeStamp() { + return timeStamp; + } + + /** + * @return Data version of this data (server dependent) + */ + public int getDataVersion() { + return dataVersion; + } + + /** + * @return the UUID of the player + */ + public UUID getPlayerId() { + return playerId; + } + + /** + * @return Display name of the player + */ + public String getPlayerName() { + return playerName; + } + + /** + * @return the players current GameMode + */ + public GameMode getGamemode() { + return gamemode; + } + + /** + * @return the players current experience points. + * This refers to the total amount of experience the player has collected over time + * and is not currently displayed to the client. + */ + public int getTotalExperience() { + return totalExperience; + } + + /** + * @return the players current experience level + */ + public int getLevel() { + return level; + } + + /** + * @return the players current experience points towards the next level + * This is a percentage value. 0 is "no progress" and 1 is "next level". + */ + public float getExp() { + return exp; + } + + /** + * @return the players current potion effects + */ + public Collection getPotionEffects() { + return potionEffects; + } + + /** + * @return map data to be rendered and send to the player + */ + public Set getMaps() { + return maps; + } + + /** + * @return the players max health + */ + public double getMaxHealth() { + return maxHealth; + } + + /** + * @return the players current health + */ + public double getHealth() { + return health; + } + + /** + * @return if the client is displayed a 'scaled' health, that is, health on a scale from 0-getHealthScale() + */ + public boolean isHealthScaled() { + return isHealthScaled; + } + + /** + * @return the number to scale health to for the client + * Displayed health follows a simple formula displayedHealth = getHealth() / getMaxHealth() * getHealthScale() + */ + public double getHealthScale() { + return healthScale; + } + + /** + * @return the players current food level + */ + public int getFoodLevel() { + return foodLevel; + } + + /** + * @return the players current saturation level. + * Saturation is a buffer for food level. Your food level will not drop if you are saturated > 0. + */ + public float getSaturation() { + return saturation; + } + + /** + * @return the players current exhaustion level. + * Exhaustion controls how fast the food level drops. + * While you have a certain amount of exhaustion, your saturation will drop to zero, + * and then your food will drop to zero. + */ + public float getExhaustion() { + return exhaustion; + } + + /** + * @return the maximum amount of air the player can have, in ticks. + */ + public int getMaxAir() { + return maxAir; + } + + /** + * @return the amount of air that the player has remaining, in ticks. + */ + public int getRemainingAir() { + return remainingAir; + } + + /** + * @return the amount of ticks before the player stops being on fire + */ + public int getFireTicks() { + return fireTicks; + } + + /** + * @return the maximum duration in which the player will not take damage. + */ + public int getMaxNoDamageTicks() { + return maxNoDamageTicks; + } + + /** + * @return the amount of no damage ticks + */ + public int getNoDamageTicks() { + return noDamageTicks; + } + + /** + * @return The fall distance of the player + */ + public float getFallDistance() { + return fallDistance; + } + + /** + * @return The velocity of the player + */ + public Vector getVelocity() { + return velocity; + } + + /** + * @return Set the slot number of the currently held item. + * This validates whether the slot is between 0 and 8 inclusive. + */ + public int getHeldItemSlot() { + return heldItemSlot; + } + + /** + * @return the advancements of this player + */ + public Map> getAdvancementProgress() { + return advancementProgress; + } + + /** + * @return the statistics of this player + */ + public Table getStatistics() { + return statistics; + } + + /** + * @return when the player was last seen + */ + public long getLastSeen() { + return lastSeen; + } + + /** + * @return the persistentData + */ + public byte[] getPersistentData() { + return persistentData; + } + + /** + * @param persistentData the persistentData to set + */ + public void setPersistentData(byte[] persistentData) { + this.persistentData = persistentData; + } + + /** + * @return a string representation of the object + */ + public String toString() { + return "PlayerData{" + + "playerId=" + playerId + + ", playerName='" + playerName + '\'' + + ", dataVersion=" + dataVersion + + ", timeStamp=" + timeStamp + + '}'; + } } diff --git a/src/main/java/de/minebench/syncinv/SyncInv.java b/src/main/java/de/minebench/syncinv/SyncInv.java index ea87f22..a1174d9 100644 --- a/src/main/java/de/minebench/syncinv/SyncInv.java +++ b/src/main/java/de/minebench/syncinv/SyncInv.java @@ -16,7 +16,6 @@ import de.minebench.syncinv.messenger.PlayerDataQuery; import de.minebench.syncinv.messenger.RedisMessenger; import de.minebench.syncinv.messenger.ServerMessenger; -import lombok.Getter; import org.bukkit.ChatColor; import org.bukkit.GameRule; import org.bukkit.Location; @@ -93,13 +92,11 @@ public final class SyncInv extends JavaPlugin { /** * Reference to the OpenInv plugin to load data for the query option */ - @Getter private OpenInv openInv = null; /** * The messenger for communications between the servers */ - @Getter private ServerMessenger messenger; /** @@ -111,7 +108,7 @@ public final class SyncInv extends JavaPlugin { * Sync data with all servers in a group when a player logs out */ private boolean syncWithGroupOnLogout; - + /** * Store player data even if the player never joined the server */ @@ -120,7 +117,6 @@ public final class SyncInv extends JavaPlugin { /** * The amount of seconds we should wait for a query to stopTimeout */ - @Getter private int queryTimeout; /** @@ -146,21 +142,18 @@ public final class SyncInv extends JavaPlugin { /** * Whether or not the plugin is currently disabling */ - @Getter private boolean disabling = false; /** * Whether or not the plugin is in debugging mode */ - @Getter private boolean debug; /** * The id of the newest map that was seen on this server */ - @Getter private int newestMap = 0; - + // Unknown player storing private Method methodGetOfflinePlayer = null; private Method methodGetHandle = null; @@ -184,7 +177,7 @@ public final class SyncInv extends JavaPlugin { public void onEnable() { // Plugin startup logic loadConfig(); - + playerDataFolder = new File(getServer().getWorlds().get(0).getWorldFolder(), "playerdata"); try { methodGetOfflinePlayer = getServer().getClass().getMethod("getOfflinePlayer", GameProfile.class); @@ -233,7 +226,7 @@ public void onEnable() { openInvCommand.onCommand(sender, command, label, args); } else { sender.sendMessage(ChatColor.RED + "Current server does not have newest player data! " - + ChatColor.GRAY + "Connecting to server " + query.getYoungestServer() + " which has the newest data..."); + + ChatColor.GRAY + "Connecting to server " + query.getYoungestServer() + " which has the newest data..."); connectToServer(((Player) sender).getUniqueId(), query.getYoungestServer()); } }); @@ -303,7 +296,7 @@ public void loadConfig() { syncWithGroupOnLogout = getConfig().getBoolean("sync-with-group-on-logout"); storeUnknownPlayers = getConfig().getBoolean("store-unknown-players"); - + queryTimeout = getConfig().getInt("query-timeout"); applyTimedOutQueries = getConfig().getBoolean("apply-timed-out-queries"); @@ -311,7 +304,7 @@ public void loadConfig() { for (SyncType syncType : SyncType.values()) { String key = "sync." + syncType.getKey(); if (!getConfig().contains(key, true) - && getConfig().contains("sync-" + syncType.getKey(), true)) { + && getConfig().contains("sync-" + syncType.getKey(), true)) { key = "sync-" + syncType.getKey(); } if (getConfig().getBoolean(key)) { @@ -398,8 +391,8 @@ && getConfig().contains("sync-" + syncType.getKey(), true)) { if (storeUnknownPlayers && getServer().getWorld("world") == null && getConfig().getBoolean("create-world")) { getLogger().log(Level.INFO, "No world with the name 'world' exists while 'store-unknown-players' is enabled. This world is needed for that functionality to work correctly, creating it... (can be disabled with 'create-world' in the config)"); World world = getServer().createWorld(new WorldCreator("world") - .type(WorldType.FLAT) - .generateStructures(false)); + .type(WorldType.FLAT) + .generateStructures(false)); world.setAutoSave(false); world.setViewDistance(2); world.setKeepSpawnInMemory(false); @@ -424,14 +417,14 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String /** * Get a language message from the config and replace variables in it - * @param key The key of the message (lang.) + * @param key The key of the message (lang.) * @param replacements An array of variables to be replaced with certain strings in the format [var,repl,var,repl,...] * @return The message string with colorcodes and variables replaced */ public String getLang(String key, String... replacements) { String msg = ChatColor.translateAlternateColorCodes('&', getConfig().getString("lang." + key, getName() + ": &cMissing language key &6" + key)); for (int i = 0; i + 1 < replacements.length; i += 2) { - msg = msg.replace("%" + replacements[i] + "%", replacements[i+1]); + msg = msg.replace("%" + replacements[i] + "%", replacements[i + 1]); } return msg; } @@ -447,10 +440,10 @@ public boolean isLocked(UUID playerId) { /** * Get the date when a player last logged out - * @param playerId The UUID of the player - * @param online Whether or not it should return the current time if the player is online - * @return The timestamp of his last known data on the server in milliseconds; - * 0 if the file doesn't exist or an error occurs. (Take a look at {File#lastModified}) + * @param playerId The UUID of the player + * @param online Whether or not it should return the current time if the player is online + * @return The timestamp of his last known data on the server in milliseconds; + * 0 if the file doesn't exist or an error occurs. (Take a look at {File#lastModified}) */ public long getLastSeen(UUID playerId, boolean online) { if (online) { @@ -480,7 +473,7 @@ public long getLastSeen(UUID playerId, boolean online) { * @param playerId The UUID of the player * @param timeStamp The timestamp to set as the last modify time of the file in * milliseconds. - * @return true if the time was successfully set + * @return true if the time was successfully set */ public boolean setLastSeen(UUID playerId, long timeStamp) { File playerDat = getPlayerDataFile(playerId); @@ -535,7 +528,7 @@ public boolean applyTimedOutQueries() { /** * Connect a player to a bungee server * @param playerId The UUID of the player - * @param server The name of the server + * @param server The name of the server */ public void connectToServer(UUID playerId, String server) { Player player = getServer().getPlayer(playerId); @@ -549,7 +542,7 @@ public void connectToServer(UUID playerId, String server) { /** * Apply a PlayerData object to its player - * @param data The data to apply + * @param data The data to apply */ public void applyData(PlayerData data, Runnable finished) { if (data == null) @@ -557,8 +550,8 @@ public void applyData(PlayerData data, Runnable finished) { if (data.getDataVersion() != getServer().getUnsafe().getDataVersion()) { getLogger().log(Level.WARNING, "Received data with " - + (data.getDataVersion() < getServer().getUnsafe().getDataVersion() ? "older" : "newer") - + " Minecraft data version (" + data.getDataVersion() + ") than this server (" + getServer().getUnsafe().getDataVersion() + "). Trying to apply anyways but there will most likely be errors! Please try running the same Server version on all synced servers."); + + (data.getDataVersion() < getServer().getUnsafe().getDataVersion() ? "older" : "newer") + + " Minecraft data version (" + data.getDataVersion() + ") than this server (" + getServer().getUnsafe().getDataVersion() + "). Trying to apply anyways but there will most likely be errors! Please try running the same Server version on all synced servers."); } runSync(() -> { @@ -645,7 +638,7 @@ public void applyData(PlayerData data, Runnable finished) { } if (player == null) { logDebug("Could not apply data for player " + data.getPlayerId() + " as he isn't online and " - + (getOpenInv() == null ? "this server doesn't have OpenInv installed!" : "never was online on this server before!")); + + (getOpenInv() == null ? "this server doesn't have OpenInv installed!" : "never was online on this server before!")); if (createdNewFile) { getPlayerDataFile(data.getPlayerId()).delete(); } @@ -768,7 +761,7 @@ public void applyData(PlayerData data, Runnable finished) { } catch (NullPointerException ignored) { // world is not known } - for (Iterator it = getServer().advancementIterator(); it.hasNext();) { + for (Iterator it = getServer().advancementIterator(); it.hasNext(); ) { Advancement advancement = it.next(); Map awarded = data.getAdvancementProgress().get(advancement.getKey().toString()); if (awarded != null) { @@ -842,7 +835,7 @@ public void applyData(PlayerData data, Runnable finished) { break; } } - } + } } if (player.isOnline()) { if (shouldSync(SyncType.EFFECTS)) { @@ -936,20 +929,13 @@ private void forceRender(MapView map) { map.addRenderer(new EmptyRenderer()); } - private static class EmptyRenderer extends MapRenderer { - @Override - public void render(@NotNull MapView map, @NotNull MapCanvas canvas, @NotNull Player player) { - - } - } - private void cacheData(PlayerData data, Runnable finished) { playerDataCache.put(data.getPlayerId(), new AbstractMap.SimpleEntry<>(data, finished)); } /** * Get data that was cached which should be applied on a player's login - * @param player The player to get the data for + * @param player The player to get the data for * @return A cache entry containing the PlayerData and the notification Runnable when applied successfully */ public Map.Entry getCachedData(Player player) { @@ -958,7 +944,7 @@ public Map.Entry getCachedData(Player player) { /** * Remove the cached data of a player - * @param player The player to remove the data for + * @param player The player to remove the data for */ public void removeCachedData(Player player) { playerDataCache.invalidate(player.getUniqueId()); @@ -1002,7 +988,7 @@ public PlayerData getData(Player player) { } if (shouldSync(SyncType.ADVANCEMENTS)) { - for (Iterator it = getServer().advancementIterator(); it.hasNext();) { + for (Iterator it = getServer().advancementIterator(); it.hasNext(); ) { Advancement advancement = it.next(); AdvancementProgress progress = player.getAdvancementProgress(advancement); Map awarded = new HashMap<>(); @@ -1089,12 +1075,12 @@ public PlayerData getData(Player player) { } MapData mapData = new MapData( - map.getId(), - worldId, - map.getCenterX(), - map.getCenterZ(), - map.getScale(), - colors + map.getId(), + worldId, + map.getCenterX(), + map.getCenterZ(), + map.getScale(), + colors ); try { // Newer map info @@ -1114,7 +1100,7 @@ public PlayerData getData(Player player) { /** * The sound to play when a player gets unlocked, should match the vanilla levelup - * @param playerId The uuid of the Player to play the sound to + * @param playerId The uuid of the Player to play the sound to */ public void playLoadSound(UUID playerId) { Player player = getServer().getPlayer(playerId); @@ -1125,7 +1111,7 @@ public void playLoadSound(UUID playerId) { /** * The sound to play when a player gets unlocked, should match the vanilla levelup - * @param player The Player to play the sound to + * @param player The Player to play the sound to */ public void playLoadSound(Player player) { player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.7f, 1); @@ -1152,7 +1138,7 @@ public void checkMap(int id) { * Make sure that a task runs on the primary thread */ public void runSync(Runnable run) { - if(getServer().isPrimaryThread() || disabling) { + if (getServer().isPrimaryThread() || disabling) { run.run(); } else { getServer().getScheduler().runTask(this, run); @@ -1163,7 +1149,7 @@ public void runSync(Runnable run) { * Make sure that a task does not run on the primary thread */ public void runAsync(Runnable run) { - if(!getServer().isPrimaryThread() && !disabling) { + if (!getServer().isPrimaryThread() && !disabling) { getServer().getScheduler().runTaskAsynchronously(this, run); } else { run.run(); @@ -1198,13 +1184,6 @@ public void logDebug(String message) { } } - public void setNewestMap(int newestMap) { - if (getNewestMap() < newestMap) { - getMessenger().sendGroupMessage(System.currentTimeMillis(), MessageType.MAP_CREATED, newestMap); - this.newestMap = newestMap; - } - } - public UUID getWorldId(MapView map) { if (map == null) { return null; @@ -1221,8 +1200,63 @@ public UUID getWorldId(MapView map) { return null; } + /** + * @return Reference to the OpenInv plugin to load data for the query option + */ + public OpenInv getOpenInv() { + return openInv; + } + + /** + * @return The messenger for communications between the servers + */ + public ServerMessenger getMessenger() { + return messenger; + } + + /** + * @return The amount of seconds we should wait for a query to stopTimeout + */ + public int getQueryTimeout() { + return queryTimeout; + } + + /** + * @return Whether or not the plugin is currently disabling + */ + public boolean isDisabling() { + return disabling; + } + + /** + * @return Whether or not the plugin is in debugging mode + */ + public boolean isDebug() { + return debug; + } + + /** + * @return The id of the newest map that was seen on this server + */ + public int getNewestMap() { + return newestMap; + } + + public void setNewestMap(int newestMap) { + if (getNewestMap() < newestMap) { + getMessenger().sendGroupMessage(System.currentTimeMillis(), MessageType.MAP_CREATED, newestMap); + this.newestMap = newestMap; + } + } + private enum FilterMode { DENY, ALLOW } + + private static class EmptyRenderer extends MapRenderer { + @Override + public void render(@NotNull MapView map, @NotNull MapCanvas canvas, @NotNull Player player) { + } + } } diff --git a/src/main/java/de/minebench/syncinv/listeners/PlayerFreezeListener.java b/src/main/java/de/minebench/syncinv/listeners/PlayerFreezeListener.java index dfae56d..3a3e4e9 100644 --- a/src/main/java/de/minebench/syncinv/listeners/PlayerFreezeListener.java +++ b/src/main/java/de/minebench/syncinv/listeners/PlayerFreezeListener.java @@ -46,7 +46,7 @@ public PlayerFreezeListener(SyncInv plugin) { @EventHandler(ignoreCancelled = true) public void onDropItem(PlayerDropItemEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("cant-drop-items")); } @@ -54,7 +54,7 @@ public void onDropItem(PlayerDropItemEvent e) { @EventHandler(ignoreCancelled = true) public void onPlayerMove(PlayerMoveEvent e) { - if(!sameBlock(e.getFrom(), e.getTo()) && plugin.isLocked(e.getPlayer().getUniqueId())) { + if (!sameBlock(e.getFrom(), e.getTo()) && plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); if (e.getFrom().getBlockY() == e.getTo().getBlockY()) { e.getPlayer().sendMessage(plugin.getLang("cant-move")); @@ -70,7 +70,7 @@ private boolean sameBlock(Location from, Location to) { @EventHandler(ignoreCancelled = true) public void onPlayerPickupItem(PlayerPickupItemEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("cant-pickup-items")); } @@ -78,7 +78,7 @@ public void onPlayerPickupItem(PlayerPickupItemEvent e) { @EventHandler(ignoreCancelled = true) public void onPlayerPickupExp(PlayerExpChangeEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setAmount(0); e.getPlayer().sendMessage(plugin.getLang("cant-pickup-exp")); } @@ -86,14 +86,14 @@ public void onPlayerPickupExp(PlayerExpChangeEvent e) { @EventHandler(ignoreCancelled = true) public void onPlayerDamage(EntityDamageEvent e) { - if(e.getEntity() instanceof Player && plugin.isLocked(e.getEntity().getUniqueId())) { + if (e.getEntity() instanceof Player && plugin.isLocked(e.getEntity().getUniqueId())) { e.setCancelled(true); } } @EventHandler(ignoreCancelled = true) public void onInventoryInteraction(InventoryClickEvent e) { - if(plugin.isLocked(e.getWhoClicked().getUniqueId())) { + if (plugin.isLocked(e.getWhoClicked().getUniqueId())) { e.setCancelled(true); e.getWhoClicked().sendMessage(plugin.getLang("wait-for-loading")); } @@ -101,7 +101,7 @@ public void onInventoryInteraction(InventoryClickEvent e) { @EventHandler(ignoreCancelled = true) public void onInventoryInteraction(InventoryDragEvent e) { - if(plugin.isLocked(e.getWhoClicked().getUniqueId())) { + if (plugin.isLocked(e.getWhoClicked().getUniqueId())) { e.setCancelled(true); e.getWhoClicked().sendMessage(plugin.getLang("wait-for-loading")); } @@ -109,7 +109,7 @@ public void onInventoryInteraction(InventoryDragEvent e) { @EventHandler(ignoreCancelled = true) public void onInventoryInteraction(InventoryOpenEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("wait-for-loading")); } @@ -117,7 +117,7 @@ public void onInventoryInteraction(InventoryOpenEvent e) { @EventHandler(ignoreCancelled = true) public void onInteraction(PlayerInteractEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("wait-for-loading")); } @@ -125,7 +125,7 @@ public void onInteraction(PlayerInteractEvent e) { @EventHandler(ignoreCancelled = true) public void onDamageEntity(EntityDamageByEntityEvent e) { - if(e.getDamager() instanceof Player && plugin.isLocked(e.getDamager().getUniqueId())) { + if (e.getDamager() instanceof Player && plugin.isLocked(e.getDamager().getUniqueId())) { e.setCancelled(true); e.getDamager().sendMessage(plugin.getLang("wait-for-loading")); } @@ -133,7 +133,7 @@ public void onDamageEntity(EntityDamageByEntityEvent e) { @EventHandler(ignoreCancelled = true) public void onBlockDamage(BlockDamageEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("wait-for-loading")); } @@ -141,7 +141,7 @@ public void onBlockDamage(BlockDamageEvent e) { @EventHandler(ignoreCancelled = true) public void onChat(AsyncPlayerChatEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("wait-for-loading")); } @@ -149,7 +149,7 @@ public void onChat(AsyncPlayerChatEvent e) { @EventHandler(ignoreCancelled = true) public void onChat(PlayerCommandPreprocessEvent e) { - if(plugin.isLocked(e.getPlayer().getUniqueId())) { + if (plugin.isLocked(e.getPlayer().getUniqueId())) { e.setCancelled(true); e.getPlayer().sendMessage(plugin.getLang("wait-for-loading")); } diff --git a/src/main/java/de/minebench/syncinv/listeners/PlayerJoinListener.java b/src/main/java/de/minebench/syncinv/listeners/PlayerJoinListener.java index 70e4cf3..5affa3d 100644 --- a/src/main/java/de/minebench/syncinv/listeners/PlayerJoinListener.java +++ b/src/main/java/de/minebench/syncinv/listeners/PlayerJoinListener.java @@ -50,7 +50,6 @@ public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) { if (plugin.getMessenger().queryData(e.getUniqueId()) == null && (!plugin.getMessenger().isAllowedToBeAlone() || !plugin.getMessenger().isAlone())) { e.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); e.setKickMessage(ChatColor.RED + "Unable to query player data!"); - return; } } } @@ -71,7 +70,7 @@ public void onPlayerLogin(PlayerLoginEvent e) { } else if (entity != null) { // Well... this is weird. An entity with the same UUID as the player's exists?!? Removing it just to be sure... plugin.getLogger().info("A " + entity + " with the same UUID " + e.getPlayer().getUniqueId() - + " as the player login in existed on the server at " + entity.getLocation() + "... removing it!"); + + " as the player login in existed on the server at " + entity.getLocation() + "... removing it!"); entity.remove(); } } diff --git a/src/main/java/de/minebench/syncinv/listeners/PlayerQuitListener.java b/src/main/java/de/minebench/syncinv/listeners/PlayerQuitListener.java index cf84061..8946888 100644 --- a/src/main/java/de/minebench/syncinv/listeners/PlayerQuitListener.java +++ b/src/main/java/de/minebench/syncinv/listeners/PlayerQuitListener.java @@ -43,7 +43,7 @@ public void onPlayerQuit(PlayerQuitEvent event) { } PlayerDataQuery query = plugin.getMessenger().removeQuery(event.getPlayer().getUniqueId()); if (query != null) { - // The player is gone although he had a query... + // The player is gone, although he had a query... // We have to make sure now that the time of the data file matches the old one // and not send our data to all the other servers as it might be outdated plugin.runLater(() -> { @@ -67,5 +67,4 @@ public void onPlayerQuit(PlayerQuitEvent event) { // Update last seen plugin.runLater(() -> plugin.setLastSeen(event.getPlayer().getUniqueId(), System.currentTimeMillis()), 1); } - } diff --git a/src/main/java/de/minebench/syncinv/messenger/Message.java b/src/main/java/de/minebench/syncinv/messenger/Message.java index 0a2c20f..baeccf4 100644 --- a/src/main/java/de/minebench/syncinv/messenger/Message.java +++ b/src/main/java/de/minebench/syncinv/messenger/Message.java @@ -18,8 +18,6 @@ * along with this program. If not, see . */ -import lombok.Getter; -import lombok.ToString; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.util.io.BukkitObjectInputStream; import org.bukkit.util.io.BukkitObjectOutputStream; @@ -33,8 +31,6 @@ import java.util.Collections; import java.util.Queue; -@Getter -@ToString public class Message { public static final int VERSION = 4; private final String sender; @@ -44,9 +40,10 @@ public class Message { /** * A Message of a certain type. Optionally with some data - * @param type The type of the message - * @param id The transaction ID this Message is associated with - * @param objects The data, in the order that it should be send + * + * @param type The type of the message + * @param id The transaction ID this Message is associated with + * @param objects The data, in the order that it should be send * @throws IllegalArgumentException when the amount of Objects given didn't match the MessageType requirements */ public Message(String sender, long id, MessageType type, Object... objects) { @@ -71,10 +68,9 @@ public Object read() { /** * Generate a byte array out of the data of this message - * @return The generated byte array (starts with the sender - * then the type ordinal, then the amount - * of data being send and each data object); - * an empty one if an error occurred + * @return The generated byte array (starts with the sender then the type ordinal, + * then the amount of data being sent and each data object); + * an empty one if an error occurred */ public byte[] toByteArray() { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -98,12 +94,12 @@ public byte[] toByteArray() { /** * Get the message from a bytearray generated as described in the toByteArray method * @param bytes The bytes - * @return The Message object + * @return The Message object * @throws IOException - * @throws IllegalArgumentException When the message type is not supported + * @throws IllegalArgumentException When the message type is not supported * @throws ClassNotFoundException - * @throws InvalidConfigurationException If the data is invalid - * @throws VersionMismatchException If the received message is of a different version than it can accept + * @throws InvalidConfigurationException If the data is invalid + * @throws VersionMismatchException If the received message is of a different version than it can accept */ public static Message fromByteArray(byte[] bytes) throws IOException, IllegalArgumentException, ClassNotFoundException, InvalidConfigurationException, VersionMismatchException { try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); @@ -123,4 +119,41 @@ public static Message fromByteArray(byte[] bytes) throws IOException, IllegalArg } } + /** + * @return the sending server name + */ + public String getSender() { + return sender; + } + + /** + * @return the type of the message + */ + public MessageType getType() { + return type; + } + + /** + * @return the transaction ID this Message is associated with + */ + public long getId() { + return id; + } + /** + * @return the data, in order + */ + public Queue getData() { + return data; + } + + /** + * @return a Sting representation of this message + */ + public String toString() { + return "Message{" + + "sender='" + sender + '\'' + + ", type=" + type + + ", data=" + data + + '}'; + } } diff --git a/src/main/java/de/minebench/syncinv/messenger/PlayerDataQuery.java b/src/main/java/de/minebench/syncinv/messenger/PlayerDataQuery.java index c028444..ec30260 100644 --- a/src/main/java/de/minebench/syncinv/messenger/PlayerDataQuery.java +++ b/src/main/java/de/minebench/syncinv/messenger/PlayerDataQuery.java @@ -2,6 +2,7 @@ import org.bukkit.scheduler.BukkitTask; +import java.util.Collections; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -33,7 +34,7 @@ public class PlayerDataQuery { private BukkitTask timeoutTask; private boolean completed = false; - private Map servers = new ConcurrentHashMap<>(); + private final Map servers = new ConcurrentHashMap<>(); public PlayerDataQuery(UUID playerId, long localLastSeen, Consumer onComplete) { this.playerId = playerId; @@ -41,21 +42,9 @@ public PlayerDataQuery(UUID playerId, long localLastSeen, Consumer getServers() { - return servers; - } - /** * Add a new response to this query - * @param server The name of the server + * @param server The name of the server * @param lastSeen When the user was last seen on that server */ public void addResponse(String server, long lastSeen) { @@ -86,10 +75,6 @@ public long getTimestamp() { return timestamp; } - public void setTimeoutTask(BukkitTask timeoutTask) { - this.timeoutTask = timeoutTask; - } - public void stopTimeout() { if (timeoutTask != null) { timeoutTask.cancel(); @@ -118,4 +103,32 @@ public boolean isCompleted() { public Consumer getOnComplete() { return onComplete; } + + /** + * @return the unique ID of the player + */ + public UUID getPlayerId() { + return playerId; + } + + /** + * @return the last seen time of this player on the local server + */ + public long getLocalLastSeen() { + return localLastSeen; + } + + /** + * @param timeoutTask the task to get canceled whenever the query completes + */ + public void setTimeoutTask(BukkitTask timeoutTask) { + this.timeoutTask = timeoutTask; + } + + /** + * @return an unmodifiable map of all servers and their last responded times + */ + public Map getServers() { + return Collections.unmodifiableMap(servers); + } } diff --git a/src/main/java/de/minebench/syncinv/messenger/RedisMessenger.java b/src/main/java/de/minebench/syncinv/messenger/RedisMessenger.java index 6f18f39..ed77366 100644 --- a/src/main/java/de/minebench/syncinv/messenger/RedisMessenger.java +++ b/src/main/java/de/minebench/syncinv/messenger/RedisMessenger.java @@ -36,10 +36,10 @@ */ public class RedisMessenger extends ServerMessenger { - private final RedisClient client; - private StatefulRedisConnection connection; private static final String CHANNEL_PREFIX = "syncinv:"; private static final String VERSION_PREFIX = Message.VERSION + ":"; + private final RedisClient client; + private StatefulRedisConnection connection; public RedisMessenger(SyncInv plugin) { super(plugin); @@ -62,7 +62,7 @@ public RedisMessenger(SyncInv plugin) { client = RedisClient.create(uri); StatefulRedisPubSubConnection connection = client.connectPubSub(new StringByteArrayCodec()); - connection.addListener(new RedisPubSubListener() { + connection.addListener(new RedisPubSubListener<>() { @Override public void message(String channel, byte[] bytes) { if (!channel.startsWith(CHANNEL_PREFIX)) { @@ -126,8 +126,7 @@ protected void sendMessageImplementation(String target, Message message, boolean } } - private class StringByteArrayCodec implements RedisCodec { - + private static class StringByteArrayCodec implements RedisCodec { private final StringCodec stringCodec = new StringCodec(); private final ByteArrayCodec byteArrayCodec = new ByteArrayCodec(); diff --git a/src/main/java/de/minebench/syncinv/messenger/ServerMessenger.java b/src/main/java/de/minebench/syncinv/messenger/ServerMessenger.java index 6f839ea..0b90b16 100644 --- a/src/main/java/de/minebench/syncinv/messenger/ServerMessenger.java +++ b/src/main/java/de/minebench/syncinv/messenger/ServerMessenger.java @@ -3,7 +3,6 @@ import de.minebench.syncinv.PlayerData; import de.minebench.syncinv.SyncInv; import de.minebench.syncinv.SyncType; -import lombok.Getter; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -37,44 +36,34 @@ public abstract class ServerMessenger { protected final SyncInv plugin; - - /** - * The group that this server is in - */ - @Getter - private final String serverGroup; - - /** - * The name of this server, should be the same as in the Bungee's config.yml - */ - @Getter - private final String serverName; - /** * The servers that are required to be online to query data */ private final Set requiredServers; - /** * Store a set of all known servers */ private final Set servers = new HashSet<>(); - /** * Store the current queries for PlayerData */ private final Map queries = new ConcurrentHashMap<>(); - /** * This holds queue requests that need to be executed when the player logs out */ private final Map> queuedDataRequests = new ConcurrentHashMap<>(); - /** * List of channels that this plugin listens on */ - @Getter - private Set channels = new HashSet<>(); + private final Set channels = new HashSet<>(); + /** + * The group that this server is in + */ + private final String serverGroup; + /** + * The name of this server, should be the same as in the Bungee's config.yml + */ + private final String serverName; public ServerMessenger(SyncInv plugin) { this.plugin = plugin; @@ -103,7 +92,7 @@ public void goodbye() { /** * Register channels that this messenger should listen on - * @param channels The channels to listen on + * @param channels The channels to listen on */ private void registerChannel(String... channels) { for (String channel : channels) { @@ -133,7 +122,7 @@ public PlayerDataQuery queryData(UUID playerId) { // players will associate the level up sound from the exp giving with the successful load of the inventory // --> play sound plugin.playLoadSound(query.getPlayerId()); - } else if (plugin.shouldQueryInventories()){ + } else if (plugin.shouldQueryInventories()) { sendMessage(youngestServer, query.getTimestamp(), MessageType.GET_DATA, query.getPlayerId()); // Query the player's data query.setTimeoutTask(plugin.runLater(() -> { plugin.sendMessage(query.getPlayerId(), "cant-load-data"); @@ -148,8 +137,8 @@ public PlayerDataQuery queryData(UUID playerId) { /** * Query the data of a player - * @param playerId The UUID of the player - * @param onComplete Handle the player data when all we have all information from the other servers + * @param playerId The UUID of the player + * @param onComplete Handle the player data when all we have all information from the other servers * @return The PlayerDataQuery object, either a new one or the existing one. null if we are unable to query. */ public PlayerDataQuery queryData(UUID playerId, Consumer onComplete) { @@ -157,7 +146,7 @@ public PlayerDataQuery queryData(UUID playerId, Consumer onComp plugin.logDebug("Tried to query data for " + playerId + " but we are all alone :'("); return null; } - + if (!servers.containsAll(requiredServers)) { plugin.logDebug("Tried to query data for " + playerId + " but not all required servers are here :'("); return null; @@ -196,22 +185,22 @@ public boolean isAllowedToBeAlone() { /** * Reaction on a message, this has to be called by the messenger implementation! - * @param target The server this message is targeted at - * @param message The message received + * @param target The server this message is targeted at + * @param message The message received */ protected void onMessage(String target, Message message) { if (message.getSender().equals(getServerName()) // don't read messages from ourselves - || target != null // target is null? Accept message anyways... - && !"*".equals(target) - && !getServerName().equals(target) - && !("group:" + getServerGroup()).equalsIgnoreCase(target) ) { + || target != null // target is null? Accept message anyways... + && !"*".equals(target) + && !getServerName().equals(target) + && !("group:" + getServerGroup()).equalsIgnoreCase(target)) { // This message is not for us return; } - + servers.add(message.getSender()); - UUID playerId = null; + UUID playerId; long lastSeen; Player player; PlayerDataQuery query; @@ -254,7 +243,7 @@ protected void onMessage(String target, Message message) { queueDataRequest(playerId, message.getSender(), message.getId()); } sendMessage(message.getSender(), message.getId(), MessageType.IS_ONLINE, playerId); // Tell the sender - } else if (plugin.getOpenInv() != null){ + } else if (plugin.getOpenInv() != null) { OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(playerId); if (offlinePlayer.hasPlayedBefore()) { // we can ensure here that openInv is using the same player instance as we do and therefor it is safe to unload regardless of openinv saving it or not @@ -282,7 +271,7 @@ protected void onMessage(String target, Message message) { break; } plugin.logDebug(message.getId() + " Received " + message.getType() + " for " + data.getPlayerId() + " from " + message.getSender() + " targeted at " + target + ". Applying it." + - " isQueryNull=" + (query == null) + ", shouldSyncWithGroupOnLogout=" + plugin.shouldSyncWithGroupOnLogout() + ", dataTimestamp=" + data.getTimeStamp()); + " isQueryNull=" + (query == null) + ", shouldSyncWithGroupOnLogout=" + plugin.shouldSyncWithGroupOnLogout() + ", dataTimestamp=" + data.getTimeStamp()); plugin.applyData(data, () -> { if (query != null) { query.stopTimeout(); @@ -291,7 +280,7 @@ protected void onMessage(String target, Message message) { }); } else { plugin.logDebug(message.getId() + " Received " + message.getType() + " for " + data.getPlayerId() + " from " + message.getSender() + " targeted at " + target + " but we decided to not apply it!" - + " isQueryNull=" + (query == null) + ", shouldSyncWithGroupOnLogout=" + plugin.shouldSyncWithGroupOnLogout() + ", dataTimestamp=" + data.getTimeStamp()); + + " isQueryNull=" + (query == null) + ", shouldSyncWithGroupOnLogout=" + plugin.shouldSyncWithGroupOnLogout() + ", dataTimestamp=" + data.getTimeStamp()); } break; @@ -312,7 +301,7 @@ protected void onMessage(String target, Message message) { break; case CANT_GET_DATA: - // Send the player to the server if we can't get the data and he has an open request + // Send the player to the server if we can't get the data, and he has an open request playerId = (UUID) message.read(); plugin.logDebug(message.getId() + " Received " + message.getType() + " for " + playerId + " from " + message.getSender() + " targeted at " + target); if (hasQuery(playerId)) { @@ -350,15 +339,15 @@ private void completeQuery(PlayerDataQuery query) { /** * Check if a query was answered by all known servers * @param query The query to check - * @return Whether or not all servers responded + * @return Whether or not all servers responded */ private boolean isCompleted(PlayerDataQuery query) { if (query.getServers().size() < servers.size()) { return false; } - + if (!query.getServers().keySet().containsAll(servers) - || !query.getServers().keySet().containsAll(requiredServers)) { + || !query.getServers().keySet().containsAll(requiredServers)) { return false; } @@ -368,12 +357,12 @@ private boolean isCompleted(PlayerDataQuery query) { /** * Send a simple message with only a type to other servers - * @param target The name of the target server; - * use "group:" to only send to a specific group of servers; - * use "*" to send it to everyone - * @param id The transaction ID this Message is associated with - * @param type The type of the message to send - * @param objects The data to send in the order the exact order + * @param target The name of the target server; + * use "group:" to only send to a specific group of servers; + * use "*" to send it to everyone + * @param id The transaction ID this Message is associated with + * @param type The type of the message to send + * @param objects The data to send in the order the exact order */ public void sendMessage(String target, long id, MessageType type, Object... objects) { sendMessage(target, new Message(getServerName(), id, type, objects), false); @@ -381,11 +370,11 @@ public void sendMessage(String target, long id, MessageType type, Object... obje /** * Send a message to other servers - * @param target The name of the target server; - * use "group:" to only send to a specific group of servers; - * use "*" to send it to everyone - * @param message The message to send - * @param sync Whether the message should be send sync or on its own thread + * @param target The name of the target server; + * use "group:" to only send to a specific group of servers; + * use "*" to send it to everyone + * @param message The message to send + * @param sync Whether the message should be send sync or on its own thread */ public void sendMessage(String target, Message message, boolean sync) { plugin.logDebug(message.getId() + " Sending " + (sync ? "sync " : "") + message.getType() + " to " + target + " containing " + message.getData().size() + " objects."); @@ -394,9 +383,9 @@ public void sendMessage(String target, Message message, boolean sync) { /** * Send a simple message with only a type to all servers of the group - * @param id The transaction ID this Message is associated with - * @param type The type of the message to send - * @param objects The data to send in the order the exact order + * @param id The transaction ID this Message is associated with + * @param type The type of the message to send + * @param objects The data to send in the order the exact order */ public void sendGroupMessage(long id, MessageType type, Object... objects) { sendMessage("group:" + getServerGroup(), id, type, objects); @@ -404,8 +393,8 @@ public void sendGroupMessage(long id, MessageType type, Object... objects) { /** * Send a message to all servers of the group - * @param message The message to send - * @param sync Whether the message should be send sync or on its own thread + * @param message The message to send + * @param sync Whether the message should be send sync or on its own thread */ public void sendGroupMessage(Message message, boolean sync) { sendMessage("group:" + getServerGroup(), message, sync); @@ -433,7 +422,7 @@ public PlayerDataQuery getQuery(UUID playerId) { * Add a query for a player * @param playerId The UUID of the player * @param query The query to add - * @return The previous PlayerDataQuery if there was one + * @return The previous PlayerDataQuery if there was one */ public PlayerDataQuery addQuery(UUID playerId, PlayerDataQuery query) { Player player = plugin.getServer().getPlayer(playerId); @@ -447,8 +436,8 @@ public PlayerDataQuery addQuery(UUID playerId, PlayerDataQuery query) { /** * Remove an active query of a player - * @param playerId The UUID of the player - * @return The previous PlayerDataQuery if there was one + * @param playerId The UUID of the player + * @return The previous PlayerDataQuery if there was one */ public PlayerDataQuery removeQuery(UUID playerId) { return queries.remove(playerId); @@ -457,8 +446,8 @@ public PlayerDataQuery removeQuery(UUID playerId) { /** * Add a server to the data request queue * @param playerId The UUID of the player - * @param server The name of the server - * @param id The transaction ID this query is associated with + * @param server The name of the server + * @param id The transaction ID this query is associated with */ private void queueDataRequest(UUID playerId, String server, long id) { queuedDataRequests.computeIfAbsent(playerId, uuid -> Collections.synchronizedMap(new LinkedHashMap<>())).put(server, id); @@ -486,4 +475,25 @@ public void fulfillQueuedDataRequest(PlayerData data) { } } } + + /** + * @return The group that this server is in + */ + public String getServerGroup() { + return serverGroup; + } + + /** + * @return The name of this server, should be the same as in the Bungee's config. yml + */ + public String getServerName() { + return serverName; + } + + /** + * @return modifiable set of all the channels the plugin is listening to + */ + public Set getChannels() { + return channels; + } } diff --git a/src/main/java/de/minebench/syncinv/messenger/VersionMismatchException.java b/src/main/java/de/minebench/syncinv/messenger/VersionMismatchException.java index 57c6899..20e3029 100644 --- a/src/main/java/de/minebench/syncinv/messenger/VersionMismatchException.java +++ b/src/main/java/de/minebench/syncinv/messenger/VersionMismatchException.java @@ -27,10 +27,16 @@ public VersionMismatchException(int receivedVersion, int supportedVersion, Strin this.supportedVersion = supportedVersion; } + /** + * @return get the actual version that was received + */ public int getReceivedVersion() { return receivedVersion; } + /** + * @return get the version that is supported and was expected + */ public int getSupportedVersion() { return supportedVersion; } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 555fa4b..341f853 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,30 +2,30 @@ name: ${project.name} version: '${minecraft.plugin.version}' api-version: '1.20' main: de.minebench.syncinv.SyncInv -softdepend: [OpenInv] -authors: [Phoenix616] +softdepend: [ OpenInv ] +authors: [ Phoenix616 ] description: ${project.description} commands: - syncinv: - aliases: [syncinv] - description: Plugin command description. - usage: / [reload] - permission: SyncInv.command - permission-message: You don't have the permission - openinv: - aliases: [oi, inv, open] - description: Open a player's inventory - permission: SyncInv.openinv - usage: / - Open a player's inventory - openender: - aliases: [oe] - description: Opens the enderchest of a player - permission: SyncInv.openender - usage: / - Open a player's enderchest + syncinv: + aliases: [ syncinv ] + description: Plugin command description. + usage: / [reload] + permission: SyncInv.command + permission-message: You don't have the permission + openinv: + aliases: [ oi, inv, open ] + description: Open a player's inventory + permission: SyncInv.openinv + usage: / - Open a player's inventory + openender: + aliases: [ oe ] + description: Opens the enderchest of a player + permission: SyncInv.openender + usage: / - Open a player's enderchest permissions: - syncinv.command: - description: Gives permission to the plugin command - default: op - syncinv.command.reload: - description: Gives permission to reload the plugin - default: op \ No newline at end of file + syncinv.command: + description: Gives permission to the plugin command + default: op + syncinv.command.reload: + description: Gives permission to reload the plugin + default: op \ No newline at end of file