diff --git a/pom.xml b/pom.xml
index bf353a24..f4b882e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -156,7 +156,7 @@
com.github.Zrips
Jobs
- 4.17.2
+ v5.2.2.3
provided
@@ -173,6 +173,12 @@
system
${project.basedir}/jars/MyPet-3.11-SNAPSHOT-B1627.jar
+
+ me.lucko
+ spark-api
+ 0.1-SNAPSHOT
+ provided
+
-
+
\ No newline at end of file
diff --git a/src/main/java/uk/antiperson/stackmob/StackMob.java b/src/main/java/uk/antiperson/stackmob/StackMob.java
index bfde8209..ee59d5d1 100644
--- a/src/main/java/uk/antiperson/stackmob/StackMob.java
+++ b/src/main/java/uk/antiperson/stackmob/StackMob.java
@@ -1,7 +1,6 @@
package uk.antiperson.stackmob;
import org.bstats.bukkit.Metrics;
-import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.command.PluginCommand;
import org.bukkit.event.Listener;
@@ -14,6 +13,10 @@
import uk.antiperson.stackmob.entity.traits.TraitManager;
import uk.antiperson.stackmob.hook.HookManager;
import uk.antiperson.stackmob.listeners.*;
+import uk.antiperson.stackmob.mspt.DummyMsptProvider;
+import uk.antiperson.stackmob.mspt.MsptProvider;
+import uk.antiperson.stackmob.mspt.PaperMsptProvider;
+import uk.antiperson.stackmob.mspt.SparkMsptProvider;
import uk.antiperson.stackmob.scheduler.BukkitScheduler;
import uk.antiperson.stackmob.scheduler.FoliaScheduler;
import uk.antiperson.stackmob.scheduler.Scheduler;
@@ -39,6 +42,7 @@ public class StackMob extends JavaPlugin {
private Updater updater;
private ItemTools itemTools;
private Scheduler scheduler;
+ private MsptProvider msptProvider;
private boolean stepDamageError;
@@ -114,7 +118,17 @@ public void onEnable() {
case AVAILABLE: getLogger().info("A new version is currently available. (" + updateResult.getNewVersion() + ")"); break;
}
}));
-
+ if (!Utilities.isPaper()) {
+ getLogger().warning("It has been detected that you are not using Paper (https://papermc.io).");
+ getLogger().warning("StackMob makes use of Paper's API, which means you're missing out on features.");
+ }
+ if (this.getServer().getPluginManager().getPlugin("Spark") != null){
+ this.msptProvider = new SparkMsptProvider();
+ } else if (Utilities.isPaper()) {
+ this.msptProvider = new PaperMsptProvider();
+ } else {
+ this.msptProvider = new DummyMsptProvider();
+ }
new Metrics(this, 522);
}
@@ -165,6 +179,10 @@ private void registerEvent(Class extends Listener> clazz) throws NoSuchMethodE
getServer().getPluginManager().registerEvents(listener, this);
}
+ public MsptProvider getMsptProvider() {
+ return msptProvider;
+ }
+
public EntityTranslation getEntityTranslation() {
return entityTranslation;
}
diff --git a/src/main/java/uk/antiperson/stackmob/config/EntityConfig.java b/src/main/java/uk/antiperson/stackmob/config/EntityConfig.java
index d8dadb8c..625596c8 100644
--- a/src/main/java/uk/antiperson/stackmob/config/EntityConfig.java
+++ b/src/main/java/uk/antiperson/stackmob/config/EntityConfig.java
@@ -117,6 +117,18 @@ public String getTagFormat() {
return getString("display-name.format");
}
+ public boolean isMsptReactiveEnabled() {
+ return getBoolean("mspt-reactive.enabled");
+ }
+
+ public double getMsptReactiveTriggerThreshold() {
+ return getDouble("mspt-reactive.trigger-mspt-threshold");
+ }
+
+ public double getMsptReactiveUntriggerThreshold() {
+ return getDouble("mspt-reactive.untrigger-mspt-threshold");
+ }
+
public int getTagThreshold() {
return getInt( "display-name.threshold");
}
diff --git a/src/main/java/uk/antiperson/stackmob/mspt/DummyMsptProvider.java b/src/main/java/uk/antiperson/stackmob/mspt/DummyMsptProvider.java
new file mode 100644
index 00000000..cefc8914
--- /dev/null
+++ b/src/main/java/uk/antiperson/stackmob/mspt/DummyMsptProvider.java
@@ -0,0 +1,17 @@
+package uk.antiperson.stackmob.mspt;
+
+public class DummyMsptProvider extends MsptProvider {
+
+ @Override
+ public double getMspt() {
+ return 0;
+ }
+
+ @Override
+ public void setUnderLoad(boolean underLoad) { }
+
+ @Override
+ public boolean isUnderLoad() {
+ return false;
+ }
+}
diff --git a/src/main/java/uk/antiperson/stackmob/mspt/MsptProvider.java b/src/main/java/uk/antiperson/stackmob/mspt/MsptProvider.java
new file mode 100644
index 00000000..e2eb3e47
--- /dev/null
+++ b/src/main/java/uk/antiperson/stackmob/mspt/MsptProvider.java
@@ -0,0 +1,15 @@
+package uk.antiperson.stackmob.mspt;
+
+public abstract class MsptProvider {
+
+ private boolean underLoad;
+
+ public abstract double getMspt();
+ public void setUnderLoad(boolean underLoad) {
+ this.underLoad = underLoad;
+ }
+ public boolean isUnderLoad() {
+ return this.underLoad;
+ }
+
+}
diff --git a/src/main/java/uk/antiperson/stackmob/mspt/PaperMsptProvider.java b/src/main/java/uk/antiperson/stackmob/mspt/PaperMsptProvider.java
new file mode 100644
index 00000000..dd649dee
--- /dev/null
+++ b/src/main/java/uk/antiperson/stackmob/mspt/PaperMsptProvider.java
@@ -0,0 +1,11 @@
+package uk.antiperson.stackmob.mspt;
+
+import org.bukkit.Bukkit;
+
+public class PaperMsptProvider extends MsptProvider {
+
+ @Override
+ public double getMspt() {
+ return Bukkit.getAverageTickTime();
+ }
+}
diff --git a/src/main/java/uk/antiperson/stackmob/mspt/SparkMsptProvider.java b/src/main/java/uk/antiperson/stackmob/mspt/SparkMsptProvider.java
new file mode 100644
index 00000000..71154f0d
--- /dev/null
+++ b/src/main/java/uk/antiperson/stackmob/mspt/SparkMsptProvider.java
@@ -0,0 +1,22 @@
+package uk.antiperson.stackmob.mspt;
+
+import me.lucko.spark.api.Spark;
+import me.lucko.spark.api.SparkProvider;
+import me.lucko.spark.api.statistic.StatisticWindow;
+
+public class SparkMsptProvider extends MsptProvider {
+
+ private final Spark spark;
+
+ public SparkMsptProvider(){
+ this.spark = SparkProvider.get();
+ }
+
+ @Override
+ public double getMspt() {
+ if(this.spark.mspt() == null){
+ return 0;
+ }
+ return this.spark.mspt().poll(StatisticWindow.MillisPerTick.SECONDS_10).mean();
+ }
+}
diff --git a/src/main/java/uk/antiperson/stackmob/tasks/MergeTask.java b/src/main/java/uk/antiperson/stackmob/tasks/MergeTask.java
index 2debc0ea..33c99f43 100644
--- a/src/main/java/uk/antiperson/stackmob/tasks/MergeTask.java
+++ b/src/main/java/uk/antiperson/stackmob/tasks/MergeTask.java
@@ -18,7 +18,24 @@ public MergeTask(StackMob sm) {
this.sm = sm;
}
- private void checkEntity(StackEntity original, boolean checkHasMoved, double checkHasMovedDistance) {
+ private void checkEntity(StackEntity original, boolean checkHasMoved, double checkHasMovedDistance, boolean checkMspt) {
+ if(checkMspt){
+ if (sm.getMsptProvider().isUnderLoad()){
+ if (sm.getMsptProvider().getMspt()<=original.getEntityConfig().getMsptReactiveUntriggerThreshold()){
+ // mspt was under heavy load, but no longer is, reset its status and skip stacking
+ sm.getMsptProvider().setUnderLoad(false);
+ return;
+ }
+ } else {
+ if (sm.getMsptProvider().getMspt()>=original.getEntityConfig().getMsptReactiveTriggerThreshold()){
+ // mspt is considered to be under heavy load, set under load to keep hysteresis status
+ sm.getMsptProvider().setUnderLoad(true);
+ } else {
+ // mspt is lower than the trigger threshold, skip stacking
+ return;
+ }
+ }
+ }
if (original.isWaiting()) {
original.incrementWait();
return;
@@ -101,8 +118,9 @@ private void removeEntity(StackEntity stackEntity) {
public void run() {
boolean checkHasMoved = sm.getMainConfig().getConfig().isCheckHasMoved();
double checkHasMovedDistance = sm.getMainConfig().getConfig().getCheckHasMovedDistance();
+ boolean checkMspt = sm.getMainConfig().getConfig().isMsptReactiveEnabled();
for (StackEntity original : sm.getEntityManager().getStackEntities()) {
- Runnable runnable = () -> checkEntity(original, checkHasMoved, checkHasMovedDistance);
+ Runnable runnable = () -> checkEntity(original, checkHasMoved, checkHasMovedDistance, checkMspt);
if (Utilities.IS_FOLIA) {
sm.getScheduler().runTask(original.getEntity(), runnable);
} else {
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index c827d2be..43701383 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -301,6 +301,16 @@ wait-to-stack:
- SPAWNER
reasons-whitelist-invert: false
+# Enable the system based on MSPT. The MSPT will be updated as often as stack.interval
+# you should use paper or install Spark for this feature to work! (**)
+mspt-reactive:
+ enabled: false
+ # Above what MSPT should the reactive mode be triggered?
+ trigger-mspt-threshold: 65.0
+ # Below what MSPT should the reactive mode be untriggered?
+ untrigger-mspt-threshold: 45.0
+
+
# Enable/disable integration with other plugins. (*)
hooks:
# Allows the custom 'entity-stacking' flag to be used in worldguard regions.
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 4a5a519c..f3878ff9 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -3,7 +3,8 @@ main: uk.antiperson.stackmob.StackMob
version: ${project.version}
api-version: 1.16
folia-supported: true
-softdepend: [WorldGuard, MythicMobs, ClearLag, MyPet, mcMMO, Jobs, Citizens]
+depend: [ProtocolLib]
+softdepend: [WorldGuard, MythicMobs, ClearLag, MyPet, mcMMO, Jobs, Citizens, Spark]
author: antiPerson
website: https://modrinth.com/plugin/stackmob
description: A plugin that aims to improve performance by 'stacking' entities together, with attempts to preserve game mechanics.