From 132eba7db6fcbe79fed4119b488bfac0356e65c9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 24 Oct 2020 23:47:33 +0200 Subject: [PATCH] Player data upgrade complete Auto-save for each user ConfigData stuff Removed player events --- .../java/buttondevteam/core/MainPlugin.java | 4 +- .../buttondevteam/core/PlayerListener.java | 16 +- .../component/channel/ChannelComponent.java | 8 +- .../java/buttondevteam/lib/TBMCCoreAPI.java | 5 +- .../buttondevteam/lib/chat/Command2MC.java | 2 +- .../buttondevteam/lib/chat/TBMCChatAPI.java | 2 +- .../lib/player/ChromaGamerBase.java | 29 +++- .../buttondevteam/lib/player/PlayerData.java | 37 ----- .../lib/player/TBMCPlayerBase.java | 150 ++++-------------- .../lib/player/TBMCPlayerJoinEvent.java | 34 ---- .../lib/player/TBMCPlayerLoadEvent.java | 27 ---- .../lib/player/TBMCPlayerQuitEvent.java | 34 ---- .../lib/player/TBMCPlayerSaveEvent.java | 27 ---- 13 files changed, 77 insertions(+), 298 deletions(-) delete mode 100755 Chroma-Core/src/main/java/buttondevteam/lib/player/PlayerData.java delete mode 100755 Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerJoinEvent.java delete mode 100755 Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerLoadEvent.java delete mode 100755 Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerQuitEvent.java delete mode 100755 Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java index bb4d7cb..9672012 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java @@ -122,7 +122,7 @@ public class MainPlugin extends ButtonPlugin { ? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof Player ? TBMCPlayer.getPlayer(((Player) sender).getUniqueId(), TBMCPlayer.class) : null)); //Players, has higher priority - TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class); + TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class, TBMCPlayer::new); TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fg§f", Color.White, "g", null)); //The /ooc ID has moved to the config TBMCChatAPI.RegisterChatChannel( Channel.AdminChat = new Channel("§cADMIN§f", Color.Red, "a", Channel.inGroupFilter(null))); @@ -153,7 +153,7 @@ public class MainPlugin extends ButtonPlugin { @Override public void pluginDisable() { logger.info("Saving player data..."); - TBMCPlayerBase.savePlayers(); + ChromaGamerBase.saveUsers(); logger.info("Player data saved."); } diff --git a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java index ea21f17..c15ede4 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.java @@ -1,5 +1,6 @@ package buttondevteam.core; +import buttondevteam.core.component.towny.TownyComponent; import buttondevteam.lib.*; import buttondevteam.lib.architecture.ButtonPlugin; import buttondevteam.lib.chat.ChatMessage; @@ -28,12 +29,21 @@ public class PlayerListener implements Listener { @EventHandler(priority = EventPriority.NORMAL) public void OnPlayerJoin(PlayerJoinEvent event) { - TBMCPlayerBase.joinPlayer(event.getPlayer()); + var p = event.getPlayer(); + TBMCPlayer player = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class); + if (player.PlayerName().get() == null) { + player.PlayerName().set(p.getName()); + MainPlugin.Instance.getLogger().info("Player name saved: " + player.PlayerName().get()); + } else if (!p.getName().equals(player.PlayerName().get())) { + TownyComponent.renameInTowny(player.PlayerName().get(), p.getName()); + MainPlugin.Instance.getLogger().info(player.PlayerName().get() + " renamed to " + p.getName()); + player.PlayerName().set(p.getName()); + } } @EventHandler(priority = EventPriority.NORMAL) public void OnPlayerLeave(PlayerQuitEvent event) { - TBMCPlayerBase.quitPlayer(event.getPlayer()); + TBMCPlayerBase.getPlayer(event.getPlayer().getUniqueId(), TBMCPlayer.class).uncache(); } @EventHandler(priority = EventPriority.HIGHEST) @@ -65,7 +75,7 @@ public class PlayerListener implements Listener { val ev = new TBMCCommandPreprocessEvent(sender, ch.orElse(Channel.GlobalChat), message, rtr.score, rtr.groupID);*/ val cg = ChromaGamerBase.getFromSender(sender); if (cg == null) throw new RuntimeException("Couldn't get user from sender for " + sender.getName() + "!"); - val ev = new TBMCCommandPreprocessEvent(sender, cg.channel().get(), message, sender); + val ev = new TBMCCommandPreprocessEvent(sender, cg.channel.get(), message, sender); Bukkit.getPluginManager().callEvent(ev); if (ev.isCancelled()) event.setCancelled(true); //Cancel the original event diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/channel/ChannelComponent.java b/Chroma-Core/src/main/java/buttondevteam/core/component/channel/ChannelComponent.java index 6f807f9..ada92d8 100644 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/channel/ChannelComponent.java +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/channel/ChannelComponent.java @@ -59,17 +59,17 @@ public class ChannelComponent extends Component { return; } if (message == null) { - Channel oldch = user.channel().get(); + Channel oldch = user.channel.get(); if (oldch instanceof ChatRoom) ((ChatRoom) oldch).leaveRoom(sender); if (oldch.equals(channel)) - user.channel().set(Channel.GlobalChat); + user.channel.set(Channel.GlobalChat); else { - user.channel().set(channel); + user.channel.set(channel); if (channel instanceof ChatRoom) ((ChatRoom) channel).joinRoom(sender); } - sender.sendMessage("§6You are now talking in: §b" + user.channel().get().DisplayName().get()); + sender.sendMessage("§6You are now talking in: §b" + user.channel.get().DisplayName().get()); } else TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender, user, message).fromCommand(true) .permCheck(senderMC.getPermCheck()).build(), channel); diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java index 72129aa..97f9e9a 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCoreAPI.java @@ -17,6 +17,7 @@ import java.net.URLConnection; import java.util.*; import java.util.Map.Entry; import java.util.function.Consumer; +import java.util.function.Supplier; public class TBMCCoreAPI { static final List coders = new ArrayList() { @@ -129,8 +130,8 @@ public class TBMCCoreAPI { EventExceptionHandler.registerEvents(listener, plugin, eventExceptionCoreHandler); } - public static void RegisterUserClass(Class userclass) { - ChromaGamerBase.RegisterPluginUserClass(userclass); + public static void RegisterUserClass(Class userclass, Supplier constructor) { + ChromaGamerBase.RegisterPluginUserClass(userclass, constructor); } /** diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java index 8676927..8f1bbaa 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java @@ -250,7 +250,7 @@ public class Command2MC extends Command2 implemen return true; } //System.out.println("Executing " + label + " which is actually " + command.getName()); - handleCommand(new Command2MCSender(sender, user.channel().get(), sender), + handleCommand(new Command2MCSender(sender, user.channel.get(), sender), ("/" + command.getName() + " " + String.join(" ", args)).trim(), false); ///trim(): remove space if there are no args return true; } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java index 421515b..3253425 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java @@ -22,7 +22,7 @@ public class TBMCChatAPI { * @return The event cancelled state */ public static boolean SendChatMessage(ChatMessage cm) { - return SendChatMessage(cm, cm.getUser().channel().get()); + return SendChatMessage(cm, cm.getUser().channel.get()); } /** diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java index 7bde5df..0ce7593 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java @@ -102,7 +102,10 @@ public abstract class ChromaGamerBase { obj.plugindata = YamlConfiguration.loadConfiguration(file); obj.plugindata.set(folder + "_id", fname); obj.init(); - userCache.computeIfAbsent(cl, key -> new HashMap<>()).put(fname, obj); + synchronized (userCache) { + userCache.computeIfAbsent(cl, key -> new HashMap<>()).put(fname, obj); + } + obj.scheduleUncache(); return obj; } @@ -130,10 +133,16 @@ public abstract class ChromaGamerBase { return null; } + public static void saveUsers() { + for (var users : userCache.values()) + for (var user : users.values()) + ConfigData.saveNow(user.plugindata); //Calls save() + } + /** - * Saves the player. It'll handle all exceptions that may happen. + * Saves the player. It'll handle all exceptions that may happen. Called automatically. */ - private final void save() { + protected void save() { try { if (plugindata.getKeys(false).size() > 0) plugindata.save(new File(TBMC_PLAYERS_DIR + getFolder(), getFileName() + ".yml")); @@ -142,6 +151,18 @@ public abstract class ChromaGamerBase { } } + public void uncache() { + synchronized (userCache) { + var c = userCache.get(getClass()); + if (c != null) if (c.remove(getFileName()) != this) + throw new IllegalStateException("A different player instance was cached!"); + } + } + + protected void scheduleUncache() { + Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, this::uncache, 2 * 60 * 60 * 20); //2 hours + } + /** * Connect two accounts. Do not use for connecting two Minecraft accounts or similar. Also make sure you have the "id" tag set * @@ -243,6 +264,6 @@ public abstract class ChromaGamerBase { //----------------------------------------------------------------- - public final ConfigData channel = getConfig().getData("channel", Channel.GlobalChat, + public final ConfigData channel = config.getData("channel", Channel.GlobalChat, id -> Channel.getChannels().filter(ch -> ch.ID.equalsIgnoreCase((String) id)).findAny().orElse(null), ch -> ch.ID); } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/PlayerData.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/PlayerData.java deleted file mode 100755 index a0a6620..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/PlayerData.java +++ /dev/null @@ -1,37 +0,0 @@ -package buttondevteam.lib.player; - -import org.bukkit.configuration.file.YamlConfiguration; - -public class PlayerData { - private final String name; - private final YamlConfiguration yaml; - private final T def; - - public PlayerData(String name, YamlConfiguration yaml, T def) { - this.name = name; - this.yaml = yaml; - this.def = def; - } - - @SuppressWarnings("unchecked") - // @Deprecated - What was once enforced (2 days ago from now) vanished now - public T get() { - Object value = yaml.get(name, def); - if (value instanceof Integer) { - if (def instanceof Short) // If the default is Short the value must be as well because both are T - return (T) (Short) ((Integer) value).shortValue(); - if (def instanceof Long) - return (T) (Long) ((Integer) value).longValue(); - } - return (T) value; - } - - public void set(T value) { - yaml.set(name, value); - } - - @Override - public String toString() { - return get().toString(); - } -} diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java index f1f0610..0629071 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java @@ -1,33 +1,21 @@ package buttondevteam.lib.player; -import buttondevteam.core.MainPlugin; -import buttondevteam.core.component.towny.TownyComponent; -import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.IHaveConfig; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; import java.util.Set; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; @AbstractUserClass(foldername = "minecraft", prototype = TBMCPlayer.class) @TBMCPlayerEnforcer public abstract class TBMCPlayerBase extends ChromaGamerBase { protected UUID uuid; - private final String pluginname; - - protected TBMCPlayerBase() { - if (getClass().isAnnotationPresent(PlayerClass.class)) - pluginname = getClass().getAnnotation(PlayerClass.class).pluginname(); - else - throw new RuntimeException("Class not defined as player class! Use @PlayerClass"); - - var section = plugindata.getConfigurationSection(pluginname); - if (section == null) section = plugindata.createSection(pluginname); - config.reset(section); - } + @Getter + private final IHaveConfig config = new IHaveConfig(this::save); public UUID getUUID() { if (uuid == null) @@ -35,28 +23,8 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { return uuid; } - public PlayerData PlayerName() { - return super.data(null); - } - - /** - * Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair" - * - * @return A data object with methods to get and set - */ - @Override - protected PlayerData data(T def) { - return super.data(pluginname, def); - } - - /** - * Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair" - * - * @return A data object with methods to get and set - */ - @Override - protected > EnumPlayerData dataEnum(Class cl, T def) { - return super.dataEnum(pluginname, cl, def); + public ConfigData PlayerName() { + return config.getData("PlayerName", ""); } /** @@ -66,93 +34,31 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { * @param cl The type of the player * @return The requested player object */ - @SuppressWarnings("unchecked") public static T getPlayer(UUID uuid, Class cl) { - if (playermap.containsKey(uuid + "-" + cl.getSimpleName())) - return (T) playermap.get(uuid + "-" + cl.getSimpleName()); - try { - T player; - if (playermap.containsKey(uuid + "-" + TBMCPlayer.class.getSimpleName())) { - player = cl.newInstance(); - player.plugindata = playermap.get(uuid + "-" + TBMCPlayer.class.getSimpleName()).plugindata; - playermap.put(uuid + "-" + cl.getSimpleName(), player); // It will get removed on player quit - } else - player = ChromaGamerBase.getUser(uuid.toString(), cl); - player.uuid = uuid; - return player; - } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e, MainPlugin.Instance); - return null; - } + var player = ChromaGamerBase.getUser(uuid.toString(), cl); + if (player.uuid.equals(uuid)) + throw new IllegalStateException("Player UUID differs after converting from and to string..."); + return player; } - /** - * Key: UUID-Class - */ - private static final ConcurrentHashMap playermap = new ConcurrentHashMap<>(); + @Override + public void init() { + super.init(); + uuid = UUID.fromString(getFileName()); - /** - * Gets the TBMCPlayer object as a specific plugin player, keeping it's data
- * Make sure to use try-with-resources with this to save the data, as it may need to load the file - * - * @param cl The TBMCPlayer subclass - */ - public T asPluginPlayer(Class cl) { - return getPlayer(uuid, cl); + String pluginname; + if (getClass().isAnnotationPresent(PlayerClass.class)) + pluginname = getClass().getAnnotation(PlayerClass.class).pluginname(); + else + throw new RuntimeException("Class not defined as player class! Use @PlayerClass"); + + var section = super.plugindata.getConfigurationSection(pluginname); + if (section == null) section = super.plugindata.createSection(pluginname); + config.reset(section); } - /** - * Only intended to use from ButtonCore - */ - public static void savePlayer(TBMCPlayerBase player) { - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerSaveEvent(player)); - try { - player.close(); - } catch (Exception e) { - new Exception("Failed to save player data for " + player.PlayerName().get(), e).printStackTrace(); - } - } - - /** - * Only intended to use from ButtonCore - */ - public static void joinPlayer(Player p) { - TBMCPlayer player = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class); - if (player.PlayerName().get() == null) { - player.PlayerName().set(p.getName()); - MainPlugin.Instance.getLogger().info("Player name saved: " + player.PlayerName().get()); - } else if (!p.getName().equals(player.PlayerName().get())) { - TownyComponent.renameInTowny(player.PlayerName().get(), p.getName()); - MainPlugin.Instance.getLogger().info(player.PlayerName().get() + " renamed to " + p.getName()); - player.PlayerName().set(p.getName()); - } - playermap.put(p.getUniqueId() + "-" + TBMCPlayer.class.getSimpleName(), player); - - // Load in other plugins - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerLoadEvent(player)); - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerJoinEvent(player, p)); - player.save(); - } - - /** - * Only intended to use from ButtonCore - */ - public static void quitPlayer(Player p) { - final TBMCPlayerBase player = playermap.get(p.getUniqueId() + "-" + TBMCPlayer.class.getSimpleName()); - player.save(); - Bukkit.getServer().getPluginManager().callEvent(new TBMCPlayerQuitEvent(player, p)); - playermap.entrySet().removeIf(entry -> entry.getKey().startsWith(p.getUniqueId().toString())); - } - - public static void savePlayers() { - playermap.values().forEach(p -> { - try { - p.close(); - } catch (Exception e) { - TBMCCoreAPI.SendException("Error while saving player " + p.PlayerName().get() + " (" + p.getFolder() - + "/" + p.getFileName() + ")!", e, MainPlugin.Instance); - } - }); + @Override + protected void scheduleUncache() { //Don't schedule it, it will happen on quit } /** @@ -180,9 +86,9 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase { } @Override - public void close() throws Exception { + protected void save() { Set keys = plugindata.getKeys(false); if (keys.size() > 1) // PlayerName is always saved, but we don't need a file for just that - super.close(); + super.save(); } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerJoinEvent.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerJoinEvent.java deleted file mode 100755 index 46b1eab..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerJoinEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -package buttondevteam.lib.player; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class TBMCPlayerJoinEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - - private final TBMCPlayerBase player; - private final Player player_; - - public TBMCPlayerJoinEvent(TBMCPlayerBase player, Player player_) { - this.player = player; - this.player_ = player_; - } - - public TBMCPlayerBase GetPlayer() { - return player; - } - - public Player getPlayer() { // :P - return player_; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerLoadEvent.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerLoadEvent.java deleted file mode 100755 index b92d2df..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerLoadEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package buttondevteam.lib.player; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class TBMCPlayerLoadEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - - private final TBMCPlayerBase player; - - public TBMCPlayerLoadEvent(TBMCPlayerBase player) { - this.player = player; - } - - public TBMCPlayerBase GetPlayer() { - return player; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerQuitEvent.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerQuitEvent.java deleted file mode 100755 index e5dc4b9..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerQuitEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -package buttondevteam.lib.player; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class TBMCPlayerQuitEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - - private final TBMCPlayerBase player; - private final Player player_; - - public TBMCPlayerQuitEvent(TBMCPlayerBase player, Player player_) { - this.player = player; - this.player_ = player_; - } - - public TBMCPlayerBase GetPlayer() { - return player; - } - - public Player getPlayer() { - return player_; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java deleted file mode 100755 index c755c8a..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerSaveEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package buttondevteam.lib.player; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class TBMCPlayerSaveEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - - private final TBMCPlayerBase player; - - public TBMCPlayerSaveEvent(TBMCPlayerBase player) { - this.player = player; - } - - public TBMCPlayerBase GetPlayer() { - return player; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} \ No newline at end of file