diff --git a/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/MojangNames.java b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/MojangNames.java new file mode 100644 index 000000000..df4d21e7a --- /dev/null +++ b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/MojangNames.java @@ -0,0 +1,121 @@ +package vg.civcraft.mc.namelayer; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import io.civrepo.commons.holders.MoreMapUtils; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.scheduler.BukkitTask; +import vg.civcraft.mc.civmodcore.serialization.NBTCompound; +import vg.civcraft.mc.namelayer.listeners.AssociationListener; + +public final class MojangNames { + + private static final Map PROFILES = Collections.synchronizedMap( + new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); + private static final String PROFILES_FILE = "mojang.dat"; + private static final long SAVE_DELAY = 20 * 60; // 60 seconds' worth of ticks + private static BukkitTask SAVE_TASK; + + public static void init(final NameLayerPlugin plugin) { + final Path mojangFile = plugin.getResourceFile(PROFILES_FILE).toPath(); + // Load all the profiles that already exist + Bukkit.getScheduler().runTaskAsynchronously( + plugin, () -> load(plugin, mojangFile)); + // Set up a process of saving profiles + SAVE_TASK = Bukkit.getScheduler().runTaskTimerAsynchronously( + plugin, () -> save(plugin, mojangFile), SAVE_DELAY, SAVE_DELAY); + } + + public static void reset(final NameLayerPlugin plugin) { + if (!PROFILES.isEmpty()) { + save(plugin, plugin.getResourceFile(PROFILES_FILE).toPath()); + PROFILES.clear(); + } + if (SAVE_TASK != null) { + SAVE_TASK.cancel(); + SAVE_TASK = null; + } + } + + private static void load(final NameLayerPlugin plugin, final Path file) { + PROFILES.clear(); + try { + final byte[] data = Files.readAllBytes(file); + final NBTCompound nbt = NBTCompound.fromBytes(data); + nbt.getKeys().forEach(key -> PROFILES.put(key, nbt.getUUID(key))); + plugin.info("[MojangNames] Mojang profiles loaded!"); + } + catch (final NoSuchFileException ignored) {} + catch (final IOException exception) { + plugin.warning("[MojangNames] Could not load Mojang profiles!", exception); + } + } + + private static void save(final NameLayerPlugin plugin, final Path file) { + final NBTCompound nbt = new NBTCompound(); + PROFILES.forEach(nbt::setUUID); + final byte[] data = NBTCompound.toBytes(nbt); + try { + Files.write(file, data, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.WRITE); + } + catch (final IOException exception) { + plugin.warning("[MojangNames] Could not save Mojang profiles!", exception); + return; + } + plugin.info("[MojangNames] Mojang profiles saved!"); + } + + /** + * Returns the player's uuid based on their Mojang name. + * + * @param name The player's Mojang name. + * @return Returns the player's uuid, or null. + */ + public static UUID getMojangUuid(final String name) { + if (Strings.isNullOrEmpty(name)) { + return null; + } + return PROFILES.get(name); + } + + /** + *

Returns the player's Mojang name based on their uuid.

+ * + *

Note: The name will be lowercase.

+ * + * @param uuid The player's uuid. + * @return Returns the player's Mojang name, or null. + */ + public static String getMojangName(final UUID uuid) { + if (uuid == null) { + return null; + } + return MoreMapUtils.getKeyFromValue(PROFILES, uuid); + } + + /** + * DO NOT USE THIS ANYWHERE OTHER THAN {@link AssociationListener#OnPlayerLogin(PlayerLoginEvent)} + * + * @param uuid The player's uuid. + * @param name The player's Mojang name. + */ + public static void declareMojangName(final UUID uuid, final String name) { + Preconditions.checkNotNull(uuid); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + PROFILES.put(name, uuid); + } + +} diff --git a/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/NameLayerPlugin.java b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/NameLayerPlugin.java index c5c160714..3a95d8b4d 100644 --- a/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/NameLayerPlugin.java +++ b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/NameLayerPlugin.java @@ -6,12 +6,10 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.logging.Level; - import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; - import vg.civcraft.mc.civmodcore.ACivMod; import vg.civcraft.mc.civmodcore.dao.ManagedDatasource; import vg.civcraft.mc.namelayer.command.CommandHandler; @@ -26,8 +24,8 @@ import vg.civcraft.mc.namelayer.misc.ClassHandler; import vg.civcraft.mc.namelayer.misc.NameCleanser; import vg.civcraft.mc.namelayer.permission.PermissionType; +public class NameLayerPlugin extends ACivMod { -public class NameLayerPlugin extends ACivMod{ private static AssociationList associations; private static BlackList blackList; private static GroupManagerDao groupManagerDao; @@ -55,6 +53,7 @@ public class NameLayerPlugin extends ACivMod{ ClassHandler.Initialize(Bukkit.getServer()); new NameAPI(new GroupManager(), associations); NameCleanser.load(config.getConfigurationSection("name_cleanser")); + MojangNames.init(this); registerListeners(); if (loadGroups){ PermissionType.initialize(); @@ -68,8 +67,8 @@ public class NameLayerPlugin extends ACivMod{ } public void registerListeners(){ - getServer().getPluginManager().registerEvents(new AssociationListener(), this); - getServer().getPluginManager().registerEvents(new PlayerListener(), this); + registerListener(new AssociationListener()); + registerListener(new PlayerListener()); } @Override @@ -88,6 +87,8 @@ public class NameLayerPlugin extends ACivMod{ @Override public void onDisable() { + MojangNames.reset(this); + super.onDisable(); } public static NameLayerPlugin getInstance(){ @@ -229,4 +230,5 @@ public class NameLayerPlugin extends ACivMod{ public static DefaultGroupHandler getDefaultGroupHandler() { return defaultGroupHandler; } + } diff --git a/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/listeners/AssociationListener.java b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/listeners/AssociationListener.java index 3ba1e9acc..93741ad0a 100644 --- a/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/listeners/AssociationListener.java +++ b/plugins/namelayer-paper/namelayer-spigot/src/main/java/vg/civcraft/mc/namelayer/listeners/AssociationListener.java @@ -1,15 +1,15 @@ package vg.civcraft.mc.namelayer.listeners; import java.util.UUID; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; - +import vg.civcraft.mc.namelayer.MojangNames; import vg.civcraft.mc.namelayer.NameAPI; import vg.civcraft.mc.namelayer.NameLayerPlugin; import vg.civcraft.mc.namelayer.database.AssociationList; @@ -62,14 +62,16 @@ public class AssociationListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void OnPlayerLogin(PlayerLoginEvent event) { - String name = associations.getCurrentName(event.getPlayer().getUniqueId()); + final Player player = event.getPlayer(); + MojangNames.declareMojangName(player.getUniqueId(), player.getName()); + String name = associations.getCurrentName(player.getUniqueId()); if (name == null) { - associations.addPlayer(event.getPlayer().getName(), event.getPlayer().getUniqueId()); - name = associations.getCurrentName(event.getPlayer().getUniqueId()); + associations.addPlayer(player.getName(), player.getUniqueId()); + name = associations.getCurrentName(player.getUniqueId()); } if (game != null) - game.setPlayerProfle(event.getPlayer(), name); + game.setPlayerProfle(player, name); } }