diff --git a/Changelog.txt b/Changelog.txt index 144a86617..b95ab27ff 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,5 +1,7 @@ Version 2.2.038 Fix potion match failing for non-english locales + FoliaLib Performance improvements (thanks SirSalad) + Fixed situations where Rupture could never end which affected server performance Version 2.2.037 Fixed bug where Alchemy was not matching potions correctly and producing incorrect results (Thanks TheBentoBox) diff --git a/pom.xml b/pom.xml index 04bc57fcb..21dc97b49 100644 --- a/pom.xml +++ b/pom.xml @@ -464,7 +464,7 @@ com.github.technicallycoded FoliaLib - dev-SNAPSHOT + main-SNAPSHOT compile diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index 9624a0d99..6ff677993 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -21,6 +21,7 @@ import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.runnables.skills.AbilityDisableTask; +import com.gmail.nossr50.runnables.skills.RuptureTask; import com.gmail.nossr50.runnables.skills.ToolLowerTask; import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; @@ -1144,14 +1145,17 @@ public class McMMOPlayer implements Identified { * @param syncSave if true, data is saved synchronously */ public void logout(boolean syncSave) { - Player thisPlayer = getPlayer(); - if (getPlayer().hasMetadata(MetadataConstants.METADATA_KEY_RUPTURE)) { - RuptureTaskMeta ruptureTaskMeta = (RuptureTaskMeta) getPlayer().getMetadata(MetadataConstants.METADATA_KEY_RUPTURE).get(0); - - //Punish a logout - ruptureTaskMeta.getRuptureTimerTask().endRupture(); - ruptureTaskMeta.getRuptureTimerTask().endRupture(); - ruptureTaskMeta.getRuptureTimerTask().endRupture(); + final Player thisPlayer = getPlayer(); + if (getPlayer() != null && getPlayer().hasMetadata(MetadataConstants.METADATA_KEY_RUPTURE)) { + final RuptureTaskMeta ruptureTaskMeta + = (RuptureTaskMeta) getPlayer().getMetadata(MetadataConstants.METADATA_KEY_RUPTURE).get(0); + if (ruptureTaskMeta != null) { + final RuptureTask ruptureTimerTask = ruptureTaskMeta.getRuptureTimerTask(); + if(ruptureTimerTask != null) { + ruptureTimerTask.cancel(); + } + getPlayer().removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p); + } } cleanup(); diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 90976b638..3d576d859 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -662,7 +662,7 @@ public class EntityListener implements Listener { */ @EventHandler(priority = EventPriority.LOWEST) public void onEntityDeathLowest(EntityDeathEvent event) { - LivingEntity entity = event.getEntity(); + final LivingEntity entity = event.getEntity(); // Clear metadata for Slimes/Magma Cubes after transformation events take place, otherwise small spawned slimes will not have any tags if (TRANSFORMABLE_ENTITIES.contains(entity.getType())) { @@ -680,7 +680,7 @@ public class EntityListener implements Listener { */ @EventHandler(ignoreCancelled = true) public void onEntityDeath(EntityDeathEvent event) { - LivingEntity entity = event.getEntity(); + final LivingEntity entity = event.getEntity(); if (mcMMO.getTransientEntityTracker().isTransient(entity)) { mcMMO.getTransientEntityTracker().killSummonAndCleanMobFlags(entity, null, false); diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index 3a95cb9f5..6ec4e2015 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -10,7 +10,6 @@ import com.gmail.nossr50.datatypes.skills.subskills.taming.CallOfTheWildType; import com.gmail.nossr50.events.McMMOReplaceVanillaTreasureEvent; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.runnables.MobHealthDisplayUpdaterTask; import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask; import com.gmail.nossr50.skills.fishing.FishingManager; @@ -26,8 +25,6 @@ import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillUtils; -import com.gmail.nossr50.util.sounds.SoundManager; -import com.gmail.nossr50.util.sounds.SoundType; import com.gmail.nossr50.worldguard.WorldGuardManager; import com.gmail.nossr50.worldguard.WorldGuardUtils; import org.bukkit.Bukkit; diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 224b503c2..f3813090a 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -162,6 +162,7 @@ public class mcMMO extends JavaPlugin { //Folia lib plugin instance foliaLib = new FoliaLib(this); InvalidTickDelayNotifier.disableNotifications = true; + foliaPerformanceHack(); setupFilePaths(); generalConfig = new GeneralConfig(getDataFolder()); //Load before skillTools @@ -315,6 +316,21 @@ public class mcMMO extends JavaPlugin { } } + private void foliaPerformanceHack() { + // Thanks SirSalad + // https://github.com/CraftYourTown/mcMMO/commit/2cffd64b127678411e20f0b8f9a3e3b87a649ee8 + try { + com.tcoded.folialib.impl.FoliaImplementation setScheduler + = new com.tcoded.folialib.impl.FoliaImplementation(foliaLib); + java.lang.reflect.Field FoliaLib$scheduler = FoliaLib.class.getDeclaredField("scheduler"); + FoliaLib$scheduler.setAccessible(true); + FoliaLib$scheduler.set(foliaLib, setScheduler); + FoliaLib$scheduler.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + getLogger().warning("Unable to apply performance tweaks to FoliaLib"); + } + } + public static PlayerLevelUtils getPlayerLevelUtils() { return playerLevelUtils; } diff --git a/src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java b/src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java index 4c43d3e7f..93db0250c 100644 --- a/src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java @@ -28,6 +28,9 @@ public class RuptureTask extends CancellableRunnable { private int damageTickTracker; private int animationTick; private final double pureTickDamage; + // failsafe to ensure Rupture always exits and does not run forever + private int totalTicks = 0; + private final int totalTickCeiling; /** * Constructor for the RuptureTask class. @@ -41,7 +44,7 @@ public class RuptureTask extends CancellableRunnable { this.ruptureSource = ruptureSource; this.targetEntity = targetEntity; this.expireTick = mcMMO.p.getAdvancedConfig().getRuptureDurationSeconds(targetEntity instanceof Player) * 20; - + this.totalTickCeiling = Math.min(this.expireTick, 200); this.ruptureTick = 0; this.damageTickTracker = 0; this.animationTick = ANIMATION_TICK_INTERVAL; //Play an animation right away @@ -68,6 +71,14 @@ public class RuptureTask extends CancellableRunnable { @Override public void run() { + // always increment the fail-safe + totalTicks++; + + if (totalTicks >= totalTickCeiling) { + this.cancel(); + return; + } + //Check validity if (targetEntity.isValid()) { ruptureTick += 1; //Advance rupture tick by 1. @@ -78,7 +89,6 @@ public class RuptureTask extends CancellableRunnable { if (ruptureTick < expireTick) { //Is it time to damage? if (damageTickTracker >= DAMAGE_TICK_INTERVAL) { - damageTickTracker = 0; //Reset timer if (applyRupture()) return; @@ -92,8 +102,8 @@ public class RuptureTask extends CancellableRunnable { endRupture(); } } else { - targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p); this.cancel(); //Task no longer needed + targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p); } } @@ -152,7 +162,7 @@ public class RuptureTask extends CancellableRunnable { ruptureTick = 0; } - public void endRupture() { + private void endRupture() { targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p); this.cancel(); //Task no longer needed } @@ -171,6 +181,20 @@ public class RuptureTask extends CancellableRunnable { return tickDamage; } + @Override + public final boolean equals(Object o) { + if (!(o instanceof RuptureTask that)) return false; + + return ruptureSource.equals(that.ruptureSource) && targetEntity.equals(that.targetEntity); + } + + @Override + public int hashCode() { + int result = ruptureSource.hashCode(); + result = 31 * result + targetEntity.hashCode(); + return result; + } + @Override public String toString() { return "RuptureTask{" + @@ -179,25 +203,10 @@ public class RuptureTask extends CancellableRunnable { ", expireTick=" + expireTick + ", ruptureTick=" + ruptureTick + ", damageTickTracker=" + damageTickTracker + + ", animationTick=" + animationTick + ", pureTickDamage=" + pureTickDamage + + ", totalTicks=" + totalTicks + + ", totalTickCeiling=" + totalTickCeiling + '}'; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RuptureTask that = (RuptureTask) o; - return expireTick == that.expireTick - && ruptureTick == that.ruptureTick - && damageTickTracker == that.damageTickTracker - && Double.compare(that.pureTickDamage, pureTickDamage) == 0 - && Objects.equal(ruptureSource, that.ruptureSource) && Objects.equal(targetEntity, that.targetEntity); - } - - @Override - public int hashCode() { - return Objects.hashCode(ruptureSource, targetEntity, expireTick, - ruptureTick, damageTickTracker, pureTickDamage); - } } diff --git a/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java b/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java index 3fdf83352..2b70f90ec 100644 --- a/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java @@ -10,7 +10,6 @@ import com.gmail.nossr50.datatypes.skills.ToolType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.runnables.skills.RuptureTask; import com.gmail.nossr50.skills.SkillManager; -import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.MetadataConstants; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.NotificationManager; @@ -20,7 +19,6 @@ import com.gmail.nossr50.util.skills.RankUtils; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; public class SwordsManager extends SkillManager { diff --git a/src/main/java/com/gmail/nossr50/util/ContainerMetadataUtils.java b/src/main/java/com/gmail/nossr50/util/ContainerMetadataUtils.java index 516394c21..3844b4f0e 100644 --- a/src/main/java/com/gmail/nossr50/util/ContainerMetadataUtils.java +++ b/src/main/java/com/gmail/nossr50/util/ContainerMetadataUtils.java @@ -1,8 +1,6 @@ package com.gmail.nossr50.util; import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.skills.PrimarySkillType; -import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.player.UserManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -19,7 +17,6 @@ import java.util.UUID; import static com.gmail.nossr50.util.MetadataService.NSK_CONTAINER_UUID_LEAST_SIG; import static com.gmail.nossr50.util.MetadataService.NSK_CONTAINER_UUID_MOST_SIG; -import static java.util.Objects.requireNonNull; public class ContainerMetadataUtils { diff --git a/src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java b/src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java index 609fe76ea..95e8be785 100644 --- a/src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java +++ b/src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java @@ -9,8 +9,6 @@ import com.gmail.nossr50.util.skills.RankUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.junit.jupiter.api.AfterEach;