mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@5274ad6 Add and implement PlayerFailMoveEvent (#9535) PaperMC/Paper@ef2b574 Clone location in PlayerFailMoveEvent getters
332 lines
19 KiB
Diff
332 lines
19 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
|
|
|
|
Adds the option for display names to be used in the afk broadcast
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index 2ec32c4845774f9697c4d8451e20f76806f9888d..8276eff5d8085fe4c4f212d0afc5a36d02b84035 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -2118,8 +2118,68 @@ public class ServerPlayer extends Player {
|
|
|
|
public void resetLastActionTime() {
|
|
this.lastActionTime = Util.getMillis();
|
|
+ this.setAfk(false); // Purpur
|
|
}
|
|
|
|
+ // Purpur Start
|
|
+ private boolean isAfk = false;
|
|
+
|
|
+ @Override
|
|
+ public void setAfk(boolean afk) {
|
|
+ if (this.isAfk == afk) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ String msg = afk ? org.purpurmc.purpur.PurpurConfig.afkBroadcastAway : org.purpurmc.purpur.PurpurConfig.afkBroadcastBack;
|
|
+
|
|
+ org.purpurmc.purpur.event.PlayerAFKEvent event = new org.purpurmc.purpur.event.PlayerAFKEvent(this.getBukkitEntity(), afk, this.level().purpurConfig.idleTimeoutKick, msg, !Bukkit.isPrimaryThread());
|
|
+ if (!event.callEvent() || event.shouldKick()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ this.isAfk = afk;
|
|
+
|
|
+ if (!afk) {
|
|
+ resetLastActionTime();
|
|
+ }
|
|
+
|
|
+ msg = event.getBroadcastMsg();
|
|
+ if (msg != null && !msg.isEmpty()) {
|
|
+ String playerName = this.getGameProfile().getName();
|
|
+ if (org.purpurmc.purpur.PurpurConfig.afkBroadcastUseDisplayName) {
|
|
+ net.kyori.adventure.text.Component playerDisplayNameComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getBukkitEntity().getDisplayName());
|
|
+ playerName = net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(playerDisplayNameComponent);
|
|
+ }
|
|
+ server.getPlayerList().broadcastMiniMessage(String.format(msg, playerName), false);
|
|
+ }
|
|
+
|
|
+ if (this.level().purpurConfig.idleTimeoutUpdateTabList) {
|
|
+ String scoreboardName = getScoreboardName();
|
|
+ String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName());
|
|
+ String[] split = playerListName.split(scoreboardName);
|
|
+ String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, "");
|
|
+ String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, "");
|
|
+ if (afk) {
|
|
+ getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true);
|
|
+ } else {
|
|
+ getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ((ServerLevel) this.level()).updateSleepingPlayerList();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isAfk() {
|
|
+ return this.isAfk;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canBeCollidedWith() {
|
|
+ return !this.isAfk() && super.canBeCollidedWith();
|
|
+ }
|
|
+ // Purpur End
|
|
+
|
|
public ServerStatsCounter getStats() {
|
|
return this.stats;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index c7748f6d1a460d8d832616b6a16219be59c6e120..ad03d1753bcddd753ed1080f240fc874dcbc06a2 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -342,6 +342,20 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
private boolean justTeleported = false;
|
|
private boolean hasMoved; // Spigot
|
|
|
|
+ // Purpur start
|
|
+ private final com.google.common.cache.LoadingCache<CraftPlayer, Boolean> kickPermissionCache = com.google.common.cache.CacheBuilder.newBuilder()
|
|
+ .maximumSize(1000)
|
|
+ .expireAfterWrite(1, java.util.concurrent.TimeUnit.MINUTES)
|
|
+ .build(
|
|
+ new com.google.common.cache.CacheLoader<>() {
|
|
+ @Override
|
|
+ public Boolean load(CraftPlayer player) {
|
|
+ return player.hasPermission("purpur.bypassIdleKick");
|
|
+ }
|
|
+ }
|
|
+ );
|
|
+ // Purpur end
|
|
+
|
|
public CraftPlayer getCraftPlayer() {
|
|
return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity();
|
|
}
|
|
@@ -435,6 +449,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
}
|
|
|
|
if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits.
|
|
+ // Purpur start
|
|
+ this.player.setAfk(true);
|
|
+ if (!this.player.level().purpurConfig.idleTimeoutKick || (!Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK")) && kickPermissionCache.getUnchecked(this.player.getBukkitEntity()))) {
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854
|
|
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
|
|
}
|
|
@@ -753,6 +773,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
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.resetLastActionTime(); // Purpur
|
|
+
|
|
// Skip the first time we do this
|
|
if (true) { // Spigot - don't skip any move events
|
|
Location oldTo = to.clone();
|
|
@@ -1570,7 +1592,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
if (!event.isAllowed()) {
|
|
flag2 = true; // Paper - diff on change, this should be moved wrongly
|
|
if (event.getLogWarning())
|
|
- ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
|
|
+ ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), d11); // Purpur
|
|
}
|
|
// Paper end
|
|
}
|
|
@@ -1632,6 +1654,8 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
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.resetLastActionTime(); // 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/players/SleepStatus.java b/src/main/java/net/minecraft/server/players/SleepStatus.java
|
|
index 823efad652d8ff9e96b99375b102fef6f017716e..caa8a69bde0c212c36dd990a67836ac2f95548c0 100644
|
|
--- a/src/main/java/net/minecraft/server/players/SleepStatus.java
|
|
+++ b/src/main/java/net/minecraft/server/players/SleepStatus.java
|
|
@@ -19,7 +19,7 @@ public class SleepStatus {
|
|
|
|
public boolean areEnoughDeepSleeping(int percentage, List<ServerPlayer> players) {
|
|
// CraftBukkit start
|
|
- int j = (int) players.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count();
|
|
+ int j = (int) players.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping || (eh.level().purpurConfig.idleTimeoutCountAsSleeping && eh.isAfk()); }).count(); // Purpur
|
|
boolean anyDeepSleep = players.stream().anyMatch(Player::isSleepingLongEnough);
|
|
|
|
return anyDeepSleep && j >= this.sleepersNeeded(percentage);
|
|
@@ -52,7 +52,7 @@ public class SleepStatus {
|
|
|
|
if (!entityplayer.isSpectator()) {
|
|
++this.activePlayers;
|
|
- if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit
|
|
+ if ((entityplayer.isSleeping() || entityplayer.fauxSleeping) || (entityplayer.level().purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk())) { // CraftBukkit // Purpur
|
|
++this.sleepingPlayers;
|
|
}
|
|
// CraftBukkit start
|
|
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
|
index 3ff999734d14e2b6e7828e117f5ee32a60c26bc1..cfa9607241c3e69777ffc317206996c2f783437a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
|
|
@@ -39,6 +39,7 @@ public final class EntitySelector {
|
|
return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks;
|
|
};
|
|
// Paper end
|
|
+ public static Predicate<Player> notAfk = (player) -> !player.isAfk(); // Purpur
|
|
|
|
private EntitySelector() {}
|
|
// Paper start
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
|
index d25307ae8bbdf10ae067ec70fc2cb957b852a0eb..54bdb81785b617e13e67530752395f2a0c6d703a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
|
@@ -64,6 +64,10 @@ public class TargetingConditions {
|
|
return false;
|
|
} else if (this.selector != null && !this.selector.test(targetEntity)) {
|
|
return false;
|
|
+ // Purpur start
|
|
+ } else if (!targetEntity.level().purpurConfig.idleTimeoutTargetPlayer && targetEntity instanceof net.minecraft.server.level.ServerPlayer player && player.isAfk()) {
|
|
+ return false;
|
|
+ // Purpur end
|
|
} else {
|
|
if (baseEntity == null) {
|
|
if (this.isCombat && (!targetEntity.canBeSeenAsEnemy() || targetEntity.level().getDifficulty() == Difficulty.PEACEFUL)) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
index 96726f06b83193fd7c5156efe6411b10eb1db435..7b39cb5346925c14f3f144d622ca7e5855420aa6 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
@@ -193,6 +193,13 @@ public abstract class Player extends LivingEntity {
|
|
public boolean fauxSleeping;
|
|
public int oldLevel = -1;
|
|
|
|
+ public void setAfk(boolean afk) {
|
|
+ }
|
|
+
|
|
+ public boolean isAfk() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
@Override
|
|
public CraftHumanEntity getBukkitEntity() {
|
|
return (CraftHumanEntity) super.getBukkitEntity();
|
|
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
|
index 3b959f42d958bf0f426853aee56753d6c455fcdb..d17abb283ea818244df0379d6b57fc634071e0b9 100644
|
|
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
|
|
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
|
@@ -154,7 +154,7 @@ public interface EntityGetter {
|
|
|
|
default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) {
|
|
for(Player player : this.players()) {
|
|
- if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) {
|
|
+ if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player) && EntitySelector.notAfk.test(player)) {
|
|
double d = player.distanceToSqr(x, y, z);
|
|
if (range < 0.0D || d < range * range) {
|
|
return true;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
index bb3ed33e20feebe3b36e24708496adf46c381525..673ac3704eee0b2aa576fe197abb8af5d8986e7e 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -510,10 +510,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
@Override
|
|
public void setPlayerListName(String name) {
|
|
+ // Purpur start
|
|
+ setPlayerListName(name, false);
|
|
+ }
|
|
+ public void setPlayerListName(String name, boolean useMM) {
|
|
+ // Purpur end
|
|
if (name == null) {
|
|
name = getName();
|
|
}
|
|
- this.getHandle().listName = name.equals(getName()) ? null : CraftChatMessage.fromStringOrNull(name);
|
|
+ this.getHandle().listName = name.equals(getName()) ? null : useMM ? io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name)) : CraftChatMessage.fromStringOrNull(name); // Purpur
|
|
for (ServerPlayer player : (List<ServerPlayer>) server.getHandle().players) {
|
|
if (player.getBukkitEntity().canSee(this)) {
|
|
player.connection.send(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, this.getHandle()));
|
|
@@ -3218,5 +3223,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
public boolean usesPurpurClient() {
|
|
return getHandle().purpurClient;
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public boolean isAfk() {
|
|
+ return getHandle().isAfk();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setAfk(boolean setAfk) {
|
|
+ getHandle().setAfk(setAfk);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void resetIdleTimer() {
|
|
+ getHandle().resetLastActionTime();
|
|
+ }
|
|
// Purpur end
|
|
}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
index e6a720f25266d793bec5f644dadacbf45aef23f5..6b768cff1318b4bcebeed95345f3cfdce05a2c16 100644
|
|
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
@@ -174,8 +174,18 @@ public class PurpurConfig {
|
|
}
|
|
|
|
public static String cannotRideMob = "<red>You cannot mount that mob";
|
|
+ public static String afkBroadcastAway = "<yellow><italic>%s is now AFK";
|
|
+ public static String afkBroadcastBack = "<yellow><italic>%s is no longer AFK";
|
|
+ public static boolean afkBroadcastUseDisplayName = false;
|
|
+ public static String afkTabListPrefix = "[AFK] ";
|
|
+ public static String afkTabListSuffix = "";
|
|
private static void messages() {
|
|
cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob);
|
|
+ afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway);
|
|
+ afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack);
|
|
+ afkBroadcastUseDisplayName = getBoolean("settings.messages.afk-broadcast-use-display-name", afkBroadcastUseDisplayName);
|
|
+ afkTabListPrefix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix)));
|
|
+ afkTabListSuffix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-suffix", afkTabListSuffix)));
|
|
}
|
|
|
|
public static int barrelRows = 3;
|
|
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
index 5fd42d8604491268074d5ff516657f5d07761092..4eb4e0b7748334c5a9d693164600854b81b1ad9e 100644
|
|
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
@@ -91,6 +91,24 @@ public class PurpurWorldConfig {
|
|
return value.isEmpty() ? fallback : value;
|
|
}
|
|
|
|
+ public boolean idleTimeoutKick = true;
|
|
+ public boolean idleTimeoutTickNearbyEntities = true;
|
|
+ public boolean idleTimeoutCountAsSleeping = false;
|
|
+ public boolean idleTimeoutUpdateTabList = false;
|
|
+ public boolean idleTimeoutTargetPlayer = true;
|
|
+ private void playerSettings() {
|
|
+ if (PurpurConfig.version < 19) {
|
|
+ boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
|
|
+ set("gameplay-mechanics.player.idle-timeout.mods-target", null);
|
|
+ set("gameplay-mechanics.player.idle-timeout.mobs-target", oldVal);
|
|
+ }
|
|
+ idleTimeoutKick = System.getenv("PURPUR_FORCE_IDLE_KICK") == null ? getBoolean("gameplay-mechanics.player.idle-timeout.kick-if-idle", idleTimeoutKick) : Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK"));
|
|
+ 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);
|
|
+ idleTimeoutTargetPlayer = getBoolean("gameplay-mechanics.player.idle-timeout.mobs-target", idleTimeoutTargetPlayer);
|
|
+ }
|
|
+
|
|
public boolean babiesAreRidable = true;
|
|
public boolean untamedTamablesAreRidable = true;
|
|
public boolean useNightVisionWhenRiding = false;
|
|
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
|
index 68557964e27fa1e5ba218178f9bcc0b28e3a78d9..12adaba78ec30e463963f99c0d78e844756143a1 100644
|
|
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
|
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
|
@@ -203,6 +203,7 @@ public class ActivationRange
|
|
continue;
|
|
}
|
|
|
|
+ if (!player.level().purpurConfig.idleTimeoutTickNearbyEntities && player.isAfk()) continue; // Purpur
|
|
// Paper start
|
|
int worldHeight = world.getHeight();
|
|
ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, worldHeight, maxRange );
|