From 9bd830efb7ecce96429acbe7f9426c9cb1885dd2 Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 21 Feb 2023 14:29:15 +0100 Subject: [PATCH 01/30] Fixed pvp mode --- .../Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java index 833735fb..ed7bdf30 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java @@ -18,7 +18,7 @@ public class PvPModeListener implements Listener { @EventHandler(ignoreCancelled = true) public void unblockPvp(DisallowedPVPEvent event) { PlayerData defender; - if (PlayerData.get(event.getAttacker()).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode()) + if (!PlayerData.get(event.getAttacker()).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode()) return; if (!defender.getCombat().canQuitPvpMode() || From 07a61b900ef2042ca3395d189884aa990df13780 Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 21 Feb 2023 14:56:25 +0100 Subject: [PATCH 02/30] Added invulnerability when using /pvpmode inside of region --- .../net/Indyuce/mmocore/command/PvpModeCommand.java | 13 ++++++++++++- .../mmocore/comp/region/pvpmode/PvPModeHandler.java | 8 ++++---- .../src/main/resources/default/messages.yml | 10 ++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java index 7cc99d7a..a0394d95 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java @@ -1,6 +1,7 @@ package net.Indyuce.mmocore.command; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.comp.flags.CustomFlag; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.command.api.RegisteredCommand; @@ -39,7 +40,17 @@ public class PvpModeCommand extends RegisteredCommand { playerData.getCombat().setPvpMode(!playerData.getCombat().isInPvpMode()); playerData.getCooldownMap().applyCooldown(COOLDOWN_KEY, playerData.getCombat().isInPvpMode() ? MMOCore.plugin.configManager.pvpModeToggleOnCooldown : MMOCore.plugin.configManager.pvpModeToggleOffCooldown); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle-" + (playerData.getCombat().isInPvpMode() ? "on" : "off")).send((Player) sender); + + // Toggling on when in PVP region + if (playerData.getCombat().isInPvpMode() && + MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) { + playerData.getCombat().applyInvulnerability(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle.on-invulnerable", "time", + MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); + + // Just send message otherwise + } else + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off")).send((Player) sender); return true; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java index 60bdb26f..d0620a24 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java @@ -82,8 +82,8 @@ public class PvPModeHandler extends FlagValueChangeHandler { final String msgPath = (playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode()) ? "allowed" : "denied"; lastMessage = System.currentTimeMillis(); final double remaining = (playerData.getCombat().getLastHit() + MMOCore.plugin.configManager.pvpModeCombatTimeout * 1000.0D - System.currentTimeMillis()) / 1000.0D; - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + msgPath, new String[]{"remaining", - (MythicLib.plugin.getMMOConfig()).decimal.format(remaining)}).send(playerData.getPlayer()); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + msgPath, "remaining", + (MythicLib.plugin.getMMOConfig()).decimal.format(remaining)).send(playerData.getPlayer()); } } else if (newPvpMode && !lastPvpMode) { @@ -95,8 +95,8 @@ public class PvPModeHandler extends FlagValueChangeHandler { // Send message if (canSendMessage()) { lastMessage = System.currentTimeMillis(); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-" + (applyInvulnerability ? "on" : "off"), new String[]{"time", - (MythicLib.plugin.getMMOConfig()).decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)}).send(playerData.getPlayer()); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-" + (applyInvulnerability ? "on" : "off"), "time", + MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); } } return true; diff --git a/MMOCore-Dist/src/main/resources/default/messages.yml b/MMOCore-Dist/src/main/resources/default/messages.yml index d79602a4..e6ec39c2 100644 --- a/MMOCore-Dist/src/main/resources/default/messages.yml +++ b/MMOCore-Dist/src/main/resources/default/messages.yml @@ -32,8 +32,14 @@ booster-expired: '&cExpired!' # PvP Mode pvp-mode: cooldown: '&cPlease wait {remaining} seconds to use this command again.' - toggle-on: '&aPvP Mode on.' - toggle-off: '&cPvP Mode off.' + + # When using /pvpmode + toggle: + on: '&aPvP Mode on.' + on-invulnerable: '&aPvP Mode on. You are now invulnerable for {time} seconds.' + off: '&cPvP Mode off.' + + # Entering/leaving regions with specific flag value leave: pvp-allowed: '&cYou left a PVP zone but are still vulnerable for {remaining} seconds!' pvp-denied: '&cYou left the PVP zone.' From b44283abcb7ee4ec0693e62341087306ee356855 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Tue, 21 Feb 2023 21:23:09 +0100 Subject: [PATCH 03/30] Bug Fixing for Skill Trees. --- .../mmocore/api/quest/trigger/StatTrigger.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java index fd9d59d4..6e345170 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java @@ -9,10 +9,10 @@ import org.apache.commons.lang.Validate; import java.util.UUID; public class StatTrigger extends Trigger { + private final StatModifier statModifier; private final String stat; - private final double amount; - private final ModifierType type; private final String modifierKey = "mmocore_trigger." + UUID.randomUUID(); + private final double amount; public StatTrigger(MMOLineConfig config) { super(config); @@ -24,12 +24,16 @@ public class StatTrigger extends Trigger { Validate.isTrue(type.equals("FLAT") || type.equals("RELATIVE")); stat = config.getString("stat"); amount = config.getDouble("amount"); - this.type = ModifierType.valueOf(type); + statModifier = new StatModifier(modifierKey, stat, amount, ModifierType.valueOf(type)); } @Override public void apply(PlayerData player) { - new StatModifier(modifierKey, stat, amount, type).register(player.getMMOPlayerData()); + StatModifier prevModifier = player.getMMOPlayerData().getStatMap().getInstance(stat).getModifier(modifierKey); + if (prevModifier == null) + statModifier.register(player.getMMOPlayerData()); + else + prevModifier.add(amount).register(player.getMMOPlayerData()); } /** From b37c461092741ec4046c564785132641e0af108e Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Tue, 21 Feb 2023 22:02:50 +0100 Subject: [PATCH 04/30] Fixed prefix bug for stat triggers. --- .../main/java/net/Indyuce/mmocore/api/player/PlayerData.java | 3 ++- .../net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 42535d30..3154ed8f 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 @@ -21,6 +21,7 @@ import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.quest.PlayerQuests; +import net.Indyuce.mmocore.api.quest.trigger.StatTrigger; import net.Indyuce.mmocore.api.util.Closable; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.experience.EXPSource; @@ -145,7 +146,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc // Used to see if the triggers need to be applied for (StatInstance instance : mmoData.getStatMap().getInstances()) for (StatModifier modifier : instance.getModifiers()) - if (modifier.getKey().startsWith("trigger")) { + if (modifier.getKey().startsWith(StatTrigger.TRIGGER_PREFIX)) { statsLoaded = true; break; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java index 6e345170..4a77bdbf 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java @@ -9,9 +9,10 @@ import org.apache.commons.lang.Validate; import java.util.UUID; public class StatTrigger extends Trigger { + public static String TRIGGER_PREFIX = "mmocore_trigger"; private final StatModifier statModifier; private final String stat; - private final String modifierKey = "mmocore_trigger." + UUID.randomUUID(); + private final String modifierKey = TRIGGER_PREFIX + "." + UUID.randomUUID(); private final double amount; public StatTrigger(MMOLineConfig config) { From cebbfcf5c876bfdca06d8425e2a4d8e87cfbdea5 Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 17:33:22 +0100 Subject: [PATCH 05/30] New options for combat mode --- .../mmocore/command/PvpModeCommand.java | 2 +- .../comp/region/pvpmode/PvPModeHandler.java | 9 ++++++- .../comp/region/pvpmode/PvPModeListener.java | 25 ++++++++++++----- .../mmocore/manager/ConfigManager.java | 10 ++++--- .../Indyuce/mmocore/player/CombatHandler.java | 19 ++++++------- MMOCore-Dist/src/main/resources/config.yml | 27 ++++++++++++++++--- 6 files changed, 68 insertions(+), 24 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java index a0394d95..44cb6c3b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java @@ -44,7 +44,7 @@ public class PvpModeCommand extends RegisteredCommand { // Toggling on when in PVP region if (playerData.getCombat().isInPvpMode() && MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) { - playerData.getCombat().applyInvulnerability(); + playerData.getCombat().preventPvp(); MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle.on-invulnerable", "time", MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java index d0620a24..f5c36407 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java @@ -13,6 +13,7 @@ import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.comp.flags.WorldGuardFlags; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.command.PvpModeCommand; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -77,6 +78,9 @@ public class PvPModeHandler extends FlagValueChangeHandler { if (!newPvpMode && lastPvpMode) { + // Apply cooldown + playerData.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionLeaveCooldown); + // Send message if (canSendMessage()) { final String msgPath = (playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode()) ? "allowed" : "denied"; @@ -87,10 +91,13 @@ public class PvPModeHandler extends FlagValueChangeHandler { } } else if (newPvpMode && !lastPvpMode) { + // Apply cooldown + playerData.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionEnterCooldown); + // Apply invulnerability final boolean applyInvulnerability = playerData.getCombat().isInPvpMode() && playerData.getCombat().canQuitPvpMode(); if (applyInvulnerability) - playerData.getCombat().applyInvulnerability(); + playerData.getCombat().preventPvp(); // Send message if (canSendMessage()) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java index ed7bdf30..497e291f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java @@ -5,6 +5,7 @@ import com.sk89q.worldguard.bukkit.protection.events.DisallowedPVPEvent; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.comp.interaction.InteractionType; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import org.apache.commons.lang.Validate; import org.bukkit.event.EventHandler; @@ -17,13 +18,25 @@ public class PvPModeListener implements Listener { @EventHandler(ignoreCancelled = true) public void unblockPvp(DisallowedPVPEvent event) { - PlayerData defender; - if (!PlayerData.get(event.getAttacker()).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode()) + PlayerData defender, attacker; + if (!(attacker = PlayerData.get(event.getAttacker())).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode()) return; - if (!defender.getCombat().canQuitPvpMode() || - (!defender.getCombat().isInvulnerable() && MythicLib.plugin.getFlags().isFlagAllowed(event.getDefender().getLocation(), CustomFlag.PVP_MODE))) - if (MythicLib.plugin.getEntities().checkPvpInteractionRules(event.getAttacker(), event.getDefender(), InteractionType.OFFENSE_ACTION, true)) - event.setCancelled(true); + // If defender is out of combat + if (!defender.getCombat().canPvp()) + return; + + // If attacker cannot deal damage yet + if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && !attacker.getCombat().canPvp()) + return; + + // Defender is still fighting and cannot leave PvP mode + if (!defender.getCombat().canQuitPvpMode()) + event.setCancelled(true); + + // Enable PvP if accepted + else if (MythicLib.plugin.getFlags().isFlagAllowed(event.getDefender().getLocation(), CustomFlag.PVP_MODE) && + MythicLib.plugin.getEntities().checkPvpInteractionRules(event.getAttacker(), event.getDefender(), InteractionType.OFFENSE_ACTION, true)) + event.setCancelled(true); } } 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 545cb98d..9e8858d4 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 @@ -27,11 +27,12 @@ import java.util.logging.Level; public class ConfigManager { public final CommandVerbose commandVerbose = new CommandVerbose(); - public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar, pvpModeEnabled; + public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar, pvpModeEnabled, pvpModeInvulnerabilityCanDamage; public String partyChatPrefix, noSkillBoundPlaceholder; public ChatColor staminaFull, staminaHalf, staminaEmpty; public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; - public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, pvpModeCombatTimeout, pvpModeInvulnerability; + public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, pvpModeCombatTimeout, pvpModeInvulnerability, + pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown; public int maxPartyLevelDifference, maxBoundActiveSkills, maxBoundPassiveSkills; public final List combatLogDamageCauses = new ArrayList<>(); @@ -136,8 +137,11 @@ public class ConfigManager { pvpModeToggleOnCooldown = config.getDouble("pvp_mode.cooldown.toggle_on"); pvpModeToggleOffCooldown = config.getDouble("pvp_mode.cooldown.toggle_off"); pvpModeCombatCooldown = config.getDouble("pvp_mode.cooldown.combat"); + pvpModeRegionEnterCooldown = config.getDouble("pvp_mode.cooldown.region_enter"); + pvpModeRegionLeaveCooldown = config.getDouble("pvp_mode.cooldown.region_leave"); pvpModeCombatTimeout = config.getDouble("pvp_mode.combat_timeout"); - pvpModeInvulnerability = config.getDouble("pvp_mode.invulnerability"); + pvpModeInvulnerability = config.getDouble("pvp_mode.invulnerability.time"); + pvpModeInvulnerabilityCanDamage = config.getBoolean("pvp_mode.invulnerability.can_damage"); // Resources staminaFull = getColorOrDefault("stamina-whole", ChatColor.GREEN); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java index 8a7b65ac..2879ff46 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java @@ -14,8 +14,7 @@ public class CombatHandler implements Closable { private final PlayerData player; private final long firstHit = System.currentTimeMillis(); - private long lastHit = System.currentTimeMillis(); - private long lastInvulnerabilityApplication; + private long lastHit = System.currentTimeMillis(), lastToggle; private boolean pvpMode; @@ -28,6 +27,7 @@ public class CombatHandler implements Closable { public void update() { lastHit = System.currentTimeMillis(); + lastToggle = 0; player.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown); // Simply refreshing @@ -68,17 +68,18 @@ public class CombatHandler implements Closable { } /** - * This is used for PvP mode invulnerability when a player - * joins a region while he still has PvP mode toggled on. + * This is used for PvP mode inactivity when a player + * joins a region with PvP mode toggled on, OR toggles on + * PvP mode using the command when standing in a PvP region. * - * @return If the player is invulnerable + * @return If the player is inert i.e if he CAN hit/take damage */ - public boolean isInvulnerable() { - return System.currentTimeMillis() < lastInvulnerabilityApplication + MMOCore.plugin.configManager.pvpModeInvulnerability * 1000; + public boolean canPvp() { + return System.currentTimeMillis() > lastToggle + MMOCore.plugin.configManager.pvpModeInvulnerability * 1000; } - public void applyInvulnerability() { - lastInvulnerabilityApplication = System.currentTimeMillis(); + public void preventPvp() { + lastToggle = System.currentTimeMillis(); } public boolean canQuitPvpMode() { diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 47b690a2..6e479196 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -296,16 +296,35 @@ pvp_mode: enabled: true # Delay after any attack during which the player will stay in PvP Mode (seconds) + # Has to be lower than 'cooldown.combat' combat_timeout: 30 - # Invulnerability when entering a pvp-mode region when your PvP mode is toggled on. - invulnerability: 60 + # Invulnerability triggered when: + # - entering a PvP region with PvP mode turned on. + # - using the /pvpmode command inside of a PvP region. + invulnerability: + time: 60 + + # When enabled, players can hit other players to + # end their invulnerability state. + can_damage: false cooldown: - # Delay before being able to use /pvpmode after being in combat (seconds) - # Has to be greater than the combat timeout for it to make sense + + # Cooldown before being able to use the /pvpmode + # command when entering a PvP mode region. + region_enter: 20 + + # Cooldown before being able to use the /pvpmode + # command when entering a PvP mode region. + region_leave: 20 + + # Delay before being able to use /pvpmode after being in combat (seconds). + # Has to be greater than the 'combat_timeout' combat: 45 + # Cooldown when toggling on PvP mode, before being able to toggle it off (seconds) toggle_on: 5 + # Cooldown when toggling off PvP mode (seconds) toggle_off: 3 \ No newline at end of file From 83b9c37c6a2e592797be8248e7bffab4f38bc96b Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 17:38:38 +0100 Subject: [PATCH 06/30] Disabled combat mode by default --- MMOCore-Dist/src/main/resources/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 6e479196..78fbf155 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -293,7 +293,7 @@ command-verbose: pvp_mode: # Requires /reload when changed - enabled: true + enabled: false # Delay after any attack during which the player will stay in PvP Mode (seconds) # Has to be lower than 'cooldown.combat' @@ -305,8 +305,8 @@ pvp_mode: invulnerability: time: 60 - # When enabled, players can hit other players to - # end their invulnerability state. + # When enabled, players can damage other players + # to end this invulnerable time period. can_damage: false cooldown: From fb270bf1b6d9106ad9da4fd5347f657eb80876a1 Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 22:31:01 +0100 Subject: [PATCH 07/30] Placeholder for pvp mode --- .../net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java index 4ba5fca6..7a865cd3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java @@ -95,6 +95,9 @@ public class RPGPlaceholders extends PlaceholderExpansion { else if (identifier.equals("in_combat")) return String.valueOf(playerData.isInCombat()); + else if (identifier.equals("pvp_mode")) + return String.valueOf(playerData.getCombat().isInPvpMode()); + else if (identifier.startsWith("since_enter_combat")) return playerData.isInCombat() ? MythicLib.plugin.getMMOConfig().decimal.format((System.currentTimeMillis() - playerData.getCombat().getFirstHit()) / 1000) : "-1"; From 05355688e206c9fc65b3e0e8ae2b31249e20f4b0 Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 22:53:27 +0100 Subject: [PATCH 08/30] Fixed support for Kingdomsx --- .../main/java/net/Indyuce/mmocore/guild/GuildModuleType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java index 40a82d0b..8b7410c5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java @@ -12,7 +12,7 @@ public enum GuildModuleType { // Useless since MythicLib already supports FactionBridge // FACTIONS("Factions", FactionsGuildModule::new), GUILDS("Guilds", GuildsGuildModule::new), - KINGDOMSX("KingdomsX", KingdomsXGuildModule::new), + KINGDOMSX("Kingdoms", KingdomsXGuildModule::new), MMOCORE("MMOCore", MMOCoreGuildModule::new), ULTIMATE_CLANS("UltimateClans", UltimateClansGuildModule::new), ; From 14c015645d6c8b9d0569d18c2de687bb49299fa1 Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 23:40:37 +0100 Subject: [PATCH 09/30] Reduced confusion for guild module --- .../src/main/java/net/Indyuce/mmocore/guild/GuildModule.java | 2 ++ .../Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java index e3dae11d..c16a9cb0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModule.java @@ -3,6 +3,7 @@ package net.Indyuce.mmocore.guild; import io.lumine.mythic.lib.comp.interaction.relation.Relationship; import net.Indyuce.mmocore.api.player.PlayerData; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface GuildModule { @@ -10,5 +11,6 @@ public interface GuildModule { @Nullable public AbstractGuild getGuild(PlayerData playerData); + @NotNull public Relationship getRelationship(Player player, Player target); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java index a8530800..97c0b48b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java @@ -30,7 +30,7 @@ public class KingdomsXGuildModule implements GuildModule { final KingdomPlayer player1 = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(player.getUniqueId()); if (player1 == null) - return null; + return Relationship.GUILD_NEUTRAL; final Kingdom kingdom1 = player1.getKingdom(); if (kingdom1 == null) @@ -38,7 +38,7 @@ public class KingdomsXGuildModule implements GuildModule { final KingdomPlayer player2 = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(target.getUniqueId()); if (player2 == null) - return null; + return Relationship.GUILD_NEUTRAL; final Kingdom kingdom2 = player2.getKingdom(); if (kingdom2 == null) From afa4a0467e90e495de50999a5268df5603f35dfc Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 23:56:51 +0100 Subject: [PATCH 10/30] Final commit for combat mode --- .../mmocore/command/PvpModeCommand.java | 6 +- .../region/pvpmode/MMOCoreFlagHandler.java | 63 ++++++++ .../comp/region/pvpmode/PvPFlagHandler.java | 59 +++++++ .../comp/region/pvpmode/PvPModeHandler.java | 70 +++------ .../comp/region/pvpmode/PvPModeListener.java | 72 +++++++-- .../mmocore/manager/ConfigManager.java | 10 +- .../Indyuce/mmocore/player/CombatHandler.java | 21 ++- MMOCore-Dist/src/main/resources/config.yml | 9 +- .../src/main/resources/default/messages.yml | 145 +++++++++--------- 9 files changed, 303 insertions(+), 152 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPFlagHandler.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java index 44cb6c3b..029c6917 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java @@ -44,13 +44,13 @@ public class PvpModeCommand extends RegisteredCommand { // Toggling on when in PVP region if (playerData.getCombat().isInPvpMode() && MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) { - playerData.getCombat().preventPvp(); + playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand); MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle.on-invulnerable", "time", - MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); + MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand)).send(playerData.getPlayer()); // Just send message otherwise } else - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off")).send((Player) sender); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off") + "-safe").send((Player) sender); return true; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java new file mode 100644 index 00000000..c9659376 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java @@ -0,0 +1,63 @@ +package net.Indyuce.mmocore.comp.region.pvpmode; + +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.session.MoveType; +import com.sk89q.worldguard.session.Session; +import com.sk89q.worldguard.session.handler.FlagValueChangeHandler; +import net.Indyuce.mmocore.api.player.PlayerData; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class MMOCoreFlagHandler extends FlagValueChangeHandler { + + @NotNull + protected PlayerData playerData; + + protected long lastMessage; + + protected static final long MESSAGE_TIMEOUT = 3 * 1000; + + public MMOCoreFlagHandler(Session session, Flag flag) { + super(session, flag); + } + + /** + * Triggered when WorldGuard initializes the value for the first time, + * on player login or world change for instance. + */ + @Override + protected void onInitialValue(LocalPlayer player, ApplicableRegionSet set, StateFlag.State value) { + try { + playerData = PlayerData.get(player.getUniqueId()); + } catch (Exception exception) { + // Citizens. + } + } + + public abstract StateFlag.State getDefaultState(); + + /** + * Triggered when WorldGuard does not find a region setting the value of the flag. + * In that case, put PvP mode to its default setting that is OFF. + */ + @Override + protected boolean onAbsentValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State lastValue, MoveType moveType) { + return onSetValue(player, from, to, toSet, getDefaultState(), lastValue, moveType); + } + + protected boolean isInvalid() { + return playerData == null; + } + + protected boolean toBoolean(@Nullable StateFlag.State state) { + return state == StateFlag.State.ALLOW; + } + + protected boolean canSendMessage() { + return System.currentTimeMillis() > lastMessage + MESSAGE_TIMEOUT; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPFlagHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPFlagHandler.java new file mode 100644 index 00000000..fb03ceed --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPFlagHandler.java @@ -0,0 +1,59 @@ +package net.Indyuce.mmocore.comp.region.pvpmode; + +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flags; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.flags.StateFlag.State; +import com.sk89q.worldguard.session.MoveType; +import com.sk89q.worldguard.session.Session; +import io.lumine.mythic.lib.MythicLib; +import net.Indyuce.mmocore.MMOCore; + +public class PvPFlagHandler extends MMOCoreFlagHandler { + + public static final Factory FACTORY = new Factory() { + + @Override + public PvPFlagHandler create(Session session) { + return new PvPFlagHandler(session, Flags.PVP); + } + }; + + public PvPFlagHandler(Session session, StateFlag flag) { + super(session, flag); + } + + @Override + public State getDefaultState() { + return State.ALLOW; + } + + /** + * Triggered when a player changes region and finds a new value for that flag. + * In that case, apply the new setting and display messages if needed. + */ + @Override + protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, State currentValue, State lastValue, MoveType moveType) { + if (isInvalid()) + return true; + + boolean newPvp = toBoolean(currentValue); + boolean lastPvp = toBoolean(lastValue); + + if (newPvp && !lastPvp) { + + // Apply invulnerability + playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange); + + // Send message + if (canSendMessage()) { + lastMessage = System.currentTimeMillis(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-on", "time", + MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange)).send(playerData.getPlayer()); + } + } + return true; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java index f5c36407..05dd6a93 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java @@ -3,33 +3,23 @@ package net.Indyuce.mmocore.comp.region.pvpmode; import com.sk89q.worldedit.util.Location; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.flags.StateFlag.State; import com.sk89q.worldguard.session.MoveType; import com.sk89q.worldguard.session.Session; -import com.sk89q.worldguard.session.handler.FlagValueChangeHandler; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.comp.flags.WorldGuardFlags; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.command.PvpModeCommand; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Objects; -public class PvPModeHandler extends FlagValueChangeHandler { - - @NotNull - private PlayerData playerData; - - private long lastMessage; - - private static final long MESSAGE_TIMEOUT = 3 * 1000; +public class PvPModeHandler extends MMOCoreFlagHandler { public static final Factory FACTORY = new Factory() { - public final WorldGuardFlags wgFlags = Objects.requireNonNull(MythicLib.plugin.getFlags().getHandler(WorldGuardFlags.class), "Could not reach ML compatibility class for WG"); + final WorldGuardFlags wgFlags = Objects.requireNonNull(MythicLib.plugin.getFlags().getHandler(WorldGuardFlags.class), "Could not reach ML compatibility class for WG"); @Override public PvPModeHandler create(Session session) { @@ -41,41 +31,23 @@ public class PvPModeHandler extends FlagValueChangeHandler { super(session, flag); } - /** - * Triggered when WorldGuard initializes the value for the first time, - * on player login or world change for instance. - */ @Override - protected void onInitialValue(LocalPlayer player, ApplicableRegionSet set, State value) { - try { - playerData = PlayerData.get(player.getUniqueId()); - } catch (Exception exception) { - // Citizens. - } + public State getDefaultState() { + return State.ALLOW; } - /** - * Triggered when WorldGuard does not find a region setting the value of the flag. - * In that case, put PvP mode to its default setting that is OFF. - */ - @Override - protected boolean onAbsentValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State lastValue, MoveType moveType) { - return onSetValue(player, from, to, toSet, DEFAULT_STATE, lastValue, moveType); - } - - public static final StateFlag.State DEFAULT_STATE = StateFlag.State.DENY; - /** * Triggered when a player changes region and finds a new value for that flag. * In that case, apply the new setting and display messages if needed. */ @Override protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State currentValue, StateFlag.State lastValue, MoveType moveType) { - boolean newPvpMode = toBoolean(currentValue); - boolean lastPvpMode = toBoolean(lastValue); if (isInvalid()) return true; + boolean newPvpMode = toBoolean(currentValue); + boolean lastPvpMode = toBoolean(lastValue); + if (!newPvpMode && lastPvpMode) { // Apply cooldown @@ -83,10 +55,16 @@ public class PvPModeHandler extends FlagValueChangeHandler { // Send message if (canSendMessage()) { - final String msgPath = (playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode()) ? "allowed" : "denied"; + + // Leave combat when joining safe zone + final boolean pvpFlag = toSet.queryState(null, Flags.PVP) != StateFlag.State.DENY; + if (playerData.getCombat().isInPvpMode() && !pvpFlag) + playerData.getCombat().close(); + + final boolean pvpEnabled = playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode() && pvpFlag; lastMessage = System.currentTimeMillis(); final double remaining = (playerData.getCombat().getLastHit() + MMOCore.plugin.configManager.pvpModeCombatTimeout * 1000.0D - System.currentTimeMillis()) / 1000.0D; - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + msgPath, "remaining", + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + (pvpEnabled ? "allowed" : "denied"), "remaining", (MythicLib.plugin.getMMOConfig()).decimal.format(remaining)).send(playerData.getPlayer()); } } else if (newPvpMode && !lastPvpMode) { @@ -97,27 +75,15 @@ public class PvPModeHandler extends FlagValueChangeHandler { // Apply invulnerability final boolean applyInvulnerability = playerData.getCombat().isInPvpMode() && playerData.getCombat().canQuitPvpMode(); if (applyInvulnerability) - playerData.getCombat().preventPvp(); + playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange); // Send message if (canSendMessage()) { lastMessage = System.currentTimeMillis(); MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-" + (applyInvulnerability ? "on" : "off"), "time", - MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); + MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange)).send(playerData.getPlayer()); } } return true; } - - private boolean isInvalid() { - return playerData == null; - } - - private boolean toBoolean(@Nullable State state) { - return state == State.ALLOW; - } - - private boolean canSendMessage() { - return System.currentTimeMillis() > lastMessage + MESSAGE_TIMEOUT; - } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java index 497e291f..49dda041 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java @@ -1,42 +1,80 @@ package net.Indyuce.mmocore.comp.region.pvpmode; import com.sk89q.worldguard.WorldGuard; -import com.sk89q.worldguard.bukkit.protection.events.DisallowedPVPEvent; +import com.sk89q.worldguard.session.handler.Handler; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.comp.flags.CustomFlag; -import io.lumine.mythic.lib.comp.interaction.InteractionType; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import org.apache.commons.lang.Validate; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +import javax.annotation.Nullable; public class PvPModeListener implements Listener { public PvPModeListener() { - Validate.isTrue(WorldGuard.getInstance().getPlatform().getSessionManager().registerHandler(PvPModeHandler.FACTORY, null), "Could not register WG handler for PvP mode"); + Validate.isTrue(registerHandler(PvPModeHandler.FACTORY), "Could not register WG handler for PvP mode"); + if (MMOCore.plugin.getConfig().getBoolean("pvp_mode.invulnerability.apply_to_pvp_flag")) + Validate.isTrue(registerHandler(PvPFlagHandler.FACTORY), "Could not register WG handler for PvP"); } + private boolean registerHandler(Handler.Factory factory) { + return WorldGuard.getInstance().getPlatform().getSessionManager().registerHandler(factory, null); + } + + /** + * Runs after MythicLib interaction checks. This listener + * takes care of PVP inside of PvP-mode regions. + */ @EventHandler(ignoreCancelled = true) - public void unblockPvp(DisallowedPVPEvent event) { - PlayerData defender, attacker; - if (!(attacker = PlayerData.get(event.getAttacker())).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode()) + public void a(EntityDamageByEntityEvent event) { + if (!UtilityMethods.isRealPlayer(event.getEntity())) return; - // If defender is out of combat - if (!defender.getCombat().canPvp()) + final @Nullable Player source = UtilityMethods.getPlayerDamager(event); + if (source == null) return; - // If attacker cannot deal damage yet - if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && !attacker.getCombat().canPvp()) - return; - - // Defender is still fighting and cannot leave PvP mode - if (!defender.getCombat().canQuitPvpMode()) + // Check for target's invulnerability BEFORE pvp-mode flag because it can also + // happen when the option pvp_mode.invulnerability.apply_to_pvp_flag is on + final Player target = (Player) event.getEntity(); + final PlayerData targetData = PlayerData.get(target); + if (targetData.getCombat().isInvulnerable()) { + final long left = targetData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-target", + "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); event.setCancelled(true); + return; + } - // Enable PvP if accepted - else if (MythicLib.plugin.getFlags().isFlagAllowed(event.getDefender().getLocation(), CustomFlag.PVP_MODE) && - MythicLib.plugin.getEntities().checkPvpInteractionRules(event.getAttacker(), event.getDefender(), InteractionType.OFFENSE_ACTION, true)) + // If attacker is still invulnerable and cannot deal damage + final PlayerData sourceData = PlayerData.get(source); + if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && sourceData.getCombat().isInvulnerable()) { + final long left = sourceData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-self", + "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); event.setCancelled(true); + return; + } + + // Checks for PvP mode on target location + if (!MythicLib.plugin.getFlags().isFlagAllowed(target.getLocation(), CustomFlag.PVP_MODE)) + return; + + // Defender has not enabled PvP mode + if (!targetData.getCombat().isInPvpMode()) { + event.setCancelled(true); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-target").send(source); + } + + // Attacker has not enabled PvP mode + else if (!sourceData.getCombat().isInPvpMode()) { + event.setCancelled(true); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-self").send(source); + } } } 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 9e8858d4..6ef35a04 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 @@ -27,12 +27,13 @@ import java.util.logging.Level; public class ConfigManager { public final CommandVerbose commandVerbose = new CommandVerbose(); - public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar, pvpModeEnabled, pvpModeInvulnerabilityCanDamage; + public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar, + pvpModeEnabled, pvpModeInvulnerabilityCanDamage; public String partyChatPrefix, noSkillBoundPlaceholder; public ChatColor staminaFull, staminaHalf, staminaEmpty; public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; - public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, pvpModeCombatTimeout, pvpModeInvulnerability, - pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown; + public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, + pvpModeCombatTimeout, pvpModeInvulnerabilityTimeRegionChange, pvpModeInvulnerabilityTimeCommand, pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown; public int maxPartyLevelDifference, maxBoundActiveSkills, maxBoundPassiveSkills; public final List combatLogDamageCauses = new ArrayList<>(); @@ -140,7 +141,8 @@ public class ConfigManager { pvpModeRegionEnterCooldown = config.getDouble("pvp_mode.cooldown.region_enter"); pvpModeRegionLeaveCooldown = config.getDouble("pvp_mode.cooldown.region_leave"); pvpModeCombatTimeout = config.getDouble("pvp_mode.combat_timeout"); - pvpModeInvulnerability = config.getDouble("pvp_mode.invulnerability.time"); + pvpModeInvulnerabilityTimeCommand = config.getDouble("pvp_mode.invulnerability.time.command"); + pvpModeInvulnerabilityTimeRegionChange = config.getDouble("pvp_mode.invulnerability.time.region_change"); pvpModeInvulnerabilityCanDamage = config.getBoolean("pvp_mode.invulnerability.can_damage"); // Resources diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java index 2879ff46..bac97f04 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java @@ -14,7 +14,7 @@ public class CombatHandler implements Closable { private final PlayerData player; private final long firstHit = System.currentTimeMillis(); - private long lastHit = System.currentTimeMillis(), lastToggle; + private long lastHit = System.currentTimeMillis(), invulnerableTill; private boolean pvpMode; @@ -27,7 +27,7 @@ public class CombatHandler implements Closable { public void update() { lastHit = System.currentTimeMillis(); - lastToggle = 0; + invulnerableTill = 0; player.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown); // Simply refreshing @@ -58,6 +58,10 @@ public class CombatHandler implements Closable { return firstHit; } + public long getInvulnerableTill() { + return invulnerableTill; + } + /** * Simply checks if there is a scheduled task. * @@ -74,12 +78,12 @@ public class CombatHandler implements Closable { * * @return If the player is inert i.e if he CAN hit/take damage */ - public boolean canPvp() { - return System.currentTimeMillis() > lastToggle + MMOCore.plugin.configManager.pvpModeInvulnerability * 1000; + public boolean isInvulnerable() { + return System.currentTimeMillis() < invulnerableTill; } - public void preventPvp() { - lastToggle = System.currentTimeMillis(); + public void setInvulnerable(double time) { + invulnerableTill = System.currentTimeMillis() + (long) (time * 1000); } public boolean canQuitPvpMode() { @@ -108,5 +112,10 @@ public class CombatHandler implements Closable { public void close() { if (isInCombat()) quit(true); + + // Necessary steps when entering a town. + lastHit = 0; + invulnerableTill = 0; + player.getMMOPlayerData().getCooldownMap().resetCooldown(PvpModeCommand.COOLDOWN_KEY); } } diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 78fbf155..984f3cc2 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -303,12 +303,19 @@ pvp_mode: # - entering a PvP region with PvP mode turned on. # - using the /pvpmode command inside of a PvP region. invulnerability: - time: 60 + time: + region_change: 60 + command: 30 # When enabled, players can damage other players # to end this invulnerable time period. can_damage: false + # When enabled, leaving a no-PVP zone and entering a PVP zone + # will apply the SAME invulnerability time. + # Requires /reload when changed + apply_to_pvp_flag: false + cooldown: # Cooldown before being able to use the /pvpmode diff --git a/MMOCore-Dist/src/main/resources/default/messages.yml b/MMOCore-Dist/src/main/resources/default/messages.yml index e6ec39c2..84864417 100644 --- a/MMOCore-Dist/src/main/resources/default/messages.yml +++ b/MMOCore-Dist/src/main/resources/default/messages.yml @@ -1,51 +1,58 @@ # Level & Experience level-up: -- '' -- '&eCongratulations, you reached level &6{level}&e!' -- '&eUse &6/p &eto see your new statistics!' -- '' + - '' + - '&eCongratulations, you reached level &6{level}&e!' + - '&eUse &6/p &eto see your new statistics!' + - '' profession-level-up: -- '&eYou are now level &6{level}&e in &6{profession}&e!' + - '&eYou are now level &6{level}&e in &6{profession}&e!' exp-notification: '%&f{profession} &e{progress} &e{ratio}%' exp-hologram: '&e+{exp} EXP!' class-select: '&eYou are now a &6{class}&e!' already-on-class: '&cYou are already a {class}.' death-exp-loss: -- '' -- '&4You died and lost {loss} experience.' -- '' + - '' + - '&4You died and lost {loss} experience.' + - '' # General not-enough-perms: '&cYou do not have enough permissions.' # Experience boosters booster-main: -- '&e' -- '&eA &6{multiplier}x&e EXP multiplier is now active!' -- '&e' + - '&e' + - '&eA &6{multiplier}x&e EXP multiplier is now active!' + - '&e' booster-skill: -- '&e' -- '&eA &6{multiplier}x&e &6{profession} &eEXP multiplier is now active!' -- '&e' + - '&e' + - '&eA &6{multiplier}x&e &6{profession} &eEXP multiplier is now active!' + - '&e' booster-expired: '&cExpired!' # PvP Mode pvp-mode: - cooldown: '&cPlease wait {remaining} seconds to use this command again.' + cooldown: '&cPlease wait {remaining} seconds to use this command again.' - # When using /pvpmode - toggle: - on: '&aPvP Mode on.' - on-invulnerable: '&aPvP Mode on. You are now invulnerable for {time} seconds.' - off: '&cPvP Mode off.' + # When you cannot hit another player + cannot-hit: + pvp-mode-disabled-target: '&cThis player has not toggled on PvP.' + pvp-mode-disabled-self: '&cYou have not toggled on PvP.' + invulnerable-self: '&cYou are still out of combat for {left} seconds.' + invulnerable-target: '&cThis player is out of combat for {left} seconds.' - # Entering/leaving regions with specific flag value - leave: - pvp-allowed: '&cYou left a PVP zone but are still vulnerable for {remaining} seconds!' - pvp-denied: '&cYou left the PVP zone.' - enter: - pvp-mode-on: '&aYou entered a PVP zone and gained invulnerability for {time} seconds!' - pvp-mode-off: '&aYou entered a PVP zone. You may use /pvpmode to fight other players.' + # When using /pvpmode + toggle: + on-safe: '&aYou will now be able to fight other players in dedicated areas.' + on-invulnerable: '&aYou will be able to fight other players in {time} seconds.' + off-safe: '&cYou can no longer fight other players.' + + # Entering/leaving regions + leave: + pvp-allowed: '&cYou left a PVP zone but are still vulnerable for {remaining} seconds!' + pvp-denied: '&cYou left the PVP zone.' + enter: + pvp-mode-on: '&aYou entered a PVP zone and gained invulnerability for {time} seconds!' + pvp-mode-off: '&aYou entered a PVP zone. You may use /pvpmode to fight other players.' # Fishing Profession caught-fish: '&cYou caught a fish!' @@ -54,32 +61,32 @@ fish-out-water-crit: '&aCritical Fish!' # Player Input player-input: - anvil: - friend-request: 'Friend name..' - party-invite: 'Player name..' - guild-invite: 'Player name..' - guild-creation-tag: 'Guild tag..' - guild-creation-name: 'Guild name..' - chat: - friend-request: '&eWrite in the chat the player name.' - party-invite: '&eWrite in the chat the player you want to invite.' - guild-invite: '&eWrite in the chat the player you want to invite.' - guild-creation-tag: '&eWrite in the chat the TAG of the Guild you want to create.' - guild-creation-name: '&eWrite in the chat the name of the Guild you want to create.' - cancel: '&eWrite &c''cancel'' &eto cancel.' + anvil: + friend-request: 'Friend name..' + party-invite: 'Player name..' + guild-invite: 'Player name..' + guild-creation-tag: 'Guild tag..' + guild-creation-name: 'Guild name..' + chat: + friend-request: '&eWrite in the chat the player name.' + party-invite: '&eWrite in the chat the player you want to invite.' + guild-invite: '&eWrite in the chat the player you want to invite.' + guild-creation-tag: '&eWrite in the chat the TAG of the Guild you want to create.' + guild-creation-name: '&eWrite in the chat the name of the Guild you want to create.' + cancel: '&eWrite &c''cancel'' &eto cancel.' # Spell Casting casting: - action-bar: - ready: '&6[{index}] &a&l{skill}' - on-cooldown: '&6[{index}] &c&l{skill} &6(&c{cooldown}&6)' - no-mana: '&6[{index}] &9&l{skill}' - no-stamina: '&6[{index}] &9&l{skill}' - split: '&7 &7 - &7 ' - no-longer: '%&cYou cancelled skill casting.' - no-mana: '&cYou do not have enough {mana}, {mana-required} more required!' - no-stamina: '&cYou do not have enough stamina!' - on-cooldown: '&cThis skill is on a {cooldown}s cooldown.' + action-bar: + ready: '&6[{index}] &a&l{skill}' + on-cooldown: '&6[{index}] &c&l{skill} &6(&c{cooldown}&6)' + no-mana: '&6[{index}] &9&l{skill}' + no-stamina: '&6[{index}] &9&l{skill}' + split: '&7 &7 - &7 ' + no-longer: '%&cYou cancelled skill casting.' + no-mana: '&cYou do not have enough {mana}, {mana-required} more required!' + no-stamina: '&cYou do not have enough stamina!' + on-cooldown: '&cThis skill is on a {cooldown}s cooldown.' # Combat Log now-in-combat: '%&cYou are now in combat!' @@ -118,20 +125,20 @@ friend-request-cooldown: '&cPlease wait {cooldown}.' cant-request-to-yourself: '&cYou can''t send a request to yourself.' already-friends: '&cYou are already friends with {player}.' friend-request: -- '{"text":""}' -- '{"text":"&6{player} &ejust sent you a friend request!"}' -- '[{"text":" ","hoverEvent":{}},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r ","hoverEvent":{}},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' -- '{"text":""}' + - '{"text":""}' + - '{"text":"&6{player} &ejust sent you a friend request!"}' + - '[{"text":" ","hoverEvent":{}},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r ","hoverEvent":{}},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' + - '{"text":""}' # Parties party-chat: '&5[Party] {player}: {message}' sent-party-invite: '&eYou sent a party invite to &6{player}&e.' already-in-party: '&c{player} is already in your party.' party-invite: -- '{"text":""}' -- '{"text":"&6{player} &ehas invited you to their party!"}' -- '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' -- '{"text":""}' + - '{"text":""}' + - '{"text":"&6{player} &ehas invited you to their party!"}' + - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' + - '{"text":""}' party-is-full: '&cSorry, your party is full.' party-joined: '&eYou successfully joined &6{owner}&e''s party.' party-joined-other: '&6{player}&e joined your party!' @@ -145,10 +152,10 @@ guild-chat: '&a[{tag}] {player}: {message}' sent-guild-invite: '&eYou sent a guild invite to &6{player}&e.' already-in-guild: '&c{player} is already in your guild.' guild-invite: -- '{"text":""}' -- '{"text":"&6{player} &ehas invited you to their guild!"}' -- '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' -- '{"text":""}' + - '{"text":""}' + - '{"text":"&6{player} &ehas invited you to their guild!"}' + - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' + - '{"text":""}' #guild-is-full: '&cSorry, your guild is full.' -Unused right now guild-joined: '&eYou successfully joined &6{owner}&e''s guild.' guild-joined-other: '&6{player}&e joined your guild!' @@ -156,11 +163,11 @@ transfer-guild-ownership: '&eYou were transfered the guild ownership.' kick-from-guild: '&eYou successfully kicked &6{player}&e from the guild.' guild-invite-cooldown: '&cPlease wait {cooldown} before inviting {player}.' guild-creation: - failed: "&cCouldn't create guild: {reason}" - reasons: - invalid-characters: "&eInvalid character(s)!" - invalid-length: "&eThe length must be between {min} and {max}!" - already-exists: "&eThat guild tag already exists!" + failed: "&cCouldn't create guild: {reason}" + reasons: + invalid-characters: "&eInvalid character(s)!" + invalid-length: "&eThe length must be between {min} and {max}!" + already-exists: "&eThat guild tag already exists!" # Quests already-on-quest: '&cYou are already on a quest.' @@ -181,9 +188,9 @@ attribute-level-up: '&eYou successfully leveled up your &6{attribute}&e.' # {lev # Class selection cant-choose-new-class: - - '&cYou need one class point to perform this action.' + - '&cYou need one class point to perform this action.' no-permission-for-class: - - "&cYou don't have the permission to choose this class." + - "&cYou don't have the permission to choose this class." # Skills no-class-skill: '&cYour class has no skill.' From b966508c2dfa2f29ac3ceef105508ab7ee37e8c5 Mon Sep 17 00:00:00 2001 From: Jules Date: Wed, 22 Feb 2023 23:59:00 +0100 Subject: [PATCH 11/30] Messages sent only when dmg > 0 --- .../comp/region/pvpmode/PvPModeListener.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java index 49dda041..9a7e0e81 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java @@ -29,6 +29,9 @@ public class PvPModeListener implements Listener { /** * Runs after MythicLib interaction checks. This listener * takes care of PVP inside of PvP-mode regions. + *

+ * Only send messages when damage is greater than 0 to support + * Bukkit events-based checks just like in recent ML builds. */ @EventHandler(ignoreCancelled = true) public void a(EntityDamageByEntityEvent event) { @@ -44,9 +47,11 @@ public class PvPModeListener implements Listener { final Player target = (Player) event.getEntity(); final PlayerData targetData = PlayerData.get(target); if (targetData.getCombat().isInvulnerable()) { - final long left = targetData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-target", - "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); + if (event.getDamage() > 0) { + final long left = targetData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-target", + "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); + } event.setCancelled(true); return; } @@ -54,9 +59,11 @@ public class PvPModeListener implements Listener { // If attacker is still invulnerable and cannot deal damage final PlayerData sourceData = PlayerData.get(source); if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && sourceData.getCombat().isInvulnerable()) { - final long left = sourceData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-self", - "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); + if (event.getDamage() > 0) { + final long left = sourceData.getCombat().getInvulnerableTill() - System.currentTimeMillis(); + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-self", + "left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source); + } event.setCancelled(true); return; } @@ -68,13 +75,15 @@ public class PvPModeListener implements Listener { // Defender has not enabled PvP mode if (!targetData.getCombat().isInPvpMode()) { event.setCancelled(true); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-target").send(source); + if (event.getDamage() > 0) + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-target").send(source); } // Attacker has not enabled PvP mode else if (!sourceData.getCombat().isInPvpMode()) { event.setCancelled(true); - MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-self").send(source); + if (event.getDamage() > 0) + MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-self").send(source); } } } From deffae106a0705fc9f01df0545863b6054defeca Mon Sep 17 00:00:00 2001 From: Jules Date: Thu, 23 Feb 2023 00:07:02 +0100 Subject: [PATCH 12/30] Updated KingdomsX dep --- MMOCore-API/pom.xml | 2 +- .../Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index 2d9849dc..7ef489ff 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -276,7 +276,7 @@ org.kingdoms.main Kingdoms - 1.11.15.0.0.0.1.1 + 1.15.5 provided diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java index 97c0b48b..d0f13c88 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java @@ -6,8 +6,8 @@ import net.Indyuce.mmocore.guild.AbstractGuild; import net.Indyuce.mmocore.guild.GuildModule; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.kingdoms.constants.kingdom.Kingdom; -import org.kingdoms.constants.kingdom.model.KingdomRelation; +import org.kingdoms.constants.group.Kingdom; +import org.kingdoms.constants.group.model.relationships.KingdomRelation; import org.kingdoms.constants.player.KingdomPlayer; import org.kingdoms.main.Kingdoms; From f750326fe31e6e78959e53090b226c3f73c2d8bd Mon Sep 17 00:00:00 2001 From: Jules Date: Thu, 23 Feb 2023 00:07:14 +0100 Subject: [PATCH 13/30] Added messages for guild/party module hook --- MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java | 2 ++ .../main/java/net/Indyuce/mmocore/guild/GuildModuleType.java | 4 ++++ .../main/java/net/Indyuce/mmocore/party/PartyModuleType.java | 4 ++++ 3 files changed, 10 insertions(+) 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 4c9f948f..ac307ed7 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -208,6 +208,7 @@ public class MMOCore extends JavaPlugin { PartyModuleType moduleType = PartyModuleType.valueOf(partyPluginName); Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); partyModule = moduleType.provideModule(); + getLogger().log(Level.WARNING, "Hooked parties onto " + moduleType.getPluginName()); } catch (RuntimeException exception) { getLogger().log(Level.WARNING, "Could not initialize party module: " + exception.getMessage()); partyModule = new MMOCorePartyModule(); @@ -219,6 +220,7 @@ public class MMOCore extends JavaPlugin { GuildModuleType moduleType = GuildModuleType.valueOf(pluginName); Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed"); guildModule = moduleType.provideModule(); + getLogger().log(Level.WARNING, "Hooked guilds onto " + moduleType.getPluginName()); } catch (RuntimeException exception) { getLogger().log(Level.WARNING, "Could not initialize guild module: " + exception.getMessage()); guildModule = new MMOCoreGuildModule(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java index 8b7410c5..49cb5a36 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java @@ -25,6 +25,10 @@ public enum GuildModuleType { this.provider = provider; } + public String getPluginName() { + return pluginName; + } + public boolean isValid() { return Bukkit.getPluginManager().getPlugin(pluginName) != null; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java index ee001aac..5c497ea9 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java @@ -24,6 +24,10 @@ public enum PartyModuleType { this.provider = provider; } + public String getPluginName() { + return pluginName; + } + public boolean isValid() { return Bukkit.getPluginManager().getPlugin(pluginName) != null; } From 79e26086aea1c87604a2909bde0bd3fecaa43f57 Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 28 Feb 2023 10:50:15 +0100 Subject: [PATCH 14/30] Combat registers when logging in/changing world --- .../mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java index c9659376..5d9282ed 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/MMOCoreFlagHandler.java @@ -33,6 +33,9 @@ public abstract class MMOCoreFlagHandler extends FlagValueChangeHandler Date: Tue, 28 Feb 2023 18:05:24 +0100 Subject: [PATCH 15/30] Fixed DungeonsXL comp --- MMOCore-API/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index 7ef489ff..b16a859d 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -213,7 +213,14 @@ de.erethon DungeonsXL - 0.18-PRE-02 + 0.18-SNAPSHOT-1149 + provided + + + + de.erethon + Bedrock + 1.2.5 provided From 9ae2b3e661fb5a8de78a6eb5920fdd0cd4a9641c Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 28 Feb 2023 18:05:45 +0100 Subject: [PATCH 16/30] Fixed UClans comp --- MMOCore-API/pom.xml | 2 +- .../Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index b16a859d..1ac1239c 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -269,7 +269,7 @@ me.ulrich UltimateClans - 4.2.0 + 6.0.2 provided diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java index b5fde4ac..97386ae9 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java @@ -3,7 +3,7 @@ package net.Indyuce.mmocore.guild.compat; import io.lumine.mythic.lib.comp.interaction.relation.Relationship; import me.ulrich.clans.data.ClanData; import me.ulrich.clans.data.ClanRivalAlly; -import me.ulrich.clans.packets.interfaces.UClans; +import me.ulrich.clans.interfaces.UClans; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.guild.AbstractGuild; import net.Indyuce.mmocore.guild.GuildModule; From b3c3218d875d9d4e0a7da25655806f3ff27e2db9 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 2 Mar 2023 21:09:31 +0100 Subject: [PATCH 17/30] Fixed bug that occured w perm stats when doing /mmocore reload --- .../mmocore/api/player/PlayerData.java | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) 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 3154ed8f..74aedaa5 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 @@ -128,7 +128,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc private final Map tableItemClaims = new HashMap<>(); // NON-FINAL player data stuff made public to facilitate field change - public boolean noCooldown, statsLoaded; + public boolean noCooldown; /** * Player data is stored in the data map before it's actually fully loaded @@ -143,15 +143,10 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc questData = new PlayerQuests(this); playerStats = new PlayerStats(this); - // Used to see if the triggers need to be applied - for (StatInstance instance : mmoData.getStatMap().getInstances()) - for (StatModifier modifier : instance.getModifiers()) - if (modifier.getKey().startsWith(StatTrigger.TRIGGER_PREFIX)) { - statsLoaded = true; - break; - } + } + /** * Update all references after /mmocore reload so there can be garbage * collection with old plugin objects like class or skill instances. @@ -193,7 +188,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc skillTree.setupNodeStates(this); // Stat triggers setup - if (!statsLoaded) { + if (!areStatsLoaded()) { for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) for (SkillTreeNode node : skillTree.getNodes()) node.getExperienceTable().claimStatTriggers(this, node); @@ -236,7 +231,12 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc } public boolean areStatsLoaded() { - return statsLoaded; + // Used to see if the triggers need to be applied + for (StatInstance instance : mmoData.getStatMap().getInstances()) + for (StatModifier modifier : instance.getModifiers()) + if (modifier.getKey().startsWith(StatTrigger.TRIGGER_PREFIX)) + return true; + return false; } public Map getNodeLevels() { @@ -753,9 +753,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc final double r = Math.sin((double) t / warpTime * Math.PI); for (double j = 0; j < Math.PI * 2; j += Math.PI / 4) getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE, getPlayer().getLocation().add( - Math.cos((double) 5 * t / warpTime + j) * r, - (double) 2 * t / warpTime, - Math.sin((double) 5 * t / warpTime + j) * r), + Math.cos((double) 5 * t / warpTime + j) * r, + (double) 2 * t / warpTime, + Math.sin((double) 5 * t / warpTime + j) * r), 1, new Particle.DustOptions(Color.PURPLE, 1.25f)); } }.runTaskTimer(MMOCore.plugin, 0, 1); @@ -1032,6 +1032,16 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc public void setSkillLevel(String skill, int level) { skills.put(skill, level); + //If it is a passive skill we rebind it to make sure to update the damages done by it. + for (int i = 0; i < boundPassiveSkills.size(); i++) { + + PassiveSkill passiveSkill = boundPassiveSkills.get(i); + if (passiveSkill.getTriggeredSkill().getHandler().getId().equals(skill)) { + passiveSkill.unregister(mmoData); + passiveSkill.register(mmoData); + } + + } } public void resetSkillLevel(String skill) { @@ -1194,7 +1204,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc * 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() { From 6ac32670591b53043406eb7edd8f5b59bec60d1d Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 2 Mar 2023 21:31:42 +0100 Subject: [PATCH 18/30] Fixed bug that occured w/ perm stats when changing to a new class. --- .../java/net/Indyuce/mmocore/api/player/PlayerData.java | 7 +++++++ .../mmocore/api/player/profess/SavedClassInformation.java | 2 ++ 2 files changed, 9 insertions(+) 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 74aedaa5..db412801 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 @@ -222,6 +222,13 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc public void clearSkillTreePoints() { skillTreePoints.clear(); } + public void clearNodeTimesClaimed() { + Map copy= new HashMap<>(tableItemClaims); + copy.forEach((str, val) -> { + if (str.startsWith(SkillTreeNode.KEY_PREFIX)) + tableItemClaims.remove(str); + }); + } public Set> getNodeLevelsEntrySet() { HashMap nodeLevelsString = new HashMap<>(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java index 08b58661..76eafa7e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java @@ -213,6 +213,8 @@ public class SavedClassInformation { while (player.hasSkillBound(0)) player.unbindSkill(0); + player.clearNodeTimesClaimed(); + /* * Reads this class info, applies it to the player. set class after From a9ebca0f4da34ae49a3217384df8978577ee03d8 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 2 Mar 2023 22:03:03 +0100 Subject: [PATCH 19/30] Enabled to have customizable ClassConfirmation GUI names. --- .../mmocore/api/util/MMOCoreUtils.java | 4 + .../mmocore/gui/ClassConfirmation.java | 83 +++++++++++-------- .../net/Indyuce/mmocore/gui/ClassSelect.java | 22 ++++- 3 files changed, 70 insertions(+), 39 deletions(-) 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 6ef895ba..798c1394 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 @@ -53,6 +53,10 @@ public class MMOCoreUtils { return builder.toString(); } + public static String ymlName(String str) { + return str.toLowerCase().replace("_", "-").replace(" ", "-"); + } + /** * * @param value an integer you want to convert diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java index a6a918ba..64a57eb2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java @@ -34,6 +34,10 @@ public class ClassConfirmation extends EditableInventory { return new ClassConfirmationInventory(data, this, profess, last); } + public GeneratedInventory newInventory(PlayerData data, String GUIName, PlayerClass profess, PluginInventory last) { + return new ClassConfirmationInventory(data, GUIName, this, profess, last); + } + public class UnlockedItem extends InventoryItem { public UnlockedItem(ConfigurationSection config) { @@ -54,10 +58,10 @@ public class ClassConfirmation extends EditableInventory { for (int j = 0; j < 20; j++) bar.append(j == chars ? "" + ChatColor.WHITE + ChatColor.BOLD : "").append("|"); - holders.register("percent", decimal.format(ratio * 100)); - holders.register("progress", bar.toString()); - holders.register("class", profess.getName()); - holders.register("unlocked_skills", info.getSkillKeys().size()); + holders.register("percent", decimal.format(ratio * 100)); + holders.register("progress", bar.toString()); + holders.register("class", profess.getName()); + holders.register("unlocked_skills", info.getSkillKeys().size()); holders.register("class_skills", profess.getSkills().size()); holders.register("next_level", "" + nextLevelExp); holders.register("level", info.getLevel()); @@ -93,43 +97,52 @@ public class ClassConfirmation extends EditableInventory { public ItemStack display(ClassConfirmationInventory inv, int n) { return inv.getPlayerData().hasSavedClass(inv.profess) ? unlocked.display(inv, n) : locked.display(inv, n); } - } + } - public class ClassConfirmationInventory extends GeneratedInventory { - private final PlayerClass profess; - private final PluginInventory last; + public class ClassConfirmationInventory extends GeneratedInventory { + private final PlayerClass profess; + private final PluginInventory last; + private String GUIName; - public ClassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last) { - super(playerData, editable); + public ClassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last) { + super(playerData, editable); + this.profess = profess; + this.last = last; + } - this.profess = profess; - this.last = last; - } + public ClassConfirmationInventory(PlayerData playerData, String GUIName, EditableInventory editable, PlayerClass profess, PluginInventory last) { + super(playerData, editable); + this.GUIName = GUIName; + this.profess = profess; + this.last = last; + } - @Override - public void whenClicked(InventoryClickContext context, InventoryItem item) { - if (item.getFunction().equals("back")) - last.open(); + @Override + public void whenClicked(InventoryClickContext context, InventoryItem item) { + if (item.getFunction().equals("back")) + last.open(); - else if (item.getFunction().equals("yes")) { + else if (item.getFunction().equals("yes")) { - PlayerChangeClassEvent called = new PlayerChangeClassEvent(playerData, profess); - Bukkit.getPluginManager().callEvent(called); - if (called.isCancelled()) - return; + PlayerChangeClassEvent called = new PlayerChangeClassEvent(playerData, profess); + Bukkit.getPluginManager().callEvent(called); + if (called.isCancelled()) + return; - playerData.giveClassPoints(-1); - (playerData.hasSavedClass(profess) ? playerData.getClassInfo(profess) - : new SavedClassInformation(MMOCore.plugin.dataProvider.getDataManager().getDefaultData())).load(profess, playerData); - MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player); - MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player); - player.closeInventory(); - } - } + playerData.giveClassPoints(-1); + (playerData.hasSavedClass(profess) ? playerData.getClassInfo(profess) + : new SavedClassInformation(MMOCore.plugin.dataProvider.getDataManager().getDefaultData())).load(profess, playerData); + MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player); + MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player); + player.closeInventory(); + } + } - @Override - public String calculateName() { - return getName(); - } - } + @Override + public String calculateName() { + if (GUIName != null) + return GUIName; + return getName(); + } + } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java index d1704bbb..a8c65ccd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java @@ -3,6 +3,7 @@ package net.Indyuce.mmocore.gui; import io.lumine.mythic.lib.MythicLib; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.InventoryClickContext; @@ -21,9 +22,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class ClassSelect extends EditableInventory { @@ -43,12 +42,21 @@ public class ClassSelect extends EditableInventory { public class ClassItem extends SimplePlaceholderItem { private final String name; private final List lore; + /** + * This enables to configure the name of the class confirmation GUI (for custom GUI textures). + */ + private final Map classGUINames = new HashMap<>(); public ClassItem(ConfigurationSection config) { super(Material.BARRIER, config); this.name = config.getString("name"); this.lore = config.getStringList("lore"); + if (config.contains("class-confirmation-GUI-name")) { + ConfigurationSection section = config.getConfigurationSection("class-confirmation-GUI-name"); + for (String key : section.getKeys(false)) + classGUINames.put(key, section.getString(key)); + } } public boolean hasDifferentDisplay() { @@ -105,6 +113,7 @@ public class ClassSelect extends EditableInventory { @Override public void whenClicked(InventoryClickContext context, InventoryItem item) { if (item.getFunction().equals("class")) { + ClassItem classItem = (ClassItem) item; String classId = context.getClickedItem().getItemMeta().getPersistentDataContainer().get(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING); if (classId.equals("")) return; @@ -127,8 +136,13 @@ public class ClassSelect extends EditableInventory { MMOCore.plugin.configManager.getSimpleMessage("already-on-class", "class", profess.getName()).send(player); return; } + PlayerClass playerClass = findDeepestSubclass(playerData, profess); + String classKey = MMOCoreUtils.ymlName(playerClass.getName()); + if (classItem.classGUINames.containsKey(classKey)) { + InventoryManager.CLASS_CONFIRM.newInventory(playerData,classItem.classGUINames.get(classKey),playerClass, this).open(); - InventoryManager.CLASS_CONFIRM.newInventory(playerData, findDeepestSubclass(playerData, profess), this).open(); + } else + InventoryManager.CLASS_CONFIRM.newInventory(playerData,playerClass, this).open(); } } } From 3754a8888025fc2705fda585d7ace4ce7d98fc08 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 2 Mar 2023 22:13:16 +0100 Subject: [PATCH 20/30] Default GUI config to show how it works. --- .../src/main/resources/default/gui/class-select.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml index 0e6cad40..e8a98d3a 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml @@ -16,3 +16,12 @@ items: - '{lore}' - '' - '{attribute-lore}' + + #Customizable name for the confirmation GUI. + #If none is provided the GUI name will be "Class Confirmation". + class-confirmation-GUI-name: + mage: "Select Mage" + rogue: "Select Rogue" + marksman: "Select Marksman" + warrior: "Select Warrior" + paladin: "Select Paladin" From 5499979567a94aed6ed893d5e6889cb8b44d551d Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 2 Mar 2023 22:37:02 +0100 Subject: [PATCH 21/30] Debug config de base MMOCore --- MMOCore-Dist/src/main/resources/default/professions/fishing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-Dist/src/main/resources/default/professions/fishing.yml b/MMOCore-Dist/src/main/resources/default/professions/fishing.yml index c5972134..80302899 100644 --- a/MMOCore-Dist/src/main/resources/default/professions/fishing.yml +++ b/MMOCore-Dist/src/main/resources/default/professions/fishing.yml @@ -22,7 +22,7 @@ exp-sources: {} on-fish: overriding-drop-table: conditions: - - 'region{name=swamp,second-region}' + - 'region{name="swamp,second-region"}' - 'biome{name=beach}' # When drop table is read, one of these From 2b5932756f30e7d349006b29cdc636777d93ca61 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 3 Mar 2023 10:27:45 +0100 Subject: [PATCH 22/30] Debug Model Data Skill Tree GUI. --- .../net/Indyuce/mmocore/gui/api/adaptor/ThreeDimAdaptor.java | 2 -- .../java/net/Indyuce/mmocore/gui/api/item/InventoryItem.java | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/adaptor/ThreeDimAdaptor.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/adaptor/ThreeDimAdaptor.java index 605ba6b9..0c713c51 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/adaptor/ThreeDimAdaptor.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/adaptor/ThreeDimAdaptor.java @@ -368,10 +368,8 @@ public class ThreeDimAdaptor extends Adaptor { .getEntityFromID(event.getPlayer().getWorld(), packet.getIntegers().read(0)); if (entity instanceof ArmorStand armorStand) { if (true) { - Bukkit.broadcastMessage("IN"); if (armorStands.values().contains(armorStand)) { - Bukkit.broadcastMessage("CANCEL" + armorStand.getName()); event.setCancelled(true); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/item/InventoryItem.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/item/InventoryItem.java index 87a2f0b5..df1d90f3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/item/InventoryItem.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/item/InventoryItem.java @@ -146,7 +146,6 @@ public abstract class InventoryItem { Placeholders placeholders = getPlaceholders(inv, n); ItemStack item = new ItemStack(specificMaterial == null ? material : specificMaterial); ItemMeta meta = item.getItemMeta(); - meta.setCustomModelData(modelData); if (texture != null && meta instanceof SkullMeta) applyTexture(texture, (SkullMeta) meta); @@ -163,7 +162,7 @@ public abstract class InventoryItem { } if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13)) - meta.setCustomModelData(getModelData()); + meta.setCustomModelData(modelData); item.setItemMeta(meta); return item; From 8ac6af34af9a86b60ee32e07852b7e4849695335 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 3 Mar 2023 14:20:56 +0100 Subject: [PATCH 23/30] Cleanup --- .../net/Indyuce/mmocore/api/player/PlayerData.java | 10 +++++----- .../net/Indyuce/mmocore/gui/api/EditableInventory.java | 2 -- .../net/Indyuce/mmocore/manager/InventoryManager.java | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) 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 db412801..6be60b55 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 @@ -222,12 +222,12 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc public void clearSkillTreePoints() { skillTreePoints.clear(); } + public void clearNodeTimesClaimed() { - Map copy= new HashMap<>(tableItemClaims); - copy.forEach((str, val) -> { - if (str.startsWith(SkillTreeNode.KEY_PREFIX)) - tableItemClaims.remove(str); - }); + final Iterator ite = tableItemClaims.keySet().iterator(); + while (ite.hasNext()) + if (ite.next().startsWith(SkillTreeNode.KEY_PREFIX)) + ite.remove(); } public Set> getNodeLevelsEntrySet() { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/EditableInventory.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/EditableInventory.java index f4d7eb60..686f043a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/EditableInventory.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/api/EditableInventory.java @@ -23,7 +23,6 @@ public abstract class EditableInventory { private String name; private int slots; - /* * This set is linked so it keeps the order/priority in * which the items are loaded from the config. @@ -83,7 +82,6 @@ public abstract class EditableInventory { return adaptorType; } - public FileConfiguration getConfig() { return config; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java index 5fd6d2f9..29d61c18 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java @@ -40,7 +40,7 @@ public class InventoryManager { try { inv.reload(new ConfigFile("/gui", inv.getId()).getConfig()); } catch (IllegalArgumentException exception) { - MMOCore.log(Level.WARNING, "Could not load inventory " + inv.getId() + ": " + exception.getMessage()); + MMOCore.log(Level.WARNING, "Could not load inventory '" + inv.getId() + "': " + exception.getMessage()); } }); } From 8c0d8da48384c7a3ae990c56dda784eb593e9c84 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 3 Mar 2023 14:22:43 +0100 Subject: [PATCH 24/30] Moved "class-confirmation-gui-name" option from class-select to class-confirm GUI --- .../mmocore/gui/ClassConfirmation.java | 58 ++++++++++++------- .../net/Indyuce/mmocore/gui/ClassSelect.java | 33 ++++------- .../resources/default/gui/class-confirm.yml | 19 ++++-- .../resources/default/gui/class-select.yml | 9 --- 4 files changed, 60 insertions(+), 59 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java index 64a57eb2..65fd4308 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java @@ -1,7 +1,12 @@ package net.Indyuce.mmocore.gui; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.SoundEvent; +import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent; 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.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.InventoryClickContext; @@ -9,21 +14,29 @@ import net.Indyuce.mmocore.gui.api.PluginInventory; import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; -import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent; -import net.Indyuce.mmocore.api.player.profess.PlayerClass; -import net.Indyuce.mmocore.api.SoundEvent; -import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; public class ClassConfirmation extends EditableInventory { - public ClassConfirmation() { - super("class-confirm"); - } + + /** + * This enables to configure the name of the + * class confirmation GUI (for custom GUI textures). + */ + private final Map specificNames = new HashMap<>(); + + public ClassConfirmation() { + super("class-confirm"); + } @Override public InventoryItem load(String function, ConfigurationSection config) { @@ -34,12 +47,20 @@ public class ClassConfirmation extends EditableInventory { return new ClassConfirmationInventory(data, this, profess, last); } - public GeneratedInventory newInventory(PlayerData data, String GUIName, PlayerClass profess, PluginInventory last) { - return new ClassConfirmationInventory(data, GUIName, this, profess, last); + @Override + public void reload(FileConfiguration config) { + super.reload(config); + + specificNames.clear(); + + if (config.contains("class-specific-name")) { + final ConfigurationSection section = config.getConfigurationSection("class-specific-name"); + for (String key : section.getKeys(false)) + specificNames.put(key, section.getString(key)); + } } public class UnlockedItem extends InventoryItem { - public UnlockedItem(ConfigurationSection config) { super(config); } @@ -50,8 +71,8 @@ public class ClassConfirmation extends EditableInventory { SavedClassInformation info = inv.getPlayerData().getClassInfo(profess); Placeholders holders = new Placeholders(); - int nextLevelExp = inv.getPlayerData().getLevelUpExperience(); - double ratio = (double) info.getExperience() / (double) nextLevelExp; + final double nextLevelExp = inv.getPlayerData().getLevelUpExperience(); + final double ratio = info.getExperience() / nextLevelExp; StringBuilder bar = new StringBuilder("" + ChatColor.BOLD); int chars = (int) (ratio * 20); @@ -102,17 +123,10 @@ public class ClassConfirmation extends EditableInventory { public class ClassConfirmationInventory extends GeneratedInventory { private final PlayerClass profess; private final PluginInventory last; - private String GUIName; public ClassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last) { super(playerData, editable); - this.profess = profess; - this.last = last; - } - public ClassConfirmationInventory(PlayerData playerData, String GUIName, EditableInventory editable, PlayerClass profess, PluginInventory last) { - super(playerData, editable); - this.GUIName = GUIName; this.profess = profess; this.last = last; } @@ -140,9 +154,9 @@ public class ClassConfirmation extends EditableInventory { @Override public String calculateName() { - if (GUIName != null) - return GUIName; - return getName(); + final String professKey = MMOCoreUtils.ymlName(profess.getId()); + final @Nullable String found = specificNames.get(professKey); + return found == null ? getName().replace("{class}", profess.getName()) : found; } } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java index a8c65ccd..9d91c8bf 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java @@ -2,18 +2,17 @@ package net.Indyuce.mmocore.gui; import io.lumine.mythic.lib.MythicLib; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.ConfigMessage; +import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.util.MMOCoreUtils; +import net.Indyuce.mmocore.api.player.profess.ClassOption; +import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.InventoryClickContext; import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; import net.Indyuce.mmocore.manager.InventoryManager; -import net.Indyuce.mmocore.api.ConfigMessage; -import net.Indyuce.mmocore.api.SoundEvent; -import net.Indyuce.mmocore.api.player.profess.ClassOption; -import net.Indyuce.mmocore.api.player.profess.PlayerClass; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.configuration.ConfigurationSection; @@ -22,7 +21,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import java.util.stream.Collectors; public class ClassSelect extends EditableInventory { @@ -42,21 +43,12 @@ public class ClassSelect extends EditableInventory { public class ClassItem extends SimplePlaceholderItem { private final String name; private final List lore; - /** - * This enables to configure the name of the class confirmation GUI (for custom GUI textures). - */ - private final Map classGUINames = new HashMap<>(); public ClassItem(ConfigurationSection config) { super(Material.BARRIER, config); this.name = config.getString("name"); this.lore = config.getStringList("lore"); - if (config.contains("class-confirmation-GUI-name")) { - ConfigurationSection section = config.getConfigurationSection("class-confirmation-GUI-name"); - for (String key : section.getKeys(false)) - classGUINames.put(key, section.getString(key)); - } } public boolean hasDifferentDisplay() { @@ -113,7 +105,6 @@ public class ClassSelect extends EditableInventory { @Override public void whenClicked(InventoryClickContext context, InventoryItem item) { if (item.getFunction().equals("class")) { - ClassItem classItem = (ClassItem) item; String classId = context.getClickedItem().getItemMeta().getPersistentDataContainer().get(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING); if (classId.equals("")) return; @@ -124,7 +115,7 @@ public class ClassSelect extends EditableInventory { return; } - PlayerClass profess = MMOCore.plugin.classManager.get(classId); + final PlayerClass profess = MMOCore.plugin.classManager.get(classId); if (profess.hasOption(ClassOption.NEEDS_PERMISSION) && !player.hasPermission("mmocore.class." + profess.getId().toLowerCase())) { MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player); new ConfigMessage("no-permission-for-class").send(player); @@ -136,13 +127,9 @@ public class ClassSelect extends EditableInventory { MMOCore.plugin.configManager.getSimpleMessage("already-on-class", "class", profess.getName()).send(player); return; } - PlayerClass playerClass = findDeepestSubclass(playerData, profess); - String classKey = MMOCoreUtils.ymlName(playerClass.getName()); - if (classItem.classGUINames.containsKey(classKey)) { - InventoryManager.CLASS_CONFIRM.newInventory(playerData,classItem.classGUINames.get(classKey),playerClass, this).open(); - } else - InventoryManager.CLASS_CONFIRM.newInventory(playerData,playerClass, this).open(); + final PlayerClass playerClass = findDeepestSubclass(playerData, profess); + InventoryManager.CLASS_CONFIRM.newInventory(playerData, playerClass, this).open(); } } } diff --git a/MMOCore-Dist/src/main/resources/default/gui/class-confirm.yml b/MMOCore-Dist/src/main/resources/default/gui/class-confirm.yml index 46aaab4b..089e1b5f 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/class-confirm.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/class-confirm.yml @@ -1,6 +1,15 @@ -# GUI display name -name: Class Confirmation +# GUI display name, used by default +name: 'Confirmation: {class}' + +# GUI display name which overrides the default one. +# This can be used to apply custom textures to the GUI +class-specific-name: + mage: "Select Mage" + rogue: "Select Rogue" + marksman: "Select Marksman" + warrior: "Select Warrior" + paladin: "Select Paladin" # Number of slots in your inventory. Must be # between 9 and 54 and must be a multiple of 9. @@ -10,7 +19,7 @@ items: yes: slots: [12] function: 'yes' - + # Displayed when the player had already selected this class # before (only if class slots are enabled in the config). unlocked: @@ -24,13 +33,13 @@ items: - '' - '&7Skill Points: &6{skill_points}' - '&7Skills You Unlocked: &6{unlocked_skills}&7/&6{class_skills}' - + # Displayed when the class is being chosen for the first time. locked: item: GREEN_TERRACOTTA name: '&aSelect {class}' lore: {} - + back: slots: [14] item: RED_TERRACOTTA diff --git a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml index e8a98d3a..0e6cad40 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml @@ -16,12 +16,3 @@ items: - '{lore}' - '' - '{attribute-lore}' - - #Customizable name for the confirmation GUI. - #If none is provided the GUI name will be "Class Confirmation". - class-confirmation-GUI-name: - mage: "Select Mage" - rogue: "Select Rogue" - marksman: "Select Marksman" - warrior: "Select Warrior" - paladin: "Select Paladin" From 46ea6484142a1d7d72a412898e2404be12369c34 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 3 Mar 2023 14:55:29 +0100 Subject: [PATCH 25/30] Moved close script to party module listener --- .../mmocore/api/player/PlayerData.java | 20 ++----- .../mmocore/party/provided/PartyListener.java | 58 +++++++++++-------- 2 files changed, 38 insertions(+), 40 deletions(-) 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 6be60b55..627a9e22 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 @@ -33,8 +33,6 @@ 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.party.AbstractParty; -import net.Indyuce.mmocore.party.provided.MMOCorePartyModule; -import net.Indyuce.mmocore.party.provided.Party; import net.Indyuce.mmocore.player.ClassDataContainer; import net.Indyuce.mmocore.player.CombatHandler; import net.Indyuce.mmocore.player.Unlockable; @@ -142,11 +140,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc this.mmoData = mmoData; questData = new PlayerQuests(this); playerStats = new PlayerStats(this); - - } - /** * Update all references after /mmocore reload so there can be garbage * collection with old plugin objects like class or skill instances. @@ -372,13 +367,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc @Override public void close() { - // Remove from party if it is MMO Party Module - if (MMOCore.plugin.partyModule instanceof MMOCorePartyModule) { - AbstractParty party = getParty(); - if (party != null && party instanceof Party) - ((Party) party).removeMember(this); - } - // Close combat handler combat.close(); @@ -760,9 +748,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc final double r = Math.sin((double) t / warpTime * Math.PI); for (double j = 0; j < Math.PI * 2; j += Math.PI / 4) getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE, getPlayer().getLocation().add( - Math.cos((double) 5 * t / warpTime + j) * r, - (double) 2 * t / warpTime, - Math.sin((double) 5 * t / warpTime + j) * r), + Math.cos((double) 5 * t / warpTime + j) * r, + (double) 2 * t / warpTime, + Math.sin((double) 5 * t / warpTime + j) * r), 1, new Particle.DustOptions(Color.PURPLE, 1.25f)); } }.runTaskTimer(MMOCore.plugin, 0, 1); @@ -1211,7 +1199,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc * 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/party/provided/PartyListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/PartyListener.java index 17641c26..3d1974fe 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/PartyListener.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/PartyListener.java @@ -1,42 +1,52 @@ package net.Indyuce.mmocore.party.provided; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.event.social.PartyChatEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.manager.ConfigManager; -import net.Indyuce.mmocore.api.event.social.PartyChatEvent; +import net.Indyuce.mmocore.party.AbstractParty; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerQuitEvent; public class PartyListener implements Listener { - private final MMOCorePartyModule module; + private final MMOCorePartyModule module; - public PartyListener(MMOCorePartyModule module) { - this.module = module; - } + public PartyListener(MMOCorePartyModule module) { + this.module = module; + } - @EventHandler(priority = EventPriority.LOW) - public void a(AsyncPlayerChatEvent event) { - if (!event.getMessage().startsWith(MMOCore.plugin.configManager.partyChatPrefix)) - return; + @EventHandler(priority = EventPriority.LOW) + public void partyChat(AsyncPlayerChatEvent event) { + if (!event.getMessage().startsWith(MMOCore.plugin.configManager.partyChatPrefix)) + return; - PlayerData data = PlayerData.get(event.getPlayer()); - Party party = module.getParty(data); - if (party == null) - return; + PlayerData data = PlayerData.get(event.getPlayer()); + Party party = module.getParty(data); + if (party == null) + return; - event.setCancelled(true); + event.setCancelled(true); - // Running it in a delayed task is recommended - Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> { - ConfigManager.SimpleMessage format = MMOCore.plugin.configManager.getSimpleMessage("party-chat", "player", data.getPlayer().getName(), "message", - event.getMessage().substring(MMOCore.plugin.configManager.partyChatPrefix.length())); - PartyChatEvent called = new PartyChatEvent(party, data, format.message()); - Bukkit.getPluginManager().callEvent(called); - if (!called.isCancelled()) - party.getOnlineMembers().forEach(member -> format.send(member.getPlayer())); - }); - } + // Running it in a delayed task is recommended + Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> { + ConfigManager.SimpleMessage format = MMOCore.plugin.configManager.getSimpleMessage("party-chat", "player", data.getPlayer().getName(), "message", + event.getMessage().substring(MMOCore.plugin.configManager.partyChatPrefix.length())); + PartyChatEvent called = new PartyChatEvent(party, data, format.message()); + Bukkit.getPluginManager().callEvent(called); + if (!called.isCancelled()) + party.getOnlineMembers().forEach(member -> format.send(member.getPlayer())); + }); + } + + @EventHandler(priority = EventPriority.LOW) + public void leavePartyOnQuit(PlayerQuitEvent event) { + final PlayerData playerData = PlayerData.get(event.getPlayer()); + final AbstractParty party = playerData.getParty(); + if (party != null) + ((Party) party).removeMember(playerData); + } } From 5e73e41fa88ffcd08f8c893ba37f13ce6a24eab2 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 3 Mar 2023 15:22:54 +0100 Subject: [PATCH 26/30] Cleanup --- .../manager/data/PlayerDataManager.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index eb28ae71..b471fd7d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -11,6 +11,7 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -79,24 +80,23 @@ public abstract class PlayerDataManager { public PlayerData setup(UUID uniqueId) { // Load player data if it does not exist - if (!data.containsKey(uniqueId)) { - PlayerData newData = new PlayerData(MMOPlayerData.get(uniqueId)); + final @Nullable PlayerData current = data.get(uniqueId); + if (current != null) + return current; - // Schedule async data loading - Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> { - loadData(newData); - newData.getStats().updateStats(); - Bukkit.getPluginManager().callEvent(new AsyncPlayerDataLoadEvent(newData)); - Bukkit.getScheduler().runTask(MMOCore.plugin, () -> Bukkit.getPluginManager().callEvent(new PlayerDataLoadEvent(newData))); - }); + final PlayerData newData = new PlayerData(MMOPlayerData.get(uniqueId)); - // Update data map - data.put(uniqueId, newData); + // Schedule async data loading + Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> { + loadData(newData); + newData.getStats().updateStats(); + Bukkit.getPluginManager().callEvent(new AsyncPlayerDataLoadEvent(newData)); + Bukkit.getScheduler().runTask(MMOCore.plugin, () -> Bukkit.getPluginManager().callEvent(new PlayerDataLoadEvent(newData))); + }); - return newData; - } - - return data.get(uniqueId); + // Update data map and return + data.put(uniqueId, newData); + return newData; } public DefaultPlayerData getDefaultData() { From 393fddf497137db182ef6f973647a87a7680318a Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 3 Mar 2023 16:00:45 +0100 Subject: [PATCH 27/30] Cleanup --- .../main/java/net/Indyuce/mmocore/experience/Profession.java | 5 ++--- .../mmocore/experience/source/MineBlockExperienceSource.java | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java index 34d33106..4a152548 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java @@ -4,8 +4,8 @@ import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.util.PostLoadObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.api.util.math.formula.LinearValue; +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; @@ -125,8 +125,7 @@ public class Profession extends PostLoadObject implements ExperienceObject { @Override public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) { - hologramLocation = !getOption(Profession.ProfessionOption.EXP_HOLOGRAMS) ? null - : hologramLocation; + hologramLocation = !getOption(Profession.ProfessionOption.EXP_HOLOGRAMS) ? null : hologramLocation; playerData.getCollectionSkills().giveExperience(this, experience, EXPSource.SOURCE, hologramLocation, true); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MineBlockExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MineBlockExperienceSource.java index 6de8fb5f..e889bd8a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MineBlockExperienceSource.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MineBlockExperienceSource.java @@ -64,7 +64,6 @@ public class MineBlockExperienceSource extends SpecificExperienceSource Date: Fri, 3 Mar 2023 16:12:37 +0100 Subject: [PATCH 28/30] Removed default exp holos for the exp trigger. --- .../net/Indyuce/mmocore/experience/SimpleExperienceObject.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java index 87e013c7..921d1438 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java @@ -10,8 +10,7 @@ public class SimpleExperienceObject implements ExperienceDispenser { @Override public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) { - hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null - : hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation; + hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null : hologramLocation; playerData.giveExperience(experience, source, hologramLocation, true); } From 825473c8c69fcc836e715d438966e90d257d57e2 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 3 Mar 2023 21:59:47 +0100 Subject: [PATCH 29/30] Debug ressources loading. --- .../mmocore/manager/data/yaml/YAMLPlayerDataManager.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java index fb3cde48..eabe5e83 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java @@ -44,10 +44,6 @@ public class YAMLPlayerDataManager extends PlayerDataManager { if (config.contains("class")) data.setClass(MMOCore.plugin.classManager.get(config.getString("class"))); - data.setMana(config.contains("mana") ? config.getDouble("mana") : data.getStats().getStat("MAX_MANA")); - data.setStamina(config.contains("stamina") ? config.getDouble("stamina") : data.getStats().getStat("MAX_STAMINA")); - data.setStellium(config.contains("stellium") ? config.getDouble("stellium") : data.getStats().getStat("MAX_STELLIUM")); - if (config.contains("guild")) { Guild guild = provider.getGuildManager().getGuild(config.getString("guild")); data.setGuild(guild.hasMember(data.getUniqueId()) ? guild : null); @@ -117,6 +113,11 @@ public class YAMLPlayerDataManager extends PlayerDataManager { } + //These should be loaded after to make sure that the MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded. + data.setMana(config.contains("mana") ? config.getDouble("mana") : data.getStats().getStat("MAX_MANA")); + data.setStamina(config.contains("stamina") ? config.getDouble("stamina") : data.getStats().getStat("MAX_STAMINA")); + data.setStellium(config.contains("stellium") ? config.getDouble("stellium") : data.getStats().getStat("MAX_STELLIUM")); + data.setFullyLoaded(); } From 3239b9ca1759abf839e01276ece2713943aee372 Mon Sep 17 00:00:00 2001 From: Jules Date: Thu, 9 Mar 2023 17:53:54 +0100 Subject: [PATCH 30/30] Test push --- MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ac307ed7..71d465c4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -172,8 +172,8 @@ public class MMOCore extends JavaPlugin { } /* - * Resource regeneration. Must check if entity is dead otherwise regen will make - * the 'respawn' button glitched plus HURT entity effect bug + * 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() {