diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index ef4b9ef7..e884e2c2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -49,6 +49,7 @@ import net.Indyuce.mmocore.script.mechanic.ManaMechanic; import net.Indyuce.mmocore.script.mechanic.StaminaMechanic; import net.Indyuce.mmocore.script.mechanic.StelliumMechanic; import net.Indyuce.mmocore.skill.cast.SkillCastingMode; +import net.Indyuce.mmocore.spawnpoint.SpawnPoint; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -82,6 +83,8 @@ public class MMOCore extends JavaPlugin { public final SkillTreeManager skillTreeManager = new SkillTreeManager(); public final SpawnPointManager spawnPointManager = new SpawnPointManager(); + + public final PluginMessageManager pluginMessageManager = new PluginMessageManager(); public final StatManager statManager = new StatManager(); public final GuildDataManager nativeGuildManager = new YAMLGuildDataManager(); public final PlayerDataManager playerDataManager = new PlayerDataManager(this); @@ -183,6 +186,10 @@ public class MMOCore extends JavaPlugin { MMOCore.plugin.getLogger().log(Level.INFO, "Hooked onto MythicMobs"); } + //Registers plugin message channel to teleport players to other servers. + MMOCore.plugin.getServer().getMessenger().registerOutgoingPluginChannel(MMOCore.plugin, "BungeeCord"); + + /* * Resource regeneration. Must check if entity is dead otherwise regen * will make the 'respawn' button glitched plus HURT entity effect bug @@ -199,6 +206,21 @@ public class MMOCore extends JavaPlugin { } }.runTaskTimer(MMOCore.plugin, 100, 20); + + new BukkitRunnable() { + @Override + public void run() { + for (PlayerData playerData : PlayerData.getAll()) { + for (SpawnPoint spawnPoint : spawnPointManager.getAll()) { + if (!playerData.hasUnlocked(spawnPoint) && spawnPoint.matchesCondition(playerData)) { + playerData.unlock(spawnPoint); + } + } + } + } + }.runTaskTimer(this, 5*20L, 5 * 20L); + + /* * 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 @@ -331,6 +353,8 @@ public class MMOCore extends JavaPlugin { requestManager.initialize(clearBefore); soundManager.initialize(clearBefore); configItems.initialize(clearBefore); + spawnPointManager.initialize(clearBefore); + pluginMessageManager.initialize(clearBefore); //Needs to be loaded after the class manager. InventoryManager.load(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java index cc3fbc5a..97c1562c 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java @@ -12,9 +12,8 @@ import net.Indyuce.mmocore.experience.source.*; import net.Indyuce.mmocore.loot.chest.condition.*; import net.Indyuce.mmocore.loot.droptable.dropitem.*; import net.Indyuce.mmocore.spawnpoint.def.DefaultSpawnOption; -import net.Indyuce.mmocore.spawnpoint.def.GlobalSpawnOption; import net.Indyuce.mmocore.spawnpoint.def.LastSpawnOption; -import net.Indyuce.mmocore.spawnpoint.def.LocationSpawnOption; +import net.Indyuce.mmocore.spawnpoint.def.SpawnPointOption; import org.bukkit.configuration.ConfigurationSection; public class DefaultMMOLoader extends MMOLoader { @@ -211,12 +210,10 @@ public class DefaultMMOLoader extends MMOLoader { @Override public DefaultSpawnOption loadDefaultSpawnOption(MMOLineConfig config) { - if (config.getKey().equals("global")) - return new GlobalSpawnOption(); if (config.getKey().equals("last")) - return new LastSpawnOption(); - if (config.getKey().equals("location")) - return new LocationSpawnOption(config); + return new LastSpawnOption(config); + if (config.getKey().equals("spawnpoint")) + return new SpawnPointOption(config); return null; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index bb20021f..69c42d99 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -49,6 +49,7 @@ import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.SkillTreeStatus; import net.Indyuce.mmocore.skilltree.tree.SkillTree; +import net.Indyuce.mmocore.spawnpoint.SpawnPointContext; import net.Indyuce.mmocore.waypoint.Waypoint; import net.Indyuce.mmocore.waypoint.WaypointOption; import net.md_5.bungee.api.ChatMessageType; @@ -84,6 +85,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ private double health; private Guild guild; + + private SpawnPointContext lastSpawnPointContext; private SkillCastingInstance skillCasting; private final PlayerQuests questData; private final PlayerStats playerStats; @@ -128,6 +131,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ private final Map tableItemClaims = new HashMap<>(); + private boolean shouldTeleportWhenJoin; + // NON-FINAL player data stuff made public to facilitate field change public boolean noCooldown; @@ -191,6 +196,21 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD node.getExperienceTable().claimRemovableTrigger(this, node); } + /** + * This method is called when a player connects to a server and has shouldTeleportWhenJoin set to true. + * If the player is alive it means that he has been teleported to this server because of spawnpoints. + * If he is dead this will be done when he respawns. + */ + public void setupSpawnPoint() { + Validate.isTrue(MMOCore.plugin.spawnPointManager.isSpawnPoint(lastSpawnPointContext.getId())); + if (isOnline() && shouldTeleportWhenJoin && (lastSpawnPointContext.getServer().isEmpty() || + lastSpawnPointContext.getServer().get().equalsIgnoreCase(MMOCore.plugin.pluginMessageManager.getServerName())) + && !getPlayer().isDead()) { + MMOCore.plugin.spawnPointManager.getSpawnPoint(lastSpawnPointContext.getId()).whenRespawn(this); + shouldTeleportWhenJoin = false; + } + } + public int getPointSpent(SkillTree skillTree) { return pointSpent.getOrDefault(skillTree, 0); } @@ -351,7 +371,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD /** * @return If the item is unlocked by the player - * This is used for skills that can be locked & unlocked. + * This is used for skills that can be locked & unlocked. */ public boolean hasUnlocked(Unlockable unlockable) { return unlockable.isUnlockedByDefault() || unlockedItems.contains(unlockable.getUnlockNamespacedKey()); @@ -366,7 +386,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD Validate.isTrue(!unlockable.isUnlockedByDefault(), "Cannot unlock an item unlocked by default"); unlockable.whenUnlocked(this); final boolean wasLocked = unlockedItems.add(unlockable.getUnlockNamespacedKey()); - // Call the event synchronously + Bukkit.broadcastMessage("Unlocked " + unlockable.getUnlockNamespacedKey()); + // Call the event synchronously if (wasLocked) Bukkit.getScheduler().runTask(MythicLib.plugin, () -> Bukkit.getPluginManager().callEvent(new ItemUnlockedEvent(this, unlockable.getUnlockNamespacedKey()))); return wasLocked; @@ -454,6 +475,18 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD this.lastActivity.put(activity, timestamp); } + public SpawnPointContext getLastSpawnPointContext() { + return lastSpawnPointContext; + } + + public void setLastSpawnPointContext(SpawnPointContext lastSpawnPointContext) { + this.lastSpawnPointContext = lastSpawnPointContext; + } + + public void setShouldTeleportWhenJoin(boolean shouldTeleport) { + this.shouldTeleportWhenJoin = shouldTeleport; + } + @Override public long getLastLogin() { return getMMOPlayerData().getLastLogActivity(); @@ -1221,7 +1254,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD * checks if they could potentially upgrade to one of these * * @return If the player can change its current class to - * a subclass + * a subclass */ @Deprecated public boolean canChooseSubclass() { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java index 53738674..af787d8b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java @@ -1,8 +1,8 @@ package net.Indyuce.mmocore.api.player.attribute; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import io.lumine.mythic.lib.gson.Gson; +import io.lumine.mythic.lib.gson.JsonElement; +import io.lumine.mythic.lib.gson.JsonObject; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.player.modifier.Closeable; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java index 5ebece1d..d0844658 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java @@ -1,8 +1,8 @@ package net.Indyuce.mmocore.api.quest; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import io.lumine.mythic.lib.gson.Gson; +import io.lumine.mythic.lib.gson.JsonElement; +import io.lumine.mythic.lib.gson.JsonObject; import io.lumine.mythic.lib.util.Closeable; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java index 752ddea1..fa7a058a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java @@ -1,7 +1,7 @@ package net.Indyuce.mmocore.api.util; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import io.lumine.mythic.lib.gson.JsonArray; +import io.lumine.mythic.lib.gson.JsonObject; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.hologram.Hologram; import io.lumine.mythic.lib.version.VersionMaterial; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java index 18a444b3..dc337c02 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java @@ -30,6 +30,7 @@ public class AdminCommandTreeNode extends CommandTreeNode { addChild(new PointsCommandTreeNode("skill-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints)); addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints)); addChild(new SkillTreePointsCommandTreeNode(this, (playerData, integer, s) -> playerData.setSkillTreePoints(s, integer), (playerData, integer, s) -> playerData.giveSkillTreePoints(s, integer), ((playerData, s) -> playerData.getSkillTreePoint(s)))); + addChild(new SpawnPointCommandTreeNode(this)); for (PlayerResource res : PlayerResource.values()) addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res)); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java index 76dfe6d5..400fce91 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java @@ -34,7 +34,7 @@ public class MMOCoreProfileDataModule implements ProfileDataModule, Listener { @Override public void processPlaceholderRequest(PlaceholderRequest placeholderRequest) { final PlayerData fictiveData = new PlayerData(new MMOPlayerData(placeholderRequest.getProfile().getUniqueId())); - MMOCore.plugin.playerDataManager.getDataHandler().loadData(fictiveData).thenRun(() -> { + MMOCore.plugin.playerDataManager.loadData(fictiveData).thenRun(() -> { placeholderRequest.addPlaceholder("class", fictiveData.getProfess().getName()); placeholderRequest.addPlaceholder("level", fictiveData.getLevel()); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java index d442c0c4..a2467572 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java @@ -1,10 +1,10 @@ package net.Indyuce.mmocore.experience; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.gson.Gson; +import io.lumine.mythic.lib.gson.JsonElement; +import io.lumine.mythic.lib.gson.JsonObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.SoundEvent; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index 14a5ccf7..f77e8418 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -104,6 +104,7 @@ public class ConfigManager { loadDefaultFile("triggers.yml"); loadDefaultFile("conditions.yml"); loadDefaultFile("guilds.yml"); + loadDefaultFile("spawn-points.yml"); final ConfigurationSection config = MMOCore.plugin.getConfig(); commandVerbose.reload(MMOCore.plugin.getConfig().getConfigurationSection("command-verbose")); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java index 4c546ac2..fe41ca57 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java @@ -1,6 +1,6 @@ package net.Indyuce.mmocore.manager; -import com.google.gson.JsonParseException; +import io.lumine.mythic.lib.gson.JsonParseException; import io.lumine.mythic.lib.api.MMOLineConfig; import net.Indyuce.mmocore.experience.source.type.ExperienceSource; import net.Indyuce.mmocore.api.block.BlockType; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SpawnPointManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SpawnPointManager.java index d9518824..241c47cd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SpawnPointManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SpawnPointManager.java @@ -1,55 +1,54 @@ package net.Indyuce.mmocore.manager; -import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.util.ConfigFile; -import io.lumine.mythic.lib.util.configobject.ConfigSectionObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.spawnpoint.SpawnPoint; import net.Indyuce.mmocore.spawnpoint.def.DefaultSpawnOption; -import org.bukkit.Location; -import org.bukkit.World; +import org.apache.commons.lang.Validate; import org.bukkit.configuration.file.FileConfiguration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.logging.Level; public class SpawnPointManager implements MMOCoreManager { - /** - * Ordered by world for faster access time. - */ - private final Map> spawnPoints = new HashMap<>(); - private Location globalSpawn; + private final Map spawnPoints = new HashMap<>(); private List defaultSpawnOptions = new ArrayList<>(); - public List getSpawnPoints(World world) { - return spawnPoints.getOrDefault(world, new ArrayList<>()); + public SpawnPoint getSpawnPoint(String id) { + return spawnPoints.get(id); + } + + public boolean isSpawnPoint(String id) { + return spawnPoints.containsKey(id); + } + + public Collection getAll() { + return spawnPoints.values(); } @Override public void initialize(boolean clearBefore) { FileConfiguration config = new ConfigFile(MMOCore.plugin, "", "spawn-points").getConfig(); + Validate.isTrue(config.isConfigurationSection("spawn-points.default"), "You must specify a default spawn-point."); if (config.isConfigurationSection("spawn-points")) for (String key : config.getConfigurationSection("spawn-points").getKeys(false)) { - SpawnPoint spawnPoint = new SpawnPoint(config.getConfigurationSection("spawn-points." + key)); - spawnPoints.putIfAbsent(spawnPoint.getLocation().getWorld(), new ArrayList<>()); - spawnPoints.get(spawnPoint.getLocation().getWorld()).add(spawnPoint); + try{ + SpawnPoint spawnPoint = new SpawnPoint(config.getConfigurationSection("spawn-points." + key)); + spawnPoints.put(spawnPoint.getId(), spawnPoint); + }catch (Exception e){ + MMOCore.log(Level.WARNING,"An error occured while loading spawnpoint " + key + ": " + e.getMessage()); + } + } - globalSpawn = UtilityMethods.readLocation(new ConfigSectionObject(config.getConfigurationSection("global-spawn"))); for (String defaultSpawnOption : config.getStringList("default-spawn")) { defaultSpawnOptions.add(MMOCore.plugin.loadManager.loadDefaultSpawnOption(new MMOLineConfig(defaultSpawnOption))); } } - public Location getGlobalSpawn() { - return globalSpawn; - } - public List getDefaultSpawnOptions() { return new ArrayList(defaultSpawnOptions); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java index 30736a42..e0154b61 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/MMOCoreDataSynchronizer.java @@ -6,6 +6,8 @@ import io.lumine.mythic.lib.data.sql.SQLDataSynchronizer; import io.lumine.mythic.lib.gson.JsonArray; import io.lumine.mythic.lib.gson.JsonElement; import io.lumine.mythic.lib.gson.JsonObject; +import io.lumine.mythic.lib.gson.JsonParser; + import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.profess.PlayerClass; @@ -15,6 +17,7 @@ import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.tree.SkillTree; +import net.Indyuce.mmocore.spawnpoint.SpawnPointContext; import org.apache.commons.lang.Validate; import org.bukkit.attribute.Attribute; import org.jetbrains.annotations.Nullable; @@ -89,6 +92,11 @@ public class MMOCoreDataSynchronizer extends SQLDataSynchronizer { getData().getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints"))); if (!isEmpty(result.getString("friends"))) MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> getData().getFriends().add(UUID.fromString(str))); + if (!isEmpty(result.getString("last_spawn_point"))) + getData().setLastSpawnPointContext(new SpawnPointContext(new JsonParser().parseString(result.getString("last_spawn_point")).getAsJsonObject())); + getData().setShouldTeleportWhenJoin(result.getBoolean("should_teleport_when_join")); + getData().setupSpawnPoint(); + if (!isEmpty(result.getString("skills"))) { JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("skills"), JsonObject.class); for (Map.Entry entry : object.entrySet()) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java index 2b744abb..12b778ea 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java @@ -1,7 +1,7 @@ package net.Indyuce.mmocore.manager.data.sql; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import io.lumine.mythic.lib.gson.JsonArray; +import io.lumine.mythic.lib.gson.JsonObject; import io.lumine.mythic.lib.data.sql.SQLDataSource; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java index dd621ce4..af7e12cf 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java @@ -1,24 +1,22 @@ package net.Indyuce.mmocore.manager.data.sql; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import io.lumine.mythic.lib.gson.JsonArray; +import io.lumine.mythic.lib.gson.JsonObject; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.data.sql.SQLDataSource; import io.lumine.mythic.lib.data.sql.SQLSynchronizedDataHandler; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.manager.data.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.manager.data.OfflinePlayerData; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.sql.SQLException; -import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -public class SQLDataHandler extends SQLSynchronizedDataHandler { +public class SQLDataHandler extends SQLSynchronizedDataHandler { public SQLDataHandler(SQLDataSource dataSource) { super(dataSource); } @@ -34,7 +32,9 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler config.set("bound-skills." + slot, skill)); + MMOCore.log(data.getUnlockedItems().size()+" unlocked."); config.set("unlocked-items", data.getUnlockedItems().stream().collect(Collectors.toList())); config.set("attribute", null); config.createSection("attribute"); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java index 70ba571e..90eeeed0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java @@ -12,7 +12,7 @@ public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, Skil SkillTreeStatus toStatus = playerData.getNodeStatus(to); if (fromStatus == SkillTreeStatus.UNLOCKED && toStatus == SkillTreeStatus.UNLOCKED) return PathStatus.UNLOCKED; - if ((fromStatus == SkillTreeStatus.UNLOCKABLE && toStatus == SkillTreeStatus.LOCKED) || (fromStatus == SkillTreeStatus.LOCKED && toStatus == SkillTreeStatus.UNLOCKABLE)) + if ((fromStatus == SkillTreeStatus.UNLOCKABLE && toStatus == SkillTreeStatus.UNLOCKED) || (fromStatus == SkillTreeStatus.UNLOCKED && toStatus == SkillTreeStatus.UNLOCKABLE)) return PathStatus.UNLOCKABLE; if (fromStatus == SkillTreeStatus.FULLY_LOCKED || toStatus == SkillTreeStatus.FULLY_LOCKED) return PathStatus.FULLY_LOCKED; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnPoint.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnPoint.java index 52bb3f39..a05afbd2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnPoint.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnPoint.java @@ -1,12 +1,14 @@ package net.Indyuce.mmocore.spawnpoint; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.player.PlayerMetadata; import io.lumine.mythic.lib.script.Script; import io.lumine.mythic.lib.script.condition.Condition; import io.lumine.mythic.lib.skill.SimpleSkill; import io.lumine.mythic.lib.skill.Skill; +import io.lumine.mythic.lib.skill.SkillMetadata; import io.lumine.mythic.lib.skill.handler.MythicLibSkillHandler; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; import io.lumine.mythic.lib.skill.trigger.TriggerType; @@ -14,41 +16,53 @@ import io.lumine.mythic.lib.util.configobject.ConfigSectionObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.player.Unlockable; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import java.util.Optional; import java.util.logging.Level; -public class SpawnPoint implements Unlockable, SpawnProvider { +public class SpawnPoint implements Unlockable { private final String id; - Location location; - Condition unlockCondition; - double strength; + private final Location location; + private final Condition unlockCondition; + private final double strength; - private Optional unlockScript; - private Optional respawnScript; + private final Optional unlockScript; + private final Optional respawnScript; public SpawnPoint(ConfigurationSection section) { id = section.getName(); - location = new Location(MMOCore.plugin.getServer().getWorld(section.getString("world")), section.getDouble("x"), section.getDouble("y"), section.getDouble("z")); + location = UtilityMethods.readLocation(new ConfigSectionObject(section.getConfigurationSection("location"))); + Validate.isTrue(section.isConfigurationSection("unlock-condition"), "You must specify an unlock condition."); unlockCondition = MythicLib.plugin.getSkills().loadCondition( new ConfigSectionObject(section.getConfigurationSection("unlock-condition"))); - strength = section.getDouble("strength"); - if (section.isConfigurationSection("script.unlock")) + + strength = section.getDouble("strength", 1); + Skill unlockScript = null; + if (section.isConfigurationSection("unlock-script")) try { - final Script script = MythicLib.plugin.getSkills().loadScript(section.getConfigurationSection("script.unlock")); - unlockScript = Optional.of(new SimpleSkill(TriggerType.CAST, new MythicLibSkillHandler(script))); + final Script script = MythicLib.plugin.getSkills().loadScript(section.getConfigurationSection("unlock-script")); + unlockScript = new SimpleSkill(TriggerType.CAST, new MythicLibSkillHandler(script)); } catch (RuntimeException exception) { MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load unlock script: " + exception.getMessage()); } - if (section.isConfigurationSection("script.respawn")) + this.unlockScript = Optional.ofNullable(unlockScript); + Skill respawnScript = null; + if (section.isConfigurationSection("respawn-script")) try { - final Script script = MythicLib.plugin.getSkills().loadScript(section.getConfigurationSection("script.respawn")); - respawnScript = Optional.of(new SimpleSkill(TriggerType.CAST, new MythicLibSkillHandler(script))); + final Script script = MythicLib.plugin.getSkills().loadScript(section.getConfigurationSection("respawn-script")); + respawnScript = new SimpleSkill(TriggerType.CAST, new MythicLibSkillHandler(script)); } catch (RuntimeException exception) { MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load respawn script: " + exception.getMessage()); } + this.respawnScript = Optional.ofNullable(respawnScript); + } + + public String getId() { + return id; } public Location getLocation() { @@ -75,19 +89,16 @@ public class SpawnPoint implements Unlockable, SpawnProvider { @Override public void whenUnlocked(PlayerData playerData) { - PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.OTHER); + PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND); unlockScript.ifPresent(skill -> skill.cast(new TriggerMetadata(caster))); } - public void whenRespawn(PlayerData playerData) { - + public boolean matchesCondition(PlayerData playerData) { + return unlockCondition.isMet(new SkillMetadata(null, playerData.getMMOPlayerData())); } - //TODO: Support BungeeCord. Point compliqué car il faut executer le script sur le serveur dans lequel le joueur va etre tp. - @Override - public void respawn(PlayerData playerData) { - playerData.getPlayer().teleport(location); - PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.OTHER); + public void whenRespawn(PlayerData playerData) { + PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND); respawnScript.ifPresent(skill -> skill.cast(new TriggerMetadata(caster))); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnProvider.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnProvider.java deleted file mode 100644 index 12b2bafd..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/SpawnProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.Indyuce.mmocore.spawnpoint; - -import net.Indyuce.mmocore.api.player.PlayerData; - -public interface SpawnProvider { - void respawn(PlayerData playerData); -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/DefaultSpawnOption.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/DefaultSpawnOption.java index 009bcf06..b7237f13 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/DefaultSpawnOption.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/DefaultSpawnOption.java @@ -2,7 +2,8 @@ package net.Indyuce.mmocore.spawnpoint.def; import io.lumine.mythic.lib.api.MMOLineConfig; import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.Location; +import net.Indyuce.mmocore.spawnpoint.SpawnPoint; +import net.Indyuce.mmocore.spawnpoint.SpawnPointContext; import org.bukkit.World; import java.util.regex.Matcher; @@ -12,6 +13,10 @@ public abstract class DefaultSpawnOption { protected final String worldExpression; + public DefaultSpawnOption() { + this.worldExpression = "true"; + } + public DefaultSpawnOption(MMOLineConfig config) { this.worldExpression = config.getString("world-expression"); } @@ -23,8 +28,6 @@ public abstract class DefaultSpawnOption { return matcher.matches(); } - public abstract Location getSpawnLocation(PlayerData playerData); - - public abstract void whenRespawn(PlayerData playerData); + public abstract SpawnPointContext getSpawnPointContext(PlayerData playerData); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/GlobalSpawnOption.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/GlobalSpawnOption.java deleted file mode 100644 index 1f2791b6..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/GlobalSpawnOption.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.Indyuce.mmocore.spawnpoint.def; - -import io.lumine.mythic.lib.api.MMOLineConfig; -import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.Location; - -public class GlobalSpawnOption extends DefaultSpawnOption { - - public GlobalSpawnOption(MMOLineConfig config) { - super(config); - } - - @Override - public Location getSpawnLocation(PlayerData playerData) { - return MMOCore.plugin.spawnPointManager.getGlobalSpawn(); - } - - @Override - public void whenRespawn() { - - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LastSpawnOption.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LastSpawnOption.java index 4dc429c4..d6e6cf3d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LastSpawnOption.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LastSpawnOption.java @@ -1,24 +1,19 @@ package net.Indyuce.mmocore.spawnpoint.def; import io.lumine.mythic.lib.api.MMOLineConfig; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.Location; +import net.Indyuce.mmocore.spawnpoint.SpawnPointContext; -public class LastSpawnOption extends DefaultSpawnOption -{ +public class LastSpawnOption extends DefaultSpawnOption { public LastSpawnOption(MMOLineConfig config) { super(config); } - //TODO @Override - public Location getSpawnLocation(PlayerData playerData) { - return null; + public SpawnPointContext getSpawnPointContext(PlayerData playerData) { + return playerData.getLastSpawnPointContext(); } - @Override - public void whenRespawn(PlayerData playerData) { - - } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LocationSpawnOption.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LocationSpawnOption.java deleted file mode 100644 index 9fd961ac..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/spawnpoint/def/LocationSpawnOption.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.Indyuce.mmocore.spawnpoint.def; - -import io.lumine.mythic.lib.api.MMOLineConfig; -import io.lumine.mythic.lib.util.configobject.ConfigObject; -import net.Indyuce.mmocore.api.player.PlayerData; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; - -import javax.swing.text.html.Option; -import java.util.Optional; - -public class LocationSpawnOption extends DefaultSpawnOption { - private final double x, y, z; - private final Optional world; - - public LocationSpawnOption(MMOLineConfig config) { - super(config); - this.x = config.getDouble("spawn-x"); - this.y = config.getDouble("spawn-y"); - this.z = config.getDouble("spawn-z"); - this.world = Optional.ofNullable(Bukkit.getWorld(config.getString("spawn-world"))); - } - - @Override - public Location getSpawnLocation(PlayerData playerData) { - return new Location(world.orElseGet(() -> playerData.getPlayer().getWorld()), x, y, z); - } - - @Override - public void whenRespawn(PlayerData playerData) { - - } -} diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java index abad1ecb..18774b27 100644 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java @@ -45,6 +45,7 @@ public class MMOCoreBukkit { Bukkit.getPluginManager().registerEvents(new FishingListener(), plugin); Bukkit.getPluginManager().registerEvents(new PlayerCollectStats(), plugin); Bukkit.getPluginManager().registerEvents(new PlayerPressKeyListener(), plugin); + Bukkit.getPluginManager().registerEvents(new SpawnPointsListener(), plugin); // Bukkit.getPluginManager().registerEvents(new ClassTriggers(), plugin); } } diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/SpawnPointsListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/SpawnPointsListener.java index 5ef1037c..69cc056d 100644 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/SpawnPointsListener.java +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/SpawnPointsListener.java @@ -3,33 +3,63 @@ package net.Indyuce.mmocore.listener; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.spawnpoint.SpawnPoint; +import net.Indyuce.mmocore.spawnpoint.SpawnPointContext; import net.Indyuce.mmocore.spawnpoint.def.DefaultSpawnOption; +import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import java.util.List; +import java.util.Optional; public class SpawnPointsListener implements Listener { @EventHandler public void onTeleport(PlayerTeleportEvent event) { - event.getFrom() + if (!event.getFrom().getWorld().equals(event.getTo().getWorld())) { + PlayerData playerData = PlayerData.get(event.getPlayer()); + getLastSpawnPointContext(playerData).ifPresent(playerData::setLastSpawnPointContext); + } } @EventHandler public void onDeath(PlayerDeathEvent event) { - //TODO Only when module enabled PlayerData playerData = PlayerData.get(event.getEntity()); + //TODO: Only when module enabled + Optional context = getLastSpawnPointContext(playerData); + if (context.isPresent()) { + SpawnPointContext spawnPointContext = context.get(); + playerData.setLastSpawnPointContext(spawnPointContext); + } + } + + @EventHandler + public void onSpawn(PlayerRespawnEvent event) { + PlayerData playerData = PlayerData.get(event.getPlayer()); + Optional context = getLastSpawnPointContext(playerData); + if (context.isPresent()) { + SpawnPointContext spawnPointContext = context.get(); + if (!spawnPointContext.isOtherServer()){ + event.setRespawnLocation(spawnPointContext.getLocation()); + } + + spawnPointContext.whenRespawn(playerData); + } + } + + public Optional getLastSpawnPointContext(PlayerData playerData) { World world = playerData.getPlayer().getWorld(); List reachableSpawnPoints = MMOCore.plugin.spawnPointManager. - getSpawnPoints(world) + getAll() .stream() - .filter(spawnPoint -> playerData.hasUnlocked(spawnPoint)) + .filter(spawnPoint -> spawnPoint.getLocation().getWorld().equals(world) && playerData.hasUnlocked(spawnPoint)) .toList(); if (!reachableSpawnPoints.isEmpty()) { + double minDistance = Double.MAX_VALUE; SpawnPoint closestSpawnPoint = null; for (SpawnPoint spawnPoint : reachableSpawnPoints) { @@ -40,14 +70,12 @@ public class SpawnPointsListener implements Listener { closestSpawnPoint = spawnPoint; } } - playerData.getPlayer().teleport(closestSpawnPoint.getLocation()); - closestSpawnPoint.whenRespawn(playerData); + return Optional.of(new SpawnPointContext(closestSpawnPoint.getId())); } else for (DefaultSpawnOption defaultSpawnOption : MMOCore.plugin.spawnPointManager.getDefaultSpawnOptions()) if (defaultSpawnOption.matches(world)) { - playerData.getPlayer().teleport(defaultSpawnOption.getSpawnLocation(playerData)); - defaultSpawnOption.whenRespawn(); - return; + return Optional.of(defaultSpawnOption.getSpawnPointContext(playerData)); } + return Optional.empty(); } }