diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index 3af53024..4817237c 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -27,6 +27,7 @@ import net.Indyuce.mmocore.comp.vault.VaultEconomy; import net.Indyuce.mmocore.comp.vault.VaultMMOLoader; import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.listener.*; +import net.Indyuce.mmocore.listener.bungee.GetMMOCorePlayerListener; import net.Indyuce.mmocore.listener.event.PlayerPressKeyListener; import net.Indyuce.mmocore.listener.option.*; import net.Indyuce.mmocore.listener.profession.FishingListener; @@ -51,401 +52,417 @@ import org.bukkit.command.CommandMap; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; +import org.spigotmc.SpigotConfig; import java.io.File; import java.lang.reflect.Field; import java.util.logging.Level; public class MMOCore extends LuminePlugin { - public static MMOCore plugin; - - public final WaypointManager waypointManager = new WaypointManager(); - public final SoundManager soundManager = new SoundManager(); - public final RequestManager requestManager = new RequestManager(); - public final ConfigItemManager configItems = new ConfigItemManager(); - public final PlayerActionBar actionBarManager = new PlayerActionBar(); - public final SkillManager skillManager = new SkillManager(); - public final ClassManager classManager = new ClassManager(); - public final DropTableManager dropTableManager = new DropTableManager(); - public final BoosterManager boosterManager = new BoosterManager(); - public final AttributeManager attributeManager = new AttributeManager(); - public final PartyManager partyManager = new PartyManager(); - public final QuestManager questManager = new QuestManager(); - public final ProfessionManager professionManager = new ProfessionManager(); - public final ExperienceManager experience = new ExperienceManager(); - public final LootChestManager lootChests = new LootChestManager(); - public final MMOLoadManager loadManager = new MMOLoadManager(); - public final RestrictionManager restrictionManager = new RestrictionManager(); - public final StatManager statManager = new StatManager(); - @Deprecated - public final SkillTreeManager skillTreeManager = new SkillTreeManager(); - - // Profession managers - public final CustomBlockManager mineManager = new CustomBlockManager(); - public final FishingManager fishingManager = new FishingManager(); - public final AlchemyManager alchemyManager = new AlchemyManager(); - public final EnchantManager enchantManager = new EnchantManager(); - public final SmithingManager smithingManager = new SmithingManager(); - - @NotNull - public ConfigManager configManager; - public VaultEconomy economy; - public RegionHandler regionHandler = new DefaultRegionHandler(); - public PlaceholderParser placeholderParser = new DefaultParser(); - public DataProvider dataProvider = new YAMLDataProvider(); - - // Modules - @NotNull - public PartyModule partyModule; - - public boolean shouldDebugSQL = false; - - private static final int MYTHICLIB_COMPATIBILITY_INDEX = 7; - - public MMOCore() { - plugin = this; - } - - public void load() { - - // Check if the ML build matches - if (MYTHICLIB_COMPATIBILITY_INDEX != MythicLib.MMOCORE_COMPATIBILITY_INDEX) { - getLogger().log(Level.WARNING, "Your versions of MythicLib and MMOCore do not match. Make sure you are using the latest builds of both plugins"); - disable(); - return; - } - - // Register MMOCore-specific objects - MythicLib.plugin.getEntities().registerRestriction(new MMOCoreTargetRestriction()); - MythicLib.plugin.getModifiers().registerModifierType("attribute", configObject -> new AttributeModifier(configObject)); - - - // Register extra objective, drop items... - if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) - loadManager.registerLoader(new WorldGuardMMOLoader()); - - if (Bukkit.getPluginManager().getPlugin("Citizens") != null) - loadManager.registerLoader(new CitizensMMOLoader()); - - if (Bukkit.getPluginManager().getPlugin("Vault") != null) loadManager.registerLoader(new VaultMMOLoader()); - - if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) - loadManager.registerLoader(new MythicMobsMMOLoader()); - } - - public void enable() { - new SpigotPlugin(70575, this).checkForUpdate(); - new Metrics(this); - saveDefaultConfig(); - - final int configVersion = getConfig().contains("config-version", true) ? getConfig().getInt("config-version") : -1; - final int defConfigVersion = getConfig().getDefaults().getInt("config-version"); - if (configVersion != defConfigVersion) { - getLogger().warning("You may be using an outdated config.yml!"); - getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); - } - - if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) - dataProvider = new MySQLDataProvider(getConfig()); - shouldDebugSQL = getConfig().getBoolean("mysql.debug"); - - if (getConfig().isConfigurationSection("default-playerdata")) - dataProvider.getDataManager().loadDefaultData(getConfig().getConfigurationSection("default-playerdata")); - - if (Bukkit.getPluginManager().getPlugin("Vault") != null) economy = new VaultEconomy(); - - if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { - placeholderParser = new PlaceholderAPIParser(); - getLogger().log(Level.INFO, "Hooked onto PlaceholderAPI"); - } - - if (Bukkit.getPluginManager().getPlugin("Citizens") != null) { - Bukkit.getPluginManager().registerEvents(new CitizenInteractEventListener(), this); - getLogger().log(Level.INFO, "Hooked onto Citizens"); - } - - if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) { - regionHandler = new WorldGuardRegionHandler(); - getLogger().log(Level.INFO, "Hooked onto WorldGuard"); - } - - if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { - Bukkit.getServer().getPluginManager().registerEvents(new MythicHook(), this); - MMOCore.plugin.getLogger().log(Level.INFO, "Hooked onto MythicMobs"); - } - - /* - * Resource regeneration. Must check if entity is dead otherwise regen will make - * the 'respawn' button glitched plus HURT entity effect bug - */ - new BukkitRunnable() { - public void run() { - for (PlayerData player : PlayerData.getAll()) - if (player.isOnline() && !player.getPlayer().isDead()) - for (PlayerResource resource : PlayerResource.values()) { - double regenAmount = player.getProfess().getHandler(resource).getRegen(player); - if (regenAmount != 0) - resource.regen(player, regenAmount); - } - } - }.runTaskTimer(MMOCore.plugin, 100, 20); - - /* - * For the sake of the lord, make sure they aren't using MMOItems Mana and - * Stamina Addon...This should prevent a couple error reports produced by people - * not reading the installation guide... - */ - if (Bukkit.getPluginManager().getPlugin("MMOMana") != null) { - getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "MMOCore is not meant to be used with MMOItems ManaAndStamina"); - getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "Please read the installation guide!"); - Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] MMOCore is not meant to be used with MMOItems ManaAndStamina"); - Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] Please read the installation guide!"); - return; - } - - initializePlugin(false); - - if (getConfig().getBoolean("vanilla-exp-redirection.enabled")) - Bukkit.getPluginManager().registerEvents(new RedirectVanillaExp(getConfig().getDouble("vanilla-exp-redirection.ratio")), this); - - // Enable debug mode for extra debug tools - if (getConfig().contains("debug")) { - DebugMode.setLevel(getConfig().getInt("debug", 0)); - DebugMode.enableActionBar(); - } - - // Load quest module - try { - String questPluginName = UtilityMethods.enumName(getConfig().getString("quest-plugin")); - PartyModuleType moduleType = PartyModuleType.valueOf(questPluginName); - Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); - partyModule = moduleType.provideModule(); - } catch (RuntimeException exception) { - getLogger().log(Level.WARNING, "Could not initialize quest module: " + exception.getMessage()); - partyModule = new MMOCorePartyModule(); - } - - - - // Load party module - try { - String partyPluginName = UtilityMethods.enumName(getConfig().getString("party-plugin")); - PartyModuleType moduleType = PartyModuleType.valueOf(partyPluginName); - Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); - partyModule = moduleType.provideModule(); - } catch (RuntimeException exception) { - getLogger().log(Level.WARNING, "Could not initialize party module: " + exception.getMessage()); - partyModule = new MMOCorePartyModule(); - } - - - // Skill casting - try { - SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode"))); - Bukkit.getPluginManager().registerEvents(mode.loadFromConfig(getConfig().getConfigurationSection("skill-casting")), this); - } catch (RuntimeException exception) { - getLogger().log(Level.WARNING, "Could not load skill casting: " + exception.getMessage()); - } - - if (configManager.overrideVanillaExp = getConfig().getBoolean("override-vanilla-exp")) - Bukkit.getPluginManager().registerEvents(new VanillaExperienceOverride(), this); - - if (getConfig().getBoolean("hotbar-swapping.enabled")) - try { - Bukkit.getPluginManager().registerEvents(new HotbarSwap(getConfig().getConfigurationSection("hotbar-swapping")), this); - } catch (RuntimeException exception) { - getLogger().log(Level.WARNING, "Could not load hotbar swapping: " + exception.getMessage()); - } - - if (getConfig().getBoolean("prevent-spawner-xp")) - Bukkit.getPluginManager().registerEvents(new NoSpawnerEXP(), this); - - if (getConfig().getBoolean("death-exp-loss.enabled")) - Bukkit.getPluginManager().registerEvents(new DeathExperienceLoss(), this); - - if (getConfig().getBoolean("shift-click-player-profile-check")) - Bukkit.getPluginManager().registerEvents(new PlayerProfileCheck(), this); - - Bukkit.getPluginManager().registerEvents(new WaypointsListener(), this); - Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); - Bukkit.getPluginManager().registerEvents(new GoldPouchesListener(), this); - Bukkit.getPluginManager().registerEvents(new BlockListener(), this); - Bukkit.getPluginManager().registerEvents(new LootableChestsListener(), this); - Bukkit.getPluginManager().registerEvents(new GuildListener(), this); - Bukkit.getPluginManager().registerEvents(new FishingListener(), this); - Bukkit.getPluginManager().registerEvents(new PlayerCollectStats(), this); - Bukkit.getPluginManager().registerEvents(new PlayerPressKeyListener(), this); - // Bukkit.getPluginManager().registerEvents(new ClassTriggers(), this); - - /* - * Initialize player data from all online players. This is very important to do - * that after registering all the professses otherwise the player datas can't - * recognize what profess the player has and professes will be lost - */ - Bukkit.getOnlinePlayers().forEach(player -> dataProvider.getDataManager().setup(player.getUniqueId())); - - // load guild data after loading player data - dataProvider.getGuildManager().load(); - - // Command - try { - final Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); - - bukkitCommandMap.setAccessible(true); - CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); - - FileConfiguration config = new ConfigFile("commands").getConfig(); - - if (config.contains("player")) - commandMap.register("mmocore", new PlayerStatsCommand(config.getConfigurationSection("player"))); - if (config.contains("attributes")) - commandMap.register("mmocore", new AttributesCommand(config.getConfigurationSection("attributes"))); - if (config.contains("class")) - commandMap.register("mmocore", new ClassCommand(config.getConfigurationSection("class"))); - if (config.contains("waypoints")) - commandMap.register("mmocore", new WaypointsCommand(config.getConfigurationSection("waypoints"))); - if (config.contains("quests")) - commandMap.register("mmocore", new QuestsCommand(config.getConfigurationSection("quests"))); - if (config.contains("skills")) - commandMap.register("mmocore", new SkillsCommand(config.getConfigurationSection("skills"))); - if (config.contains("friends")) - commandMap.register("mmocore", new FriendsCommand(config.getConfigurationSection("friends"))); - if (config.contains("party")) - commandMap.register("mmocore", new PartyCommand(config.getConfigurationSection("party"))); - if (config.contains("guild")) - commandMap.register("mmocore", new GuildCommand(config.getConfigurationSection("guild"))); - - if (hasEconomy() && economy.isValid()) { - if (config.contains("withdraw")) - commandMap.register("mmocore", new WithdrawCommand(config.getConfigurationSection("withdraw"))); - if (config.contains("deposit")) - commandMap.register("mmocore", new DepositCommand(config.getConfigurationSection("deposit"))); - } - } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) { - ex.printStackTrace(); - } - - MMOCoreCommandTreeRoot mmoCoreCommand = new MMOCoreCommandTreeRoot(); - getCommand("mmocore").setExecutor(mmoCoreCommand); - getCommand("mmocore").setTabCompleter(mmoCoreCommand); - - if (getConfig().getBoolean("auto-save.enabled")) { - int autosave = getConfig().getInt("auto-save.interval") * 20; - new BukkitRunnable() { - public void run() { - - // Save player data - for (PlayerData data : PlayerData.getAll()) - if (data.isFullyLoaded()) - dataProvider.getDataManager().saveData(data); - - // Save guild info - for (Guild guild : dataProvider.getGuildManager().getAll()) - dataProvider.getGuildManager().save(guild); - } - }.runTaskTimerAsynchronously(MMOCore.plugin, autosave, autosave); - } - } - - public void disable() { - - // Save player data - for (PlayerData data : PlayerData.getAll()) - if (data.isFullyLoaded()) { - data.close(); - dataProvider.getDataManager().saveData(data); - } - - // Save guild info - for (Guild guild : dataProvider.getGuildManager().getAll()) - dataProvider.getGuildManager().save(guild); - - // Close MySQL data provider (memory leaks) - if (dataProvider instanceof MySQLDataProvider) - ((MySQLDataProvider) dataProvider).close(); - - // Reset active blocks - mineManager.resetRemainingBlocks(); - - // Clear spawned loot chests - lootChests.getActive().forEach(chest -> chest.expire(false)); - } - - /** - * Called either when the server starts when initializing the manager for - * the first time, or when issuing a plugin reload; in that case, stuff - * like listeners must all be cleared before. - * - * Also see {@link MMOCoreManager} - * - * @param clearBefore True when issuing a plugin reload - */ - public void initializePlugin(boolean clearBefore) { - if (clearBefore) - reloadConfig(); - - configManager = new ConfigManager(); - - statManager.initialize(clearBefore); - if (clearBefore) - MythicLib.plugin.getSkills().initialize(true); - skillManager.initialize(clearBefore); - mineManager.initialize(clearBefore); - partyManager.initialize(clearBefore); - attributeManager.initialize(clearBefore); - - // Experience must be loaded before professions and classes - experience.initialize(clearBefore); - - // Drop tables must be loaded before professions - dropTableManager.initialize(clearBefore); - - professionManager.initialize(clearBefore); - classManager.initialize(clearBefore); - - InventoryManager.load(); - - questManager.initialize(clearBefore); - lootChests.initialize(clearBefore); - restrictionManager.initialize(clearBefore); - waypointManager.initialize(clearBefore); - requestManager.initialize(clearBefore); - soundManager.initialize(clearBefore); - configItems.initialize(clearBefore); - - if (getConfig().isConfigurationSection("action-bar")) - actionBarManager.reload(getConfig().getConfigurationSection("action-bar")); - - if (clearBefore) - PlayerData.getAll().forEach(PlayerData::update); - } - - public static void log(String message) { - log(Level.INFO, message); - } - - public static void debug(int value, String message) { - debug(value, Level.INFO, message); - } - - public static void log(Level level, String message) { - plugin.getLogger().log(level, message); - } - - public static void debug(int value, Level level, String message) { - if (DebugMode.level > (value - 1)) plugin.getLogger().log(level, message); - } - - public File getJarFile() { - return getFile(); - } - - public boolean hasEconomy() { - return economy != null && economy.isValid(); - } - - public static void sqlDebug(String s) { - if(!MMOCore.plugin.shouldDebugSQL) return; - MMOCore.plugin.getLogger().warning("- [SQL Debug] " + s); - } + public static MMOCore plugin; + + public final WaypointManager waypointManager = new WaypointManager(); + public final SoundManager soundManager = new SoundManager(); + public final RequestManager requestManager = new RequestManager(); + public final ConfigItemManager configItems = new ConfigItemManager(); + public final PlayerActionBar actionBarManager = new PlayerActionBar(); + public final SkillManager skillManager = new SkillManager(); + public final ClassManager classManager = new ClassManager(); + public final DropTableManager dropTableManager = new DropTableManager(); + public final BoosterManager boosterManager = new BoosterManager(); + public final AttributeManager attributeManager = new AttributeManager(); + public final PartyManager partyManager = new PartyManager(); + public final QuestManager questManager = new QuestManager(); + public final ProfessionManager professionManager = new ProfessionManager(); + public final ExperienceManager experience = new ExperienceManager(); + public final LootChestManager lootChests = new LootChestManager(); + public final MMOLoadManager loadManager = new MMOLoadManager(); + public final RestrictionManager restrictionManager = new RestrictionManager(); + public final StatManager statManager = new StatManager(); + @Deprecated + public final SkillTreeManager skillTreeManager = new SkillTreeManager(); + + // Profession managers + public final CustomBlockManager mineManager = new CustomBlockManager(); + public final FishingManager fishingManager = new FishingManager(); + public final AlchemyManager alchemyManager = new AlchemyManager(); + public final EnchantManager enchantManager = new EnchantManager(); + public final SmithingManager smithingManager = new SmithingManager(); + + @NotNull + public ConfigManager configManager; + public VaultEconomy economy; + public RegionHandler regionHandler = new DefaultRegionHandler(); + public PlaceholderParser placeholderParser = new DefaultParser(); + public DataProvider dataProvider = new YAMLDataProvider(); + + // Modules + @NotNull + public PartyModule partyModule; + + public boolean shouldDebugSQL = false; + public boolean hasBungee=false; + private static final int MYTHICLIB_COMPATIBILITY_INDEX = 7; + + public MMOCore() { + plugin = this; + } + + public void load() { + + // Check if the ML build matches + if (MYTHICLIB_COMPATIBILITY_INDEX != MythicLib.MMOCORE_COMPATIBILITY_INDEX) { + getLogger().log(Level.WARNING, "Your versions of MythicLib and MMOCore do not match. Make sure you are using the latest builds of both plugins"); + disable(); + return; + } + + // Register MMOCore-specific objects + MythicLib.plugin.getEntities().registerRestriction(new MMOCoreTargetRestriction()); + MythicLib.plugin.getModifiers().registerModifierType("attribute", configObject -> new AttributeModifier(configObject)); + + + // Register extra objective, drop items... + if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) + loadManager.registerLoader(new WorldGuardMMOLoader()); + + if (Bukkit.getPluginManager().getPlugin("Citizens") != null) + loadManager.registerLoader(new CitizensMMOLoader()); + + if (Bukkit.getPluginManager().getPlugin("Vault") != null) loadManager.registerLoader(new VaultMMOLoader()); + + if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) + loadManager.registerLoader(new MythicMobsMMOLoader()); + } + + public void enable() { + new SpigotPlugin(70575, this).checkForUpdate(); + new Metrics(this); + saveDefaultConfig(); + + final int configVersion = getConfig().contains("config-version", true) ? getConfig().getInt("config-version") : -1; + final int defConfigVersion = getConfig().getDefaults().getInt("config-version"); + if (configVersion != defConfigVersion) { + getLogger().warning("You may be using an outdated config.yml!"); + getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); + } + + if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) + dataProvider = new MySQLDataProvider(getConfig()); + shouldDebugSQL = getConfig().getBoolean("mysql.debug"); + + if (getConfig().isConfigurationSection("default-playerdata")) + dataProvider.getDataManager().loadDefaultData(getConfig().getConfigurationSection("default-playerdata")); + + if (Bukkit.getPluginManager().getPlugin("Vault") != null) economy = new VaultEconomy(); + + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + placeholderParser = new PlaceholderAPIParser(); + getLogger().log(Level.INFO, "Hooked onto PlaceholderAPI"); + } + + if (Bukkit.getPluginManager().getPlugin("Citizens") != null) { + Bukkit.getPluginManager().registerEvents(new CitizenInteractEventListener(), this); + getLogger().log(Level.INFO, "Hooked onto Citizens"); + } + + if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) { + regionHandler = new WorldGuardRegionHandler(); + getLogger().log(Level.INFO, "Hooked onto WorldGuard"); + } + + if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { + Bukkit.getServer().getPluginManager().registerEvents(new MythicHook(), this); + MMOCore.plugin.getLogger().log(Level.INFO, "Hooked onto MythicMobs"); + } + + //Checks if the server runs with bungee + boolean bungee = SpigotConfig.bungee; + boolean onlineMode = Bukkit.getServer().getOnlineMode(); + if (bungee && (!(onlineMode))) + hasBungee=true; + else + hasBungee=false; + + //Setups the channel for Bungee + if(hasBungee) { + getServer().getMessenger().registerOutgoingPluginChannel(this,"namespace:give_mmocore_player"); + getServer().getMessenger().registerOutgoingPluginChannel(this,"namespace:get_mmocore_player"); + getServer().getMessenger().registerIncomingPluginChannel(this,"namespace:get_mmocore_player",new GetMMOCorePlayerListener()); + } + + + /* + * Resource regeneration. Must check if entity is dead otherwise regen will make + * the 'respawn' button glitched plus HURT entity effect bug + */ + new BukkitRunnable() { + public void run() { + for (PlayerData player : PlayerData.getAll()) + if (player.isOnline() && !player.getPlayer().isDead()) + for (PlayerResource resource : PlayerResource.values()) { + double regenAmount = player.getProfess().getHandler(resource).getRegen(player); + if (regenAmount != 0) + resource.regen(player, regenAmount); + } + } + }.runTaskTimer(MMOCore.plugin, 100, 20); + + /* + * For the sake of the lord, make sure they aren't using MMOItems Mana and + * Stamina Addon...This should prevent a couple error reports produced by people + * not reading the installation guide... + */ + if (Bukkit.getPluginManager().getPlugin("MMOMana") != null) { + getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "MMOCore is not meant to be used with MMOItems ManaAndStamina"); + getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "Please read the installation guide!"); + Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] MMOCore is not meant to be used with MMOItems ManaAndStamina"); + Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] Please read the installation guide!"); + return; + } + + initializePlugin(false); + + if (getConfig().getBoolean("vanilla-exp-redirection.enabled")) + Bukkit.getPluginManager().registerEvents(new RedirectVanillaExp(getConfig().getDouble("vanilla-exp-redirection.ratio")), this); + + // Enable debug mode for extra debug tools + if (getConfig().contains("debug")) { + DebugMode.setLevel(getConfig().getInt("debug", 0)); + DebugMode.enableActionBar(); + } + + // Load quest module + try { + String questPluginName = UtilityMethods.enumName(getConfig().getString("quest-plugin")); + PartyModuleType moduleType = PartyModuleType.valueOf(questPluginName); + Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); + partyModule = moduleType.provideModule(); + } catch (RuntimeException exception) { + getLogger().log(Level.WARNING, "Could not initialize quest module: " + exception.getMessage()); + partyModule = new MMOCorePartyModule(); + } + + + // Load party module + try { + String partyPluginName = UtilityMethods.enumName(getConfig().getString("party-plugin")); + PartyModuleType moduleType = PartyModuleType.valueOf(partyPluginName); + Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); + partyModule = moduleType.provideModule(); + } catch (RuntimeException exception) { + getLogger().log(Level.WARNING, "Could not initialize party module: " + exception.getMessage()); + partyModule = new MMOCorePartyModule(); + } + + + // Skill casting + try { + SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode"))); + Bukkit.getPluginManager().registerEvents(mode.loadFromConfig(getConfig().getConfigurationSection("skill-casting")), this); + } catch (RuntimeException exception) { + getLogger().log(Level.WARNING, "Could not load skill casting: " + exception.getMessage()); + } + + if (configManager.overrideVanillaExp = getConfig().getBoolean("override-vanilla-exp")) + Bukkit.getPluginManager().registerEvents(new VanillaExperienceOverride(), this); + + if (getConfig().getBoolean("hotbar-swapping.enabled")) + try { + Bukkit.getPluginManager().registerEvents(new HotbarSwap(getConfig().getConfigurationSection("hotbar-swapping")), this); + } catch (RuntimeException exception) { + getLogger().log(Level.WARNING, "Could not load hotbar swapping: " + exception.getMessage()); + } + + if (getConfig().getBoolean("prevent-spawner-xp")) + Bukkit.getPluginManager().registerEvents(new NoSpawnerEXP(), this); + + if (getConfig().getBoolean("death-exp-loss.enabled")) + Bukkit.getPluginManager().registerEvents(new DeathExperienceLoss(), this); + + if (getConfig().getBoolean("shift-click-player-profile-check")) + Bukkit.getPluginManager().registerEvents(new PlayerProfileCheck(), this); + + Bukkit.getPluginManager().registerEvents(new WaypointsListener(), this); + Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); + Bukkit.getPluginManager().registerEvents(new GoldPouchesListener(), this); + Bukkit.getPluginManager().registerEvents(new BlockListener(), this); + Bukkit.getPluginManager().registerEvents(new LootableChestsListener(), this); + Bukkit.getPluginManager().registerEvents(new GuildListener(), this); + Bukkit.getPluginManager().registerEvents(new FishingListener(), this); + Bukkit.getPluginManager().registerEvents(new PlayerCollectStats(), this); + Bukkit.getPluginManager().registerEvents(new PlayerPressKeyListener(), this); + // Bukkit.getPluginManager().registerEvents(new ClassTriggers(), this); + + /* + * Initialize player data from all online players. This is very important to do + * that after registering all the professses otherwise the player datas can't + * recognize what profess the player has and professes will be lost + */ + Bukkit.getOnlinePlayers().forEach(player -> dataProvider.getDataManager().setup(player.getUniqueId())); + + // load guild data after loading player data + dataProvider.getGuildManager().load(); + + // Command + try { + final Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + + bukkitCommandMap.setAccessible(true); + CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); + + FileConfiguration config = new ConfigFile("commands").getConfig(); + + if (config.contains("player")) + commandMap.register("mmocore", new PlayerStatsCommand(config.getConfigurationSection("player"))); + if (config.contains("attributes")) + commandMap.register("mmocore", new AttributesCommand(config.getConfigurationSection("attributes"))); + if (config.contains("class")) + commandMap.register("mmocore", new ClassCommand(config.getConfigurationSection("class"))); + if (config.contains("waypoints")) + commandMap.register("mmocore", new WaypointsCommand(config.getConfigurationSection("waypoints"))); + if (config.contains("quests")) + commandMap.register("mmocore", new QuestsCommand(config.getConfigurationSection("quests"))); + if (config.contains("skills")) + commandMap.register("mmocore", new SkillsCommand(config.getConfigurationSection("skills"))); + if (config.contains("friends")) + commandMap.register("mmocore", new FriendsCommand(config.getConfigurationSection("friends"))); + if (config.contains("party")) + commandMap.register("mmocore", new PartyCommand(config.getConfigurationSection("party"))); + if (config.contains("guild")) + commandMap.register("mmocore", new GuildCommand(config.getConfigurationSection("guild"))); + + if (hasEconomy() && economy.isValid()) { + if (config.contains("withdraw")) + commandMap.register("mmocore", new WithdrawCommand(config.getConfigurationSection("withdraw"))); + if (config.contains("deposit")) + commandMap.register("mmocore", new DepositCommand(config.getConfigurationSection("deposit"))); + } + } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) { + ex.printStackTrace(); + } + + MMOCoreCommandTreeRoot mmoCoreCommand = new MMOCoreCommandTreeRoot(); + getCommand("mmocore").setExecutor(mmoCoreCommand); + getCommand("mmocore").setTabCompleter(mmoCoreCommand); + + if (getConfig().getBoolean("auto-save.enabled")) { + int autosave = getConfig().getInt("auto-save.interval") * 20; + new BukkitRunnable() { + public void run() { + + // Save player data + for (PlayerData data : PlayerData.getAll()) + if (data.isFullyLoaded()) + dataProvider.getDataManager().saveData(data); + + // Save guild info + for (Guild guild : dataProvider.getGuildManager().getAll()) + dataProvider.getGuildManager().save(guild); + } + }.runTaskTimerAsynchronously(MMOCore.plugin, autosave, autosave); + } + } + + public void disable() { + + // Save player data + for (PlayerData data : PlayerData.getAll()) + if (data.isFullyLoaded()) { + data.close(); + dataProvider.getDataManager().saveData(data); + } + + // Save guild info + for (Guild guild : dataProvider.getGuildManager().getAll()) + dataProvider.getGuildManager().save(guild); + + // Close MySQL data provider (memory leaks) + if (dataProvider instanceof MySQLDataProvider) + ((MySQLDataProvider) dataProvider).close(); + + // Reset active blocks + mineManager.resetRemainingBlocks(); + + // Clear spawned loot chests + lootChests.getActive().forEach(chest -> chest.expire(false)); + } + + /** + * Called either when the server starts when initializing the manager for + * the first time, or when issuing a plugin reload; in that case, stuff + * like listeners must all be cleared before. + *

+ * Also see {@link MMOCoreManager} + * + * @param clearBefore True when issuing a plugin reload + */ + public void initializePlugin(boolean clearBefore) { + if (clearBefore) + reloadConfig(); + + configManager = new ConfigManager(); + + statManager.initialize(clearBefore); + if (clearBefore) + MythicLib.plugin.getSkills().initialize(true); + skillManager.initialize(clearBefore); + mineManager.initialize(clearBefore); + partyManager.initialize(clearBefore); + attributeManager.initialize(clearBefore); + + // Experience must be loaded before professions and classes + experience.initialize(clearBefore); + + // Drop tables must be loaded before professions + dropTableManager.initialize(clearBefore); + + professionManager.initialize(clearBefore); + classManager.initialize(clearBefore); + + InventoryManager.load(); + + questManager.initialize(clearBefore); + lootChests.initialize(clearBefore); + restrictionManager.initialize(clearBefore); + waypointManager.initialize(clearBefore); + requestManager.initialize(clearBefore); + soundManager.initialize(clearBefore); + configItems.initialize(clearBefore); + + if (getConfig().isConfigurationSection("action-bar")) + actionBarManager.reload(getConfig().getConfigurationSection("action-bar")); + + if (clearBefore) + PlayerData.getAll().forEach(PlayerData::update); + } + + public static void log(String message) { + log(Level.INFO, message); + } + + public static void debug(int value, String message) { + debug(value, Level.INFO, message); + } + + public static void log(Level level, String message) { + plugin.getLogger().log(level, message); + } + + public static void debug(int value, Level level, String message) { + if (DebugMode.level > (value - 1)) plugin.getLogger().log(level, message); + } + + public File getJarFile() { + return getFile(); + } + + public boolean hasEconomy() { + return economy != null && economy.isValid(); + } + + public static void sqlDebug(String s) { + if (!MMOCore.plugin.shouldDebugSQL) return; + MMOCore.plugin.getLogger().warning("- [SQL Debug] " + s); + } } diff --git a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 8713d21f..c75d3080 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.api.player; +import com.google.gson.JsonObject; import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.player.TemporaryPlayerData; import io.lumine.mythic.lib.player.cooldown.CooldownMap; @@ -28,6 +29,7 @@ import net.Indyuce.mmocore.experience.droptable.ExperienceItem; import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect; +import net.Indyuce.mmocore.manager.data.mysql.MySQLTableEditor; import net.Indyuce.mmocore.party.AbstractParty; import net.Indyuce.mmocore.party.provided.Party; import net.Indyuce.mmocore.player.Unlockable; @@ -50,6 +52,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.*; import java.util.logging.Level; +import java.util.stream.Collectors; public class PlayerData extends OfflinePlayerData implements Closable, ExperienceTableClaimer { @@ -508,6 +511,64 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc }.runTaskTimer(MMOCore.plugin, 0, 1); } + public String toJson() { + + //We create the JSON correspondign to player Data + JsonObject jsonObject = new JsonObject(); + MySQLTableEditor sql = new MySQLTableEditor(MySQLTableEditor.Table.PLAYERDATA, getUniqueId()); + MMOCore.sqlDebug("Saving data for: '" + getUniqueId() + "'..."); + + jsonObject.addProperty("class_points", getClassPoints()); + jsonObject.addProperty("skill_points", getSkillPoints()); + jsonObject.addProperty("attribute_points", getAttributePoints()); + jsonObject.addProperty("attribute_realloc_points", getAttributeReallocationPoints()); + jsonObject.addProperty("level", getLevel()); + jsonObject.addProperty("experience", getExperience()); + jsonObject.addProperty("class", getProfess().getId()); + jsonObject.addProperty("last_login", getLastLogin()); + jsonObject.addProperty("guild", hasGuild() ? getGuild().getId() : null); + + jsonObject.addProperty("waypoints", MMOCoreUtils.arrayToJsonString(getWaypoints())); + jsonObject.addProperty("friends", MMOCoreUtils.arrayToJsonString(getFriends().stream().map(UUID::toString).collect(Collectors.toList()))); + jsonObject.addProperty("bound_skills", MMOCoreUtils.arrayToJsonString(getBoundSkills().stream().map(skill -> skill.getSkill().getHandler().getId()).collect(Collectors.toList()))); + + jsonObject.addProperty("skills", MMOCoreUtils.entrySetToJsonString(mapSkillLevels().entrySet())); + jsonObject.addProperty("times_claimed", MMOCoreUtils.entrySetToJsonString(getItemClaims().entrySet())); + + jsonObject.addProperty("attributes", getAttributes().toJsonString()); + jsonObject.addProperty("professions", getCollectionSkills().toJsonString()); + jsonObject.addProperty("quests", getQuestData().toJsonString()); + jsonObject.addProperty("class_info", createClassInfoData(this).toString()); + + return jsonObject.toString(); + } + + + public static JsonObject createClassInfoData(PlayerData data) { + JsonObject json = new JsonObject(); + for (String c : data.getSavedClasses()) { + SavedClassInformation info = data.getClassInfo(c); + JsonObject classinfo = new JsonObject(); + classinfo.addProperty("level", info.getLevel()); + classinfo.addProperty("experience", info.getExperience()); + classinfo.addProperty("skill-points", info.getSkillPoints()); + classinfo.addProperty("attribute-points", info.getAttributePoints()); + classinfo.addProperty("attribute-realloc-points", info.getAttributeReallocationPoints()); + JsonObject skillinfo = new JsonObject(); + for (String skill : info.getSkillKeys()) + skillinfo.addProperty(skill, info.getSkillLevel(skill)); + classinfo.add("skill", skillinfo); + JsonObject attributeinfo = new JsonObject(); + for (String attribute : info.getAttributeKeys()) + attributeinfo.addProperty(attribute, info.getAttributeLevel(attribute)); + classinfo.add("attribute", attributeinfo); + + json.add(c, classinfo); + } + + return json; + } + public boolean hasReachedMaxLevel() { return getProfess().getMaxLevel() > 0 && getLevel() >= getProfess().getMaxLevel(); } diff --git a/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java b/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java index 64a5744a..bd3b4050 100644 --- a/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java +++ b/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java @@ -1,5 +1,7 @@ package net.Indyuce.mmocore.api.util; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.version.VersionMaterial; import io.lumine.mythic.utils.holograms.Hologram; @@ -26,9 +28,7 @@ import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class MMOCoreUtils { public static boolean pluginItem(ItemStack item) { @@ -140,6 +140,27 @@ public class MMOCoreUtils { return result.toString(); } + + public static Collection jsonArrayToList(String json) { + return new ArrayList<>(Arrays.asList(MythicLib.plugin.getJson().parse(json, String[].class))); + } + + public static String arrayToJsonString(Collection array) { + JsonArray object = new JsonArray(); + for (String str : array) { + object.add(str); + } + return object.toString(); + } + + public static String entrySetToJsonString(Set> entrySet) { + JsonObject object = new JsonObject(); + for (Map.Entry entry : entrySet) { + object.addProperty(entry.getKey(), entry.getValue()); + } + return object.toString(); + } + /** * Method to get all entities surrounding a location. This method does not * take every entity in the world but rather takes all the entities from the diff --git a/src/main/java/net/Indyuce/mmocore/bungee/Bungee.java b/src/main/java/net/Indyuce/mmocore/bungee/Bungee.java new file mode 100644 index 00000000..0d59c7c8 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/bungee/Bungee.java @@ -0,0 +1,52 @@ +package net.Indyuce.mmocore.bungee; + +import net.md_5.bungee.api.plugin.Plugin; +import org.checkerframework.checker.units.qual.C; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.logging.Level; + +public class Bungee extends Plugin { + public static Bungee plugin; + public CacheManager cacheManager = new CacheManager(); + + + @Override + public void onEnable() { + //Register a new communication channel + getProxy().registerChannel("give_mmocore_player"); + getProxy().registerChannel("get_mmocore_player"); + getProxy().getPluginManager().registerListener(this, new MessageListener()); + + + try { + getProxy().getLogger().log(Level.WARNING,"enabling socket"); + ServerSocket serverSocket= new ServerSocket(25580); + Socket clientSocket=serverSocket.accept(); + getProxy().getLogger().log(Level.WARNING,"port: "+clientSocket.getPort()); + + BufferedReader bufferedReader= new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + String line; + while((line=bufferedReader.readLine())!=null) { + getProxy().getLogger().log(Level.WARNING,line); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + @Override + public void onDisable() { + + } + + @Override + public void onLoad() { + plugin = this; + } +} diff --git a/src/main/java/net/Indyuce/mmocore/bungee/CacheManager.java b/src/main/java/net/Indyuce/mmocore/bungee/CacheManager.java new file mode 100644 index 00000000..88b19f63 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/bungee/CacheManager.java @@ -0,0 +1,28 @@ +package net.Indyuce.mmocore.bungee; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.manager.data.mysql.MySQLTableEditor; + +import java.util.HashMap; +import java.util.UUID; +import java.util.stream.Collectors; + +public class CacheManager { + private final HashMap cachedPlayers= new HashMap<>(); + + + public String getCachedPlayer(UUID uuid) { + return cachedPlayers.get(uuid); + } + public boolean hasCachedPlayer(UUID uuid) { + return cachedPlayers.containsKey(uuid); + } + + public void addCachedPlayer(UUID uuid,String playerData) { + cachedPlayers.put(uuid,playerData); + } + + + public void save() { + } +} diff --git a/src/main/java/net/Indyuce/mmocore/bungee/MessageListener.java b/src/main/java/net/Indyuce/mmocore/bungee/MessageListener.java new file mode 100644 index 00000000..a0bd7477 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/bungee/MessageListener.java @@ -0,0 +1,65 @@ +package net.Indyuce.mmocore.bungee; + +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.event.PluginMessageEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; +import org.jetbrains.annotations.NotNull; + +import java.io.*; +import java.util.Collection; +import java.util.UUID; + +public class MessageListener implements Listener { + + /** + * Used to register in the cached Players the data that is sent + */ + @EventHandler + public void onPluginMessage(PluginMessageEvent e) throws IOException { + + //When a server gives the player data + if (e.getTag().equals("give_mmocore_player")) { + + byte[] data = e.getData(); + ByteArrayInputStream in = new ByteArrayInputStream(e.getData()); + DataInputStream inputStream = new DataInputStream(in); + + UUID uuid = UUID.fromString(inputStream.readUTF()); + String jsonMsg = inputStream.readUTF(); + + //We put this data into the CacheManager + Bungee.plugin.cacheManager.addCachedPlayer(uuid,jsonMsg); + } + + + //When a server asks for the player data + if (e.getTag().equals("get_mmocore_player")) { + byte[] data = e.getData(); + ByteArrayInputStream in = new ByteArrayInputStream(e.getData()); + DataInputStream inputStream = new DataInputStream(in); + UUID uuid = UUID.fromString(inputStream.readUTF()); + + + + String response=Bungee.plugin.cacheManager.hasCachedPlayer(uuid)? + Bungee.plugin.cacheManager.getCachedPlayer(uuid):"{}"; + //We format the data corresponding to the player + ByteArrayOutputStream out=new ByteArrayOutputStream(); + DataOutputStream outputStream= new DataOutputStream(out); + outputStream.writeChars(response); + + //We get the corresponding player + ProxiedPlayer proxiedPlayer= Bungee.plugin.getProxy().getPlayer(uuid); + //We send the answer + proxiedPlayer.getServer().getInfo().sendData("get_mmocore_player",out.toByteArray()); + + + } + + } +} + diff --git a/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java b/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java index c26ebd0a..dd27e927 100644 --- a/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java +++ b/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java @@ -30,8 +30,8 @@ public class ClimbExperienceSource extends SpecificExperienceSource { else { String str = config.getString("type").toUpperCase().replace("-", "_"); Validate.isTrue(str.equals("LADDER") || - str.equals("VINE") || str.equals("TWISTING_VINES_PLANT") || str.equals("WEEPING_VINES"), - "ClimbExperienceSource problem: The type must be ladder, vine, twisted-vines or weeping-vines"); + str.equals("VINE") || str.equals("TWISTING_VINES") || str.equals("WEEPING_VINES"), + "ClimbExperienceSource problem: The type must be ladder, vine, twisting-vines or weeping-vines"); type = Material.valueOf(str); } diff --git a/src/main/java/net/Indyuce/mmocore/listener/bungee/GetMMOCorePlayerListener.java b/src/main/java/net/Indyuce/mmocore/listener/bungee/GetMMOCorePlayerListener.java new file mode 100644 index 00000000..81e40242 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/listener/bungee/GetMMOCorePlayerListener.java @@ -0,0 +1,21 @@ +package net.Indyuce.mmocore.listener.bungee; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; + +import java.util.UUID; + +public class GetMMOCorePlayerListener implements PluginMessageListener { + @Override + public void onPluginMessageReceived( String channel, Player player, byte[] bytes) { + if(!channel.equals("give_mmocore_player")) + return; + ByteArrayDataInput input= ByteStreams.newDataInput(bytes); + UUID uuid=UUID.fromString(input.readUTF()); + String Json=input.readUTF(); + } + + +} diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 20549d26..bb5f148a 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -1,5 +1,9 @@ package net.Indyuce.mmocore.manager.data; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.player.TemporaryPlayerData; import net.Indyuce.mmocore.MMOCore; @@ -7,12 +11,18 @@ import net.Indyuce.mmocore.api.event.AsyncPlayerDataLoadEvent; import net.Indyuce.mmocore.api.event.PlayerDataLoadEvent; import net.Indyuce.mmocore.api.player.OfflinePlayerData; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.profess.PlayerClass; +import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; +import net.Indyuce.mmocore.api.util.MMOCoreUtils; +import net.Indyuce.mmocore.guild.provided.Guild; +import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; import java.util.*; +import java.util.logging.Level; public abstract class PlayerDataManager { private final static Map data = Collections.synchronizedMap(new HashMap<>()); @@ -35,6 +45,63 @@ public abstract class PlayerDataManager { return Objects.requireNonNull(data.get(uuid), "Player data is not loaded"); } + + public static void loadDataFromJson(PlayerData data, String json) { + JsonObject object = MythicLib.plugin.getJson().parse(json, JsonObject.class); + + data.setClassPoints(object.get("class_points").getAsInt()); + data.setSkillPoints(object.get("skill_points").getAsInt()); + data.setAttributePoints(object.get("attribute_points").getAsInt()); + data.setAttributeReallocationPoints(object.get("attribute_realloc_points").getAsInt()); + data.setLevel(object.get("level").getAsInt()); + data.setExperience(object.get("experience").getAsInt()); + if (object.has("class")) + data.setClass(MMOCore.plugin.classManager.get(object.get(("class")).getAsString())); + + if (object.has("times_claimed")) { + JsonObject timesClaimed =object.get(("times_claimed")).getAsJsonObject(); + timesClaimed.entrySet().forEach(entry -> data.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt())); + } + + if (object.has(("guild"))) { + Guild guild = MMOCore.plugin.dataProvider.getGuildManager().getGuild(object.get("guild").getAsString()); + data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null); + } + if (object.has(("attributes"))) data.getAttributes().load(object.get("attributes").getAsString()); + if (object.has(("professions"))) + data.getCollectionSkills().load(object.get("professions").getAsString()); + if (object.has(("quests"))) data.getQuestData().load(object.get("quests").getAsString()); + data.getQuestData().updateBossBar(); + if (object.has(("waypoints"))) + data.getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(object.get("waypoints").getAsString())); + if (object.has(("friends"))) + MMOCoreUtils.jsonArrayToList(object.get("friends").getAsString()).forEach(str -> data.getFriends().add(UUID.fromString(str))) + ; + if (object.has(("skills"))) { + JsonObject skillsObject = object.get("skills").getAsJsonObject(); + for (Map.Entry entry : skillsObject.entrySet()) + data.setSkillLevel(entry.getKey(), entry.getValue().getAsInt()); + } + if (object.has(("bound_skills"))) + for (String skill : MMOCoreUtils.jsonArrayToList(object.get("bound_skills").getAsString())) + if (data.getProfess().hasSkill(skill)) + data.getBoundSkills().add(data.getProfess().getSkill(skill)); + if (object.has(("class_info"))) { + JsonObject classObject = object.get("class_info").getAsJsonObject(); + for (Map.Entry entry : classObject.entrySet()) { + try { + PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey()); + Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'"); + data.applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject())); + } catch (IllegalArgumentException exception) { + MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage()); + } + } + } + + } + + /** * Safely unregisters the player data from the map. * This saves the player data either through SQL or YAML, diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java index e720ab8f..38597892 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java @@ -42,7 +42,7 @@ getResultAsync("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" + "experience INT(11) DEFAULT 0,class VARCHAR(20),guild VARCHAR(20),last_login LONG," + "attributes LONGTEXT,professions LONGTEXT,times_claimed LONGTEXT,quests LONGTEXT," + "waypoints LONGTEXT,friends LONGTEXT,skills LONGTEXT,bound_skills LONGTEXT," - + "class_info LONGTEXT,PRIMARY KEY (uuid));"); + + "class_info LONGTEXT, PRIMARY KEY (uuid));"); } @Override diff --git a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java index 66d5ed47..977b6784 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLPlayerDataManager.java @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.manager.data.mysql; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -9,238 +10,253 @@ import net.Indyuce.mmocore.api.player.OfflinePlayerData; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; +import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.manager.data.PlayerDataManager; import net.Indyuce.mmocore.manager.data.mysql.MySQLTableEditor.Table; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; +import java.io.*; +import java.net.Socket; import java.sql.SQLException; import java.util.*; import java.util.Map.Entry; import java.util.logging.Level; import java.util.stream.Collectors; +import static net.Indyuce.mmocore.api.player.PlayerData.createClassInfoData; + public class MySQLPlayerDataManager extends PlayerDataManager { - private final MySQLDataProvider provider; + private final MySQLDataProvider provider; - public MySQLPlayerDataManager(MySQLDataProvider provider) { - this.provider = provider; - } + public MySQLPlayerDataManager(MySQLDataProvider provider) { + this.provider = provider; + } - @Override - public void loadData(PlayerData data) { - provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + data.getUniqueId() + "';", (result) -> { - try { - MMOCore.sqlDebug("Loading data for: '" + data.getUniqueId() + "'..."); + @Override + public void loadData(PlayerData data) { + provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + data.getUniqueId() + "';", (result) -> { + try { + MMOCore.sqlDebug("Loading data for: '" + data.getUniqueId() + "'..."); - // Initialize custom resources - if (!data.hasUsedTemporaryData()) { - data.setMana(data.getStats().getStat("MAX_MANA")); - data.setStamina(data.getStats().getStat("MAX_STAMINA")); - data.setStellium(data.getStats().getStat("MAX_STELLIUM")); - } + // Initialize custom resources + if (!data.hasUsedTemporaryData()) { + data.setMana(data.getStats().getStat("MAX_MANA")); + data.setStamina(data.getStats().getStat("MAX_STAMINA")); + data.setStellium(data.getStats().getStat("MAX_STELLIUM")); + } - if (!result.next()) { - data.setLevel(getDefaultData().getLevel()); - data.setClassPoints(getDefaultData().getClassPoints()); - data.setSkillPoints(getDefaultData().getSkillPoints()); - data.setAttributePoints(getDefaultData().getAttributePoints()); - data.setAttributeReallocationPoints(getDefaultData().getAttrReallocPoints()); - data.setExperience(0); - data.getQuestData().updateBossBar(); + if (!result.next()) { + data.setLevel(getDefaultData().getLevel()); + data.setClassPoints(getDefaultData().getClassPoints()); + data.setSkillPoints(getDefaultData().getSkillPoints()); + data.setAttributePoints(getDefaultData().getAttributePoints()); + data.setAttributeReallocationPoints(getDefaultData().getAttrReallocPoints()); + data.setExperience(0); + data.getQuestData().updateBossBar(); - data.setFullyLoaded(); - MMOCore.sqlDebug("Loaded DEFAULT data for: '" + data.getUniqueId() + "' as no saved data was found."); - return; - } + data.setFullyLoaded(); + MMOCore.sqlDebug("Loaded DEFAULT data for: '" + data.getUniqueId() + "' as no saved data was found."); + return; + } - data.setClassPoints(result.getInt("class_points")); - data.setSkillPoints(result.getInt("skill_points")); - data.setAttributePoints(result.getInt("attribute_points")); - data.setAttributeReallocationPoints(result.getInt("attribute_realloc_points")); - data.setLevel(result.getInt("level")); - data.setExperience(result.getInt("experience")); - if (!isEmpty(result.getString("class"))) - data.setClass(MMOCore.plugin.classManager.get(result.getString("class"))); + data.setClassPoints(result.getInt("class_points")); + data.setSkillPoints(result.getInt("skill_points")); + data.setAttributePoints(result.getInt("attribute_points")); + data.setAttributeReallocationPoints(result.getInt("attribute_realloc_points")); + data.setLevel(result.getInt("level")); + data.setExperience(result.getInt("experience")); + if (!isEmpty(result.getString("class"))) + data.setClass(MMOCore.plugin.classManager.get(result.getString("class"))); - if (!isEmpty(result.getString("times_claimed"))) { - JsonObject json = new JsonParser().parse(result.getString("times_claimed")).getAsJsonObject(); - json.entrySet().forEach(entry -> data.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt())); - } + if (!isEmpty(result.getString("times_claimed"))) { + JsonObject json = new JsonParser().parse(result.getString("times_claimed")).getAsJsonObject(); + json.entrySet().forEach(entry -> data.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt())); + } - if (!isEmpty(result.getString("guild"))) { - Guild guild = provider.getGuildManager().getGuild(result.getString("guild")); - data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null); - } - if (!isEmpty(result.getString("attributes"))) data.getAttributes().load(result.getString("attributes")); - if (!isEmpty(result.getString("professions"))) - data.getCollectionSkills().load(result.getString("professions")); - if (!isEmpty(result.getString("quests"))) data.getQuestData().load(result.getString("quests")); - data.getQuestData().updateBossBar(); - if (!isEmpty(result.getString("waypoints"))) - data.getWaypoints().addAll(getJSONArray(result.getString("waypoints"))); - if (!isEmpty(result.getString("friends"))) - getJSONArray(result.getString("friends")).forEach(str -> data.getFriends().add(UUID.fromString(str))); - if (!isEmpty(result.getString("skills"))) { - JsonObject object = MythicLib.plugin.getJson().parse(result.getString("skills"), JsonObject.class); - for (Entry entry : object.entrySet()) - data.setSkillLevel(entry.getKey(), entry.getValue().getAsInt()); - } - if (!isEmpty(result.getString("bound_skills"))) - for (String skill : getJSONArray(result.getString("bound_skills"))) - if (data.getProfess().hasSkill(skill)) - data.getBoundSkills().add(data.getProfess().getSkill(skill)); - if (!isEmpty(result.getString("class_info"))) { - JsonObject object = MythicLib.plugin.getJson().parse(result.getString("class_info"), JsonObject.class); - for (Entry entry : object.entrySet()) { - try { - PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey()); - Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'"); - data.applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject())); - } catch (IllegalArgumentException exception) { - MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage()); - } - } - } + if (!isEmpty(result.getString("guild"))) { + Guild guild = MMOCore.plugin.dataProvider.getGuildManager().getGuild(result.getString("guild")); + data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null); + } + if (!isEmpty(result.getString("attributes"))) data.getAttributes().load(result.getString("attributes")); + if (!isEmpty(result.getString("professions"))) + data.getCollectionSkills().load(result.getString("professions")); + if (!isEmpty(result.getString("quests"))) data.getQuestData().load(result.getString("quests")); + data.getQuestData().updateBossBar(); + if (!isEmpty(result.getString("waypoints"))) + data.getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints"))); + if (!isEmpty(result.getString("friends"))) + MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> data.getFriends().add(UUID.fromString(str))); + if (!isEmpty(result.getString("skills"))) { + JsonObject object = MythicLib.plugin.getJson().parse(result.getString("skills"), JsonObject.class); + for (Entry entry : object.entrySet()) + data.setSkillLevel(entry.getKey(), entry.getValue().getAsInt()); + } + if (!isEmpty(result.getString("bound_skills"))) + for (String skill : MMOCoreUtils.jsonArrayToList(result.getString("bound_skills"))) + if (data.getProfess().hasSkill(skill)) + data.getBoundSkills().add(data.getProfess().getSkill(skill)); + if (!isEmpty(result.getString("class_info"))) { + JsonObject object = MythicLib.plugin.getJson().parse(result.getString("class_info"), JsonObject.class); + for (Entry entry : object.entrySet()) { + try { + PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey()); + Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'"); + data.applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject())); + } catch (IllegalArgumentException exception) { + MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage()); + } + } + } - data.setFullyLoaded(); - MMOCore.sqlDebug("Loaded saved data for: '" + data.getUniqueId() + "'!"); - MMOCore.sqlDebug(String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); - } catch (SQLException e) { - e.printStackTrace(); - } - }); - } + //We now change the saved status to false because the data on SQL won't be the same as in the RAM + MySQLTableEditor sql = new MySQLTableEditor(Table.PLAYERDATA, data.getUniqueId()); - private boolean isEmpty(String s) { - return s == null || s.equalsIgnoreCase("null") || s.equalsIgnoreCase("{}") || s.equalsIgnoreCase("[]") || s.equalsIgnoreCase(""); - } - @Override - public void saveData(PlayerData data) { - MySQLTableEditor sql = new MySQLTableEditor(Table.PLAYERDATA, data.getUniqueId()); - MMOCore.sqlDebug("Saving data for: '" + data.getUniqueId() + "'..."); + data.setFullyLoaded(); + MMOCore.sqlDebug("Loaded saved data for: '" + data.getUniqueId() + "'!"); + MMOCore.sqlDebug(String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + } - sql.updateData("class_points", data.getClassPoints()); - sql.updateData("skill_points", data.getSkillPoints()); - sql.updateData("attribute_points", data.getAttributePoints()); - sql.updateData("attribute_realloc_points", data.getAttributeReallocationPoints()); - sql.updateData("level", data.getLevel()); - sql.updateData("experience", data.getExperience()); - sql.updateData("class", data.getProfess().getId()); - sql.updateData("last_login", data.getLastLogin()); - sql.updateData("guild", data.hasGuild() ? data.getGuild().getId() : null); + private boolean isEmpty(String s) { + return s == null || s.equalsIgnoreCase("null") || s.equalsIgnoreCase("{}") || s.equalsIgnoreCase("[]") || s.equalsIgnoreCase(""); + } - sql.updateJSONArray("waypoints", data.getWaypoints()); - sql.updateJSONArray("friends", data.getFriends().stream().map(UUID::toString).collect(Collectors.toList())); - sql.updateJSONArray("bound_skills", data.getBoundSkills().stream().map(skill -> skill.getSkill().getHandler().getId()).collect(Collectors.toList())); + @Override + public void saveData(PlayerData data) { - sql.updateJSONObject("skills", data.mapSkillLevels().entrySet()); - sql.updateJSONObject("times_claimed", data.getItemClaims().entrySet()); + if (MMOCore.plugin.hasBungee) { + //Initialize a connection with bungee using Sockets + try { + Socket socket=new Socket("localhost",25580); + BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + writer.write("BONJOUR"); + } catch (IOException e) { + throw new RuntimeException(e); + } - sql.updateData("attributes", data.getAttributes().toJsonString()); - sql.updateData("professions", data.getCollectionSkills().toJsonString()); - sql.updateData("quests", data.getQuestData().toJsonString()); - sql.updateData("class_info", createClassInfoData(data).toString()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DataOutputStream outStream = new DataOutputStream(out); + try { + outStream.writeChars(data.toJson()); + } catch (IOException e) { + MMOCore.plugin.getLogger().log(Level.SEVERE, "Couldn't send the data to Bungee for player " + data.getPlayer().getName()); + return; + } + MMOCore.plugin.getLogger().log(Level.WARNING, "BUNGEE"+ Bukkit.getOnlinePlayers().size()); - MMOCore.sqlDebug("Saved data for: " + data.getUniqueId()); - MMOCore.sqlDebug(String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); - } - private JsonObject createClassInfoData(PlayerData data) { - JsonObject json = new JsonObject(); - for (String c : data.getSavedClasses()) { - SavedClassInformation info = data.getClassInfo(c); - JsonObject classinfo = new JsonObject(); - classinfo.addProperty("level", info.getLevel()); - classinfo.addProperty("experience", info.getExperience()); - classinfo.addProperty("skill-points", info.getSkillPoints()); - classinfo.addProperty("attribute-points", info.getAttributePoints()); - classinfo.addProperty("attribute-realloc-points", info.getAttributeReallocationPoints()); - JsonObject skillinfo = new JsonObject(); - for (String skill : info.getSkillKeys()) - skillinfo.addProperty(skill, info.getSkillLevel(skill)); - classinfo.add("skill", skillinfo); - JsonObject attributeinfo = new JsonObject(); - for (String attribute : info.getAttributeKeys()) - attributeinfo.addProperty(attribute, info.getAttributeLevel(attribute)); - classinfo.add("attribute", attributeinfo); + MMOCore.sqlDebug("Sent data to bungee for: " + data.getUniqueId()); + MMOCore.sqlDebug(String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); - json.add(c, classinfo); - } - return json; - } + } else { + MySQLTableEditor sql = new MySQLTableEditor(MySQLTableEditor.Table.PLAYERDATA, data.getUniqueId()); + MMOCore.sqlDebug("Saving data for: '" + data.getUniqueId() + "'..."); - @NotNull - @Override - public OfflinePlayerData getOffline(UUID uuid) { - return isLoaded(uuid) ? get(uuid) : new MySQLOfflinePlayerData(uuid); - } + sql.updateData("class_points", data.getClassPoints()); + sql.updateData("skill_points", data.getSkillPoints()); + sql.updateData("attribute_points", data.getAttributePoints()); + sql.updateData("attribute_realloc_points", data.getAttributeReallocationPoints()); + sql.updateData("level", data.getLevel()); + sql.updateData("experience", data.getExperience()); + sql.updateData("class", data.getProfess().getId()); + sql.updateData("last_login", data.getLastLogin()); + sql.updateData("guild", data.hasGuild() ? data.getGuild().getId() : null); - private Collection getJSONArray(String json) { - return new ArrayList<>(Arrays.asList(MythicLib.plugin.getJson().parse(json, String[].class))); - } + sql.updateJSONArray("waypoints", data.getWaypoints()); + sql.updateJSONArray("friends", data.getFriends().stream().map(UUID::toString).collect(Collectors.toList())); + sql.updateJSONArray("bound_skills", data.getBoundSkills().stream().map(skill -> skill.getSkill().getHandler().getId()).collect(Collectors.toList())); - public class MySQLOfflinePlayerData extends OfflinePlayerData { - private int level; - private long lastLogin; - private PlayerClass profess; - private List friends; + sql.updateJSONObject("skills", data.mapSkillLevels().entrySet()); + sql.updateJSONObject("times_claimed", data.getItemClaims().entrySet()); - public MySQLOfflinePlayerData(UUID uuid) { - super(uuid); + sql.updateData("attributes", data.getAttributes().toJsonString()); + sql.updateData("professions", data.getCollectionSkills().toJsonString()); + sql.updateData("quests", data.getQuestData().toJsonString()); - provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> { - try { - MMOCore.sqlDebug("Loading OFFLINE data for '" + uuid + "'."); - if (!result.next()) { - level = 0; - lastLogin = 0; - profess = MMOCore.plugin.classManager.getDefaultClass(); - friends = new ArrayList<>(); - MMOCore.sqlDebug("Default OFFLINE data loaded."); - } else { - level = result.getInt("level"); - lastLogin = result.getLong("last_login"); - profess = isEmpty(result.getString("class")) ? MMOCore.plugin.classManager.getDefaultClass() : MMOCore.plugin.classManager.get(result.getString("class")); - if (!isEmpty(result.getString("friends"))) - getJSONArray(result.getString("friends")).forEach(str -> friends.add(UUID.fromString(str))); - else friends = new ArrayList<>(); - MMOCore.sqlDebug("Saved OFFLINE data loaded."); - } - } catch (SQLException e) { - e.printStackTrace(); - } - }); - } + sql.updateData("class_info", createClassInfoData(data).toString()); - @Override - public void removeFriend(UUID uuid) { - friends.remove(uuid); - new MySQLTableEditor(Table.PLAYERDATA, uuid).updateData("friends", friends.stream().map(UUID::toString).collect(Collectors.toList())); - } - @Override - public boolean hasFriend(UUID uuid) { - return friends.contains(uuid); - } + MMOCore.sqlDebug("Saved data for: " + data.getUniqueId()); + MMOCore.sqlDebug(String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); - @Override - public PlayerClass getProfess() { - return profess; - } - @Override - public int getLevel() { - return level; - } + } + } - @Override - public long getLastLogin() { - return lastLogin; - } - } + + @NotNull + @Override + public OfflinePlayerData getOffline(UUID uuid) { + return isLoaded(uuid) ? get(uuid) : new MySQLOfflinePlayerData(uuid); + } + + + public class MySQLOfflinePlayerData extends OfflinePlayerData { + private int level; + private long lastLogin; + private PlayerClass profess; + private List friends; + + public MySQLOfflinePlayerData(UUID uuid) { + super(uuid); + + provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> { + try { + MMOCore.sqlDebug("Loading OFFLINE data for '" + uuid + "'."); + if (!result.next()) { + level = 0; + lastLogin = 0; + profess = MMOCore.plugin.classManager.getDefaultClass(); + friends = new ArrayList<>(); + MMOCore.sqlDebug("Default OFFLINE data loaded."); + } else { + level = result.getInt("level"); + lastLogin = result.getLong("last_login"); + profess = isEmpty(result.getString("class")) ? MMOCore.plugin.classManager.getDefaultClass() : MMOCore.plugin.classManager.get(result.getString("class")); + if (!isEmpty(result.getString("friends"))) + MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> friends.add(UUID.fromString(str))); + else friends = new ArrayList<>(); + MMOCore.sqlDebug("Saved OFFLINE data loaded."); + } + } catch (SQLException e) { + e.printStackTrace(); + } + }); + } + + @Override + public void removeFriend(UUID uuid) { + friends.remove(uuid); + new MySQLTableEditor(Table.PLAYERDATA, uuid).updateData("friends", friends.stream().map(UUID::toString).collect(Collectors.toList())); + } + + @Override + public boolean hasFriend(UUID uuid) { + return friends.contains(uuid); + } + + @Override + public PlayerClass getProfess() { + return profess; + } + + @Override + public int getLevel() { + return level; + } + + @Override + public long getLastLogin() { + return lastLogin; + } + } } diff --git a/src/main/resources/bungee.yml b/src/main/resources/bungee.yml new file mode 100644 index 00000000..1495d76a --- /dev/null +++ b/src/main/resources/bungee.yml @@ -0,0 +1,3 @@ +name: MMOCore +main: net.Indyuce.mmocore.bungee.Bungee +author: Ka0rX