Files
Purpur/patches/server/0009-AFK-API.patch
BillyGalbreath 643d9681ff Updated Upstream (Paper & Tuinity)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
8fa15382b [Auto] Updated Upstream (CraftBukkit)
732b2f6b5 [CI-SKIP] [Auto] Rebuild Patches
c5a39ffa2 Add BlockPreDispenseEvent (#5075)
8aeb4c9c3 Correctly skip pathfinder ticks for inactive entities (#5085)
0e420049c Fix console spam when removing chests in water
56b7935bb Add PlayerChangeBeaconEffectEvent
2eda45c34 added Wither API
97d0c571b Added Vanilla Entity Tags
fccac282a fix NPE in getDisplayNameComponent
24e140372 Configurable max leash distance

Tuinity Changes:
d3ee22224 Merge dev/lighting
2021-01-20 23:52:16 -06:00

303 lines
15 KiB
Diff

From 0000000000000000000000000000000000000000 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] AFK API
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index 9796b4e57d6680c9f0dc76decdd985572daafb7e..f15ec5c45d95c6828ed628451917ac3426a76f1f 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -84,6 +84,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, BlockPosition blockposition, float f, GameProfile gameprofile) {
super(EntityTypes.PLAYER, world);
this.bL = ItemStack.b;
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 9f5b7243ccbe0729a061345c25033d9145b91b3f..dc69cba40806782e0b8ffd3b77aa6298feddb35d 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1904,8 +1904,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public void resetIdleTimer() {
this.ca = SystemUtils.getMonotonicMillis();
+ setAfk(false); // Purpur
}
+ // Purpur start
+ private boolean isAfk = false;
+
+ @Override
+ public void setAfk(boolean setAfk) {
+ if (this.isAfk == setAfk) {
+ return;
+ }
+
+ String msg = setAfk ? net.pl3x.purpur.PurpurConfig.afkBroadcastAway : net.pl3x.purpur.PurpurConfig.afkBroadcastBack;
+
+ net.pl3x.purpur.event.PlayerAFKEvent event = new net.pl3x.purpur.event.PlayerAFKEvent(getBukkitEntity(), setAfk, world.purpurConfig.idleTimeoutKick, msg, !Bukkit.isPrimaryThread());
+ if (!event.callEvent() || event.shouldKick()) {
+ return;
+ }
+
+ this.isAfk = setAfk;
+
+ if (!setAfk) {
+ resetIdleTimer();
+ }
+
+ msg = event.getBroadcastMsg();
+ if (msg != null && !msg.isEmpty()) {
+ server.getPlayerList().sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(String.format(msg, getProfile().getName())));
+ }
+
+ if (world.purpurConfig.idleTimeoutUpdateTabList) {
+ getBukkitEntity().setPlayerListName((setAfk ? net.pl3x.purpur.PurpurConfig.afkTabListPrefix : "") + getName());
+ }
+
+ ((WorldServer) world).everyoneSleeping();
+ }
+
+ @Override
+ public boolean isAfk() {
+ return isAfk;
+ }
+
+ @Override
+ public boolean isCollidable() {
+ return !isAfk() && super.isCollidable();
+ }
+ // 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 cbaf18af1066e8bde10293bba5eb3060bae1e66f..0c98a436021cbdedba5352073b1f8bf9852298eb 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -174,28 +174,18 @@ public interface IEntityAccess {
}
// Paper end
- 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.g.test(entityhuman));
- } while (!IEntitySelector.b.test(entityhuman));
-
- d4 = entityhuman.h(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 b5e1a860a2569d7668330827614d221b60f3fc78..5f85a1d513f4fdc21b64e1a2b6882e3325b98ddd 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();
@@ -27,6 +28,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
// Paper start
public static final Predicate<Entity> affectsSpawning = (entity) -> {
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 4058c1f7ada7d0c9e4ba73a0073b4f94bf410a8f..caf9ce94a7cb6154981d42953c81b588b19e3814 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -250,6 +250,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"));
}
@@ -517,6 +523,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() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetIdleTimer(); // Purpur
+
// Skip the first time we do this
if (true) { // Spigot - don't skip any move events
Location oldTo = to.clone();
@@ -1228,7 +1236,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot
flag1 = true; // Tuinity - diff on change, this should be moved wrongly
- PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString());
+ PlayerConnection.LOGGER.warn("{} moved wrongly! ({})", this.player.getDisplayName().getString(), d11); // Purpur
}
this.player.setLocation(d4, d5, d6, f, f1);
@@ -1278,6 +1286,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() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) 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 6ff5ef6b710652f1c4fe6461ff230ee78988f623..efe2a9ad2ece23bd71f4ad63b2c6f54f42345b55 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -781,7 +781,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end
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;
@@ -1118,7 +1118,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
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/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java
index cb7e34924cb5dbff25d1ffe05cfe5bc22e4a90ed..406e840499e09638e8b325d0e52b764e80acc777 100644
--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java
@@ -1,6 +1,7 @@
package net.pl3x.purpur;
import com.google.common.base.Throwables;
+import net.minecraft.server.LocaleLanguage;
import net.minecraft.server.MinecraftServer;
import net.pl3x.purpur.command.PurpurCommand;
import org.bukkit.Bukkit;
@@ -129,6 +130,15 @@ public class PurpurConfig {
return config.getString(path, config.getString(path));
}
+ public static String afkBroadcastAway = "§e§o%s is now AFK";
+ public static String afkBroadcastBack = "§e§o%s is no longer AFK";
+ public static String afkTabListPrefix = "[AFK] ";
+ private static void messages() {
+ afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway);
+ afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack);
+ afkTabListPrefix = getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix);
+ }
+
public static String timingsUrl = "https://timings.pl3x.net";
private static void timingsSettings() {
timingsUrl = getString("settings.timings.url", timingsUrl);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index 361f7857e461578e90cb71e15027dadaf794cb69..2578a4677d1ee060f687be531e696b7c7be89e84 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -56,4 +56,15 @@ public class PurpurWorldConfig {
PurpurConfig.config.addDefault("world-settings.default." + path, def);
return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path));
}
+
+ public boolean idleTimeoutKick = true;
+ public boolean idleTimeoutTickNearbyEntities = true;
+ public boolean idleTimeoutCountAsSleeping = false;
+ public boolean idleTimeoutUpdateTabList = false;
+ private void playerIdleTimeoutSettings() {
+ 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);
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7c18b22c7b93b6ca1189e481dde17476797b8fd5..debf252a23d0178f06fdadb9c27c3c66b9bbc2d0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2223,4 +2223,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 0b93635ba59df4eb4456a97c5e9b51ab5aeda53f..b47d6fa2de3368d1afe329573bc18c3541bb7377 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 );