Player data upgrade complete

Auto-save for each user
ConfigData stuff
Removed player events
This commit is contained in:
Norbi Peti 2020-10-24 23:47:33 +02:00
parent 83ecf7717f
commit 132eba7db6
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
13 changed files with 77 additions and 298 deletions

View file

@ -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.");
}

View file

@ -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

View file

@ -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);

View file

@ -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);
}
/**

View file

@ -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;
}

View file

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

View file

@ -102,7 +102,10 @@ public abstract class ChromaGamerBase {
obj.plugindata = YamlConfiguration.loadConfiguration(file);
obj.plugindata.set(folder + "_id", fname);
obj.init();
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);
}

View file

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

View file

@ -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;
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;
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to get player with UUID " + uuid + " and class " + cl.getSimpleName() + "!", e, MainPlugin.Instance);
return null;
}
}
/**
* 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();
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}