perf improvements and rupture improvements

This commit is contained in:
nossr50 2025-06-06 18:43:41 -07:00
parent 27a232d03e
commit 382b86ad34
10 changed files with 64 additions and 43 deletions

View File

@ -1,5 +1,7 @@
Version 2.2.038 Version 2.2.038
Fix potion match failing for non-english locales 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 Version 2.2.037
Fixed bug where Alchemy was not matching potions correctly and producing incorrect results (Thanks TheBentoBox) Fixed bug where Alchemy was not matching potions correctly and producing incorrect results (Thanks TheBentoBox)

View File

@ -464,7 +464,7 @@
<dependency> <dependency>
<groupId>com.github.technicallycoded</groupId> <groupId>com.github.technicallycoded</groupId>
<artifactId>FoliaLib</artifactId> <artifactId>FoliaLib</artifactId>
<version>dev-SNAPSHOT</version> <version>main-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -21,6 +21,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.party.ShareHandler;
import com.gmail.nossr50.runnables.skills.AbilityDisableTask; 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.runnables.skills.ToolLowerTask;
import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
@ -1144,14 +1145,17 @@ public class McMMOPlayer implements Identified {
* @param syncSave if true, data is saved synchronously * @param syncSave if true, data is saved synchronously
*/ */
public void logout(boolean syncSave) { public void logout(boolean syncSave) {
Player thisPlayer = getPlayer(); final Player thisPlayer = getPlayer();
if (getPlayer().hasMetadata(MetadataConstants.METADATA_KEY_RUPTURE)) { if (getPlayer() != null && getPlayer().hasMetadata(MetadataConstants.METADATA_KEY_RUPTURE)) {
RuptureTaskMeta ruptureTaskMeta = (RuptureTaskMeta) getPlayer().getMetadata(MetadataConstants.METADATA_KEY_RUPTURE).get(0); final RuptureTaskMeta ruptureTaskMeta
= (RuptureTaskMeta) getPlayer().getMetadata(MetadataConstants.METADATA_KEY_RUPTURE).get(0);
//Punish a logout if (ruptureTaskMeta != null) {
ruptureTaskMeta.getRuptureTimerTask().endRupture(); final RuptureTask ruptureTimerTask = ruptureTaskMeta.getRuptureTimerTask();
ruptureTaskMeta.getRuptureTimerTask().endRupture(); if(ruptureTimerTask != null) {
ruptureTaskMeta.getRuptureTimerTask().endRupture(); ruptureTimerTask.cancel();
}
getPlayer().removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p);
}
} }
cleanup(); cleanup();

View File

@ -662,7 +662,7 @@ public class EntityListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onEntityDeathLowest(EntityDeathEvent event) { 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 // 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())) { if (TRANSFORMABLE_ENTITIES.contains(entity.getType())) {
@ -680,7 +680,7 @@ public class EntityListener implements Listener {
*/ */
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onEntityDeath(EntityDeathEvent event) { public void onEntityDeath(EntityDeathEvent event) {
LivingEntity entity = event.getEntity(); final LivingEntity entity = event.getEntity();
if (mcMMO.getTransientEntityTracker().isTransient(entity)) { if (mcMMO.getTransientEntityTracker().isTransient(entity)) {
mcMMO.getTransientEntityTracker().killSummonAndCleanMobFlags(entity, null, false); mcMMO.getTransientEntityTracker().killSummonAndCleanMobFlags(entity, null, false);

View File

@ -10,7 +10,6 @@ import com.gmail.nossr50.datatypes.skills.subskills.taming.CallOfTheWildType;
import com.gmail.nossr50.events.McMMOReplaceVanillaTreasureEvent; import com.gmail.nossr50.events.McMMOReplaceVanillaTreasureEvent;
import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.ShareHandler;
import com.gmail.nossr50.runnables.MobHealthDisplayUpdaterTask; import com.gmail.nossr50.runnables.MobHealthDisplayUpdaterTask;
import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask; import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask;
import com.gmail.nossr50.skills.fishing.FishingManager; 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.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils; 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.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils; import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;

View File

@ -162,6 +162,7 @@ public class mcMMO extends JavaPlugin {
//Folia lib plugin instance //Folia lib plugin instance
foliaLib = new FoliaLib(this); foliaLib = new FoliaLib(this);
InvalidTickDelayNotifier.disableNotifications = true; InvalidTickDelayNotifier.disableNotifications = true;
foliaPerformanceHack();
setupFilePaths(); setupFilePaths();
generalConfig = new GeneralConfig(getDataFolder()); //Load before skillTools 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() { public static PlayerLevelUtils getPlayerLevelUtils() {
return playerLevelUtils; return playerLevelUtils;
} }

View File

@ -28,6 +28,9 @@ public class RuptureTask extends CancellableRunnable {
private int damageTickTracker; private int damageTickTracker;
private int animationTick; private int animationTick;
private final double pureTickDamage; 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. * Constructor for the RuptureTask class.
@ -41,7 +44,7 @@ public class RuptureTask extends CancellableRunnable {
this.ruptureSource = ruptureSource; this.ruptureSource = ruptureSource;
this.targetEntity = targetEntity; this.targetEntity = targetEntity;
this.expireTick = mcMMO.p.getAdvancedConfig().getRuptureDurationSeconds(targetEntity instanceof Player) * 20; this.expireTick = mcMMO.p.getAdvancedConfig().getRuptureDurationSeconds(targetEntity instanceof Player) * 20;
this.totalTickCeiling = Math.min(this.expireTick, 200);
this.ruptureTick = 0; this.ruptureTick = 0;
this.damageTickTracker = 0; this.damageTickTracker = 0;
this.animationTick = ANIMATION_TICK_INTERVAL; //Play an animation right away this.animationTick = ANIMATION_TICK_INTERVAL; //Play an animation right away
@ -68,6 +71,14 @@ public class RuptureTask extends CancellableRunnable {
@Override @Override
public void run() { public void run() {
// always increment the fail-safe
totalTicks++;
if (totalTicks >= totalTickCeiling) {
this.cancel();
return;
}
//Check validity //Check validity
if (targetEntity.isValid()) { if (targetEntity.isValid()) {
ruptureTick += 1; //Advance rupture tick by 1. ruptureTick += 1; //Advance rupture tick by 1.
@ -78,7 +89,6 @@ public class RuptureTask extends CancellableRunnable {
if (ruptureTick < expireTick) { if (ruptureTick < expireTick) {
//Is it time to damage? //Is it time to damage?
if (damageTickTracker >= DAMAGE_TICK_INTERVAL) { if (damageTickTracker >= DAMAGE_TICK_INTERVAL) {
damageTickTracker = 0; //Reset timer damageTickTracker = 0; //Reset timer
if (applyRupture()) return; if (applyRupture()) return;
@ -92,8 +102,8 @@ public class RuptureTask extends CancellableRunnable {
endRupture(); endRupture();
} }
} else { } else {
targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p);
this.cancel(); //Task no longer needed 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; ruptureTick = 0;
} }
public void endRupture() { private void endRupture() {
targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p); targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p);
this.cancel(); //Task no longer needed this.cancel(); //Task no longer needed
} }
@ -171,6 +181,20 @@ public class RuptureTask extends CancellableRunnable {
return tickDamage; 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 @Override
public String toString() { public String toString() {
return "RuptureTask{" + return "RuptureTask{" +
@ -179,25 +203,10 @@ public class RuptureTask extends CancellableRunnable {
", expireTick=" + expireTick + ", expireTick=" + expireTick +
", ruptureTick=" + ruptureTick + ", ruptureTick=" + ruptureTick +
", damageTickTracker=" + damageTickTracker + ", damageTickTracker=" + damageTickTracker +
", animationTick=" + animationTick +
", pureTickDamage=" + pureTickDamage + ", 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);
}
} }

View File

@ -10,7 +10,6 @@ import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.skills.RuptureTask; import com.gmail.nossr50.runnables.skills.RuptureTask;
import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.MetadataConstants; import com.gmail.nossr50.util.MetadataConstants;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager; 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.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class SwordsManager extends SkillManager { public class SwordsManager extends SkillManager {

View File

@ -1,8 +1,6 @@
package com.gmail.nossr50.util; package com.gmail.nossr50.util;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; 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 com.gmail.nossr50.util.player.UserManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; 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_LEAST_SIG;
import static com.gmail.nossr50.util.MetadataService.NSK_CONTAINER_UUID_MOST_SIG; import static com.gmail.nossr50.util.MetadataService.NSK_CONTAINER_UUID_MOST_SIG;
import static java.util.Objects.requireNonNull;
public class ContainerMetadataUtils { public class ContainerMetadataUtils {

View File

@ -9,8 +9,6 @@ import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;