Files
Purpur/patches/server/0050-Implement-AFK-API.patch
2020-01-03 01:41:07 -06:00

304 lines
14 KiB
Diff

From a812fd3b8c0aef3ba27d7a49f4b721ee73d9db5a 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 | 16 +++++++
.../craftbukkit/entity/CraftPlayer.java | 17 ++++++++
.../java/org/spigotmc/ActivationRange.java | 1 +
10 files changed, 113 insertions(+), 24 deletions(-)
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index dee92e5a72..5e99ad8144 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1374,6 +1374,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
return MathHelper.c(f * f + f1 * f1 + f2 * f2);
}
+ public double getDistanceSq(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 57c528d532..3c9f180960 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 8565ad9c76..50a922ff1b 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1583,8 +1583,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, setAfk ? world.purpurConfig.idleTimeoutBroadcastAway : world.purpurConfig.idleTimeoutBroadcastBack);
+ if (!event.callEvent() || event.shouldKick()) {
+ return;
+ }
+
+ this.isAfk = setAfk;
+
+ if (!setAfk) {
+ resetIdleTimer();
+ }
+
+ if (event.getBroadcastMsg() != null && !event.getBroadcastMsg().isEmpty()) {
+ ((WorldServer) world).getMinecraftServer().server.broadcastMessage(event.getBroadcastMsg().replace("{player}", getName()));
+ }
+
+ 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 8b36252ae1..5e2d56d5de 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -116,28 +116,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.getDistanceSq(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 8d7273a38b..71c61dc45e 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();
@@ -23,6 +24,7 @@ public final class IEntitySelector {
public static final Predicate<Entity> f = (entity) -> {
return !entity.isSpectator();
};
+ 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 a4af019bc6..2db59c55ca 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -277,6 +277,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]));
}
@@ -493,6 +499,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();
@@ -1162,6 +1170,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 0a9df816c2..84c0693303 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -367,7 +367,7 @@ public class WorldServer extends World {
}
if (this.C && 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;
@@ -648,7 +648,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 06d6275809..259f6fa287 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -1,6 +1,7 @@
package net.pl3x.purpur;
import com.destroystokyo.paper.PaperWorldConfig;
+import org.bukkit.ChatColor;
import org.bukkit.configuration.file.YamlConfiguration;
import org.spigotmc.SpigotWorldConfig;
@@ -132,6 +133,21 @@ public class PurpurWorldConfig {
elytraDamagePerTridentBoost = getInt("elytra.damage-per-boost.trident", elytraDamagePerTridentBoost);
}
+ public boolean idleTimeoutKick = true;
+ public boolean idleTimeoutTickNearbyEntities = false;
+ public boolean idleTimeoutCountAsSleeping = false;
+ public boolean idleTimeoutUpdateTabList = true;
+ public String idleTimeoutBroadcastAway = "&e&o{player} is now AFK";
+ public String idleTimeoutBroadcastBack = "&e&o{player} is no longer AFK";
+ private void playerIdleTimeoutSettings() {
+ idleTimeoutKick = getBoolean("idle-timeout.kick-if-idle", idleTimeoutKick);
+ idleTimeoutTickNearbyEntities = getBoolean("idle-timeout.tick-nearby-entities", idleTimeoutTickNearbyEntities);
+ idleTimeoutCountAsSleeping = getBoolean("idle-timeout.count-as-sleeping", idleTimeoutCountAsSleeping);
+ idleTimeoutUpdateTabList = getBoolean("idle-timeout.update-tab-list", idleTimeoutUpdateTabList);
+ idleTimeoutBroadcastAway = ChatColor.translateAlternateColorCodes('&', getString("idle-timeout.broadcast.away", idleTimeoutBroadcastAway));
+ idleTimeoutBroadcastBack = ChatColor.translateAlternateColorCodes('&', getString("idle-timeout.broadcast.back", idleTimeoutBroadcastBack));
+ }
+
public int pillagerLimitOutpostSpawns = 10;
private void pillagerSettings() {
pillagerLimitOutpostSpawns = getInt("mobs.pillager.limit-outpost-spawns", pillagerLimitOutpostSpawns);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 712056cad1..c12d52e5df 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2063,4 +2063,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 92601c581c..185717c804 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -128,6 +128,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 );
--
2.24.0