Player data upgrade complete
Auto-save for each user ConfigData stuff Removed player events
This commit is contained in:
parent
83ecf7717f
commit
132eba7db6
13 changed files with 77 additions and 298 deletions
|
@ -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.");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<String> coders = new ArrayList<String>() {
|
||||
|
@ -129,8 +130,8 @@ public class TBMCCoreAPI {
|
|||
EventExceptionHandler.registerEvents(listener, plugin, eventExceptionCoreHandler);
|
||||
}
|
||||
|
||||
public static <T extends ChromaGamerBase> void RegisterUserClass(Class<T> userclass) {
|
||||
ChromaGamerBase.RegisterPluginUserClass(userclass);
|
||||
public static <T extends ChromaGamerBase> void RegisterUserClass(Class<T> userclass, Supplier<T> constructor) {
|
||||
ChromaGamerBase.RegisterPluginUserClass(userclass, constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -250,7 +250,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> 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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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> channel = getConfig().getData("channel", Channel.GlobalChat,
|
||||
public final ConfigData<Channel> channel = config.getData("channel", Channel.GlobalChat,
|
||||
id -> Channel.getChannels().filter(ch -> ch.ID.equalsIgnoreCase((String) id)).findAny().orElse(null), ch -> ch.ID);
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package buttondevteam.lib.player;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class PlayerData<T> {
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -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<String> 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 <T> PlayerData<T> 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 <T extends Enum<T>> EnumPlayerData<T> dataEnum(Class<T> cl, T def) {
|
||||
return super.dataEnum(pluginname, cl, def);
|
||||
public ConfigData<String> 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 extends TBMCPlayerBase> T getPlayer(UUID uuid, Class<T> 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<String, TBMCPlayerBase> 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<br>
|
||||
* 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 extends TBMCPlayerBase> T asPluginPlayer(Class<T> 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<String> 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue