mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-04-20 10:18:16 +02:00
Upstream has released updates that appears to apply and compile correctly Paper Changes: cf82dad3 Fix Non Full Status Chunk NBT Memory Leak 5a12515a Update Log4J Configuration file to stop truncating stack traces 7c001d64 More Improvements to Chunks e1c45196 Fix high memory use of non ticking chunks ee9f0d51 Fix another case of breaking blocks causing sync chunk loads 6009ba8f Drop AABB limit patch until it can be tested more 0e9c24e5 Fix log spam about Hanging entities bounding boxes 83fadad7 Fix conversion for deserializing raw nbt itemstacks - Fixes #3424 4d38ee11 Many fixes and improvements to chunk prioritization 281181c7 Use saner Entity bounding box limits edd6b6a2 Protect the visible chunk map from plugins touching it, trim Timing Errors 18c68657 Optimize performance of object pool 7e1525ea Many improvements to chunk prioritization and bug fixes c82b292a Fix pooled buffer leak resulting in dynmap black spots - Fixes #3386 63274472 Fix ./paper edit continue for Windows eb5a3058 Fix path in CONTRIBUTING.md (#3406) f6ed326d Fix a small error in CONTRIBUTING.md (#3403) 614a664b Implement Chunk Priority / Urgency System for Chunks
304 lines
14 KiB
Diff
304 lines
14 KiB
Diff
From 08028ae0a027ecced21386341be053dc433ec59f Mon Sep 17 00:00:00 2001
|
|
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
|
Date: Thu, 8 Aug 2019 15:29:15 -0500
|
|
Subject: [PATCH] Implement AFK API
|
|
|
|
---
|
|
.../java/net/minecraft/server/Entity.java | 1 +
|
|
.../net/minecraft/server/EntityHuman.java | 9 ++++
|
|
.../net/minecraft/server/EntityPlayer.java | 43 +++++++++++++++++++
|
|
.../net/minecraft/server/IEntityAccess.java | 34 ++++++---------
|
|
.../net/minecraft/server/IEntitySelector.java | 2 +
|
|
.../minecraft/server/PlayerConnection.java | 10 +++++
|
|
.../net/minecraft/server/WorldServer.java | 4 +-
|
|
.../net/pl3x/purpur/PurpurWorldConfig.java | 11 +++++
|
|
.../craftbukkit/entity/CraftPlayer.java | 17 ++++++++
|
|
.../java/org/spigotmc/ActivationRange.java | 1 +
|
|
src/main/resources/purpur.lang | 4 +-
|
|
11 files changed, 111 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
|
index 5d39d86f0..46bc91524 100644
|
|
--- a/src/main/java/net/minecraft/server/Entity.java
|
|
+++ b/src/main/java/net/minecraft/server/Entity.java
|
|
@@ -1438,6 +1438,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
|
return MathHelper.c(f * f + f1 * f1 + f2 * f2);
|
|
}
|
|
|
|
+ public double getDistanceSquared(double x, double y, double z) { return g(x, y, z); } // Purpur - OBFHELPER
|
|
public double g(double d0, double d1, double d2) {
|
|
double d3 = this.locX() - d0;
|
|
double d4 = this.locY() - d1;
|
|
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
|
|
index 27cfc6654..d62174e9c 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityHuman.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
|
|
@@ -86,6 +86,15 @@ public abstract class EntityHuman extends EntityLiving {
|
|
}
|
|
// CraftBukkit end
|
|
|
|
+ // Purpur start
|
|
+ public void setAfk(boolean setAfk){
|
|
+ }
|
|
+
|
|
+ public boolean isAfk() {
|
|
+ return false;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public EntityHuman(World world, GameProfile gameprofile) {
|
|
super(EntityTypes.PLAYER, world);
|
|
this.bV = ItemStack.a;
|
|
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
index b66f9cd2c..0834ca328 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
@@ -1625,8 +1625,51 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
public void resetIdleTimer() {
|
|
this.cj = SystemUtils.getMonotonicMillis();
|
|
+ setAfk(false); // Purpur
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ private boolean isAfk = false;
|
|
+
|
|
+ @Override
|
|
+ public void setAfk(boolean setAfk) {
|
|
+ if (this.isAfk == setAfk) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ net.pl3x.purpur.event.PlayerAFKEvent event = new net.pl3x.purpur.event.PlayerAFKEvent(getBukkitEntity(), setAfk, world.purpurConfig.idleTimeoutKick, LocaleLanguage.getInstance().translateKey("idle.timeout.broadcast." + (setAfk ? "away" : "back")), !Bukkit.isPrimaryThread());
|
|
+ if (!event.callEvent() || event.shouldKick()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ this.isAfk = setAfk;
|
|
+
|
|
+ if (!setAfk) {
|
|
+ resetIdleTimer();
|
|
+ }
|
|
+
|
|
+ if (event.getBroadcastMsg() != null && !event.getBroadcastMsg().isEmpty()) {
|
|
+ server.getPlayerList().sendAll(new PacketPlayOutChat(new ChatMessage(event.getBroadcastMsg(), getScoreboardDisplayName())));
|
|
+ }
|
|
+
|
|
+ if (world.purpurConfig.idleTimeoutUpdateTabList) {
|
|
+ getBukkitEntity().setPlayerListName((setAfk ? "[AFK] " : "") + getName());
|
|
+ }
|
|
+
|
|
+ ((WorldServer) world).everyoneSleeping();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isAfk() {
|
|
+ return isAfk;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isCollidable(boolean ignoreClimbing) {
|
|
+ return !isAfk() && super.isCollidable(ignoreClimbing);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public ServerStatisticManager getStatisticManager() {
|
|
return this.serverStatisticManager;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
|
|
index e0d97d2c8..e1a7926d7 100644
|
|
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
|
|
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
|
|
@@ -150,28 +150,18 @@ public interface IEntityAccess {
|
|
return entityhuman;
|
|
}
|
|
|
|
- default boolean isPlayerNearby(double d0, double d1, double d2, double d3) {
|
|
- Iterator iterator = this.getPlayers().iterator();
|
|
-
|
|
- double d4;
|
|
-
|
|
- do {
|
|
- EntityHuman entityhuman;
|
|
-
|
|
- do {
|
|
- do {
|
|
- if (!iterator.hasNext()) {
|
|
- return false;
|
|
- }
|
|
-
|
|
- entityhuman = (EntityHuman) iterator.next();
|
|
- } while (!IEntitySelector.f.test(entityhuman));
|
|
- } while (!IEntitySelector.b.test(entityhuman));
|
|
-
|
|
- d4 = entityhuman.g(d0, d1, d2);
|
|
- } while (d3 >= 0.0D && d4 >= d3 * d3);
|
|
-
|
|
- return true;
|
|
+ // Purpur start
|
|
+ default boolean isPlayerNearby(double x, double y, double z, double distance) {
|
|
+ double distanceSq = distance * distance;
|
|
+ for (EntityHuman player : getPlayers()) {
|
|
+ if (IEntitySelector.notSpectator().test(player) && IEntitySelector.isLivingAlive().test(player) && IEntitySelector.notAfk.test(player)) {
|
|
+ if (distance < 0.0D || player.getDistanceSquared(x, y, z) < distanceSq) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ // Purpur end
|
|
}
|
|
|
|
@Nullable
|
|
diff --git a/src/main/java/net/minecraft/server/IEntitySelector.java b/src/main/java/net/minecraft/server/IEntitySelector.java
|
|
index 1398c47a2..0bf1a14b7 100644
|
|
--- a/src/main/java/net/minecraft/server/IEntitySelector.java
|
|
+++ b/src/main/java/net/minecraft/server/IEntitySelector.java
|
|
@@ -7,6 +7,7 @@ import javax.annotation.Nullable;
|
|
public final class IEntitySelector {
|
|
|
|
public static final Predicate<Entity> a = Entity::isAlive;
|
|
+ public static Predicate<EntityLiving> isLivingAlive() { return b; } // Purpur - OBFHELPER
|
|
public static final Predicate<EntityLiving> b = EntityLiving::isAlive;
|
|
public static final Predicate<Entity> c = (entity) -> {
|
|
return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger();
|
|
@@ -24,6 +25,7 @@ public final class IEntitySelector {
|
|
return !entity.isSpectator();
|
|
};
|
|
public static Predicate<EntityHuman> isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper
|
|
+ public static Predicate<EntityHuman> notAfk = (player) -> !player.isAfk(); // Purpur
|
|
|
|
public static Predicate<Entity> a(double d0, double d1, double d2, double d3) {
|
|
double d4 = d3 * d3;
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
index ee961bc05..17b23ed2f 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
@@ -233,6 +233,12 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
}
|
|
|
|
if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) {
|
|
+ // Purpur start
|
|
+ this.player.setAfk(true);
|
|
+ if (!this.player.world.purpurConfig.idleTimeoutKick) {
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854
|
|
this.disconnect(new ChatMessage("multiplayer.disconnect.idling", new Object[0]));
|
|
}
|
|
@@ -449,6 +455,8 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
this.lastYaw = to.getYaw();
|
|
this.lastPitch = to.getPitch();
|
|
|
|
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ()) this.player.resetIdleTimer(); // Purpur
|
|
+
|
|
// Skip the first time we do this
|
|
if (true) { // Spigot - don't skip any move events
|
|
Location oldTo = to.clone();
|
|
@@ -1141,6 +1149,8 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
this.lastYaw = to.getYaw();
|
|
this.lastPitch = to.getPitch();
|
|
|
|
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ()) this.player.resetIdleTimer(); // Purpur
|
|
+
|
|
// Skip the first time we do this
|
|
if (from.getX() != Double.MAX_VALUE) {
|
|
Location oldTo = to.clone();
|
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
|
index 441249284..afb6ad44a 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
|
@@ -405,7 +405,7 @@ public class WorldServer extends World {
|
|
}
|
|
|
|
if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> {
|
|
- return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping; // CraftBukkit
|
|
+ return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping && !(purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk()); // CraftBukkit // Purpur
|
|
})) {
|
|
// CraftBukkit start
|
|
long l = this.worldData.getDayTime() + 24000L;
|
|
@@ -723,7 +723,7 @@ public class WorldServer extends World {
|
|
while (iterator.hasNext()) {
|
|
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
|
|
|
|
- if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping())) { // CraftBukkit
|
|
+ if (entityplayer.isSpectator() || (entityplayer.fauxSleeping && !entityplayer.isSleeping()) || (purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk())) { // CraftBukkit // Purpur
|
|
++i;
|
|
} else if (entityplayer.isSleeping()) {
|
|
++j;
|
|
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
index d6405b2ec..41dd1b861 100644
|
|
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
@@ -138,6 +138,17 @@ public class PurpurWorldConfig {
|
|
disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath);
|
|
}
|
|
|
|
+ public boolean idleTimeoutKick = true;
|
|
+ public boolean idleTimeoutTickNearbyEntities = true;
|
|
+ public boolean idleTimeoutCountAsSleeping = false;
|
|
+ public boolean idleTimeoutUpdateTabList = false;
|
|
+ private void idleTimeoutSettings() {
|
|
+ idleTimeoutKick = getBoolean("gameplay-mechanics.player.idle-timeout.kick-if-idle", idleTimeoutKick);
|
|
+ idleTimeoutTickNearbyEntities = getBoolean("gameplay-mechanics.player.idle-timeout.tick-nearby-entities", idleTimeoutTickNearbyEntities);
|
|
+ idleTimeoutCountAsSleeping = getBoolean("gameplay-mechanics.player.idle-timeout.count-as-sleeping", idleTimeoutCountAsSleeping);
|
|
+ idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList);
|
|
+ }
|
|
+
|
|
public boolean batRidable = false;
|
|
public boolean batRidableInWater = false;
|
|
public boolean batRequireShiftToMount = true;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
index dcbda5b35..c14493929 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -2079,4 +2079,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
return spigot;
|
|
}
|
|
// Spigot end
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isAfk() {
|
|
+ return getHandle().isAfk();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setAfk(boolean setAfk) {
|
|
+ getHandle().setAfk(setAfk);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void resetIdleTimer() {
|
|
+ getHandle().resetIdleTimer();
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
|
index f735217e7..818f8070c 100644
|
|
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
|
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
|
@@ -207,6 +207,7 @@ public class ActivationRange
|
|
{
|
|
|
|
player.activatedTick = MinecraftServer.currentTick;
|
|
+ if (!player.world.purpurConfig.idleTimeoutTickNearbyEntities && player.isAfk()) continue; // Purpur
|
|
maxBB = player.getBoundingBox().grow( maxRange, 256, maxRange );
|
|
ActivationType.MISC.boundingBox = player.getBoundingBox().grow( miscActivationRange, 256, miscActivationRange );
|
|
ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange );
|
|
diff --git a/src/main/resources/purpur.lang b/src/main/resources/purpur.lang
|
|
index 7125c0477..e925e1374 100644
|
|
--- a/src/main/resources/purpur.lang
|
|
+++ b/src/main/resources/purpur.lang
|
|
@@ -1,3 +1,5 @@
|
|
{
|
|
- "cannot.ride.mob": "You cannot mount that mob"
|
|
+ "cannot.ride.mob": "You cannot mount that mob",
|
|
+ "idle.timeout.broadcast.away": "§e§o%s is now AFK",
|
|
+ "idle.timeout.broadcast.back": "§e§o%s is no longer AFK"
|
|
}
|
|
--
|
|
2.24.0
|
|
|