geforkt von Mirrors/Paper
7df472527f
A long standing bug in spigot and its derivatives was the fact that players taking damage while blocking with a shield would not receive invulnerability, while they do in vanilla. This enabled the pvp technique of disabling a shield and immediately attacking again to knock a player into the air. While upstream fixed this and properly aligned itself with vanilla damage logic (in this specific case) changing such long standing behaviour has some downsides. To allow players used to this specific bug to still use it, this patch introduces a configuration option to re-introduce said bug. As there is no easy way to *only* re-add this bug, the option is found in the unsupported section as it may introduce other damage related disparity from vanilla.
90 Zeilen
6.0 KiB
Diff
90 Zeilen
6.0 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: kickash32 <kickash32@gmail.com>
|
|
Date: Mon, 5 Apr 2021 01:42:35 -0400
|
|
Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
|
|
spawns
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 7bebf252887ecc7594b1ce21471fb6ba7aa2c051..df00ea382915480be1279a5347872cf7a1417341 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -300,8 +300,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
++((ServerPlayer)backingSet[i]).mobCounts[index];
|
|
}
|
|
}
|
|
+ // Paper start - per player mob count backoff
|
|
+ public void updateFailurePlayerMobTypeMap(int chunkX, int chunkZ, net.minecraft.world.entity.MobCategory mobCategory) {
|
|
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
|
+ return;
|
|
+ }
|
|
+ int idx = mobCategory.ordinal();
|
|
+ final com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> inRange =
|
|
+ this.getNearbyPlayers().getPlayersByChunk(chunkX, chunkZ, io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
|
+ if (inRange == null) {
|
|
+ return;
|
|
+ }
|
|
+ final Object[] backingSet = inRange.getRawData();
|
|
+ for (int i = 0, len = inRange.size(); i < len; i++) {
|
|
+ ++((ServerPlayer)backingSet[i]).mobBackoffCounts[idx];
|
|
+ }
|
|
+ }
|
|
+ // Paper end - per player mob count backoff
|
|
public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
|
|
- return player.mobCounts[mobCategory.ordinal()];
|
|
+ return player.mobCounts[mobCategory.ordinal()] + player.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff
|
|
// Paper end - Optional per player mob spawns
|
|
}
|
|
// Paper end
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index f134b75b3665b53ef873404b3f4775657cfbcadb..7dc2ecd8a80b063cec922021bd978ba2c6f8c0fb 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -505,7 +505,17 @@ public class ServerChunkCache extends ChunkSource {
|
|
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
|
// re-set mob counts
|
|
for (ServerPlayer player : this.level.players) {
|
|
- Arrays.fill(player.mobCounts, 0);
|
|
+ // Paper start - per player mob spawning backoff
|
|
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
|
+ player.mobCounts[ii] = 0;
|
|
+
|
|
+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
|
|
+ if (newBackoff < 0) {
|
|
+ newBackoff = 0;
|
|
+ }
|
|
+ player.mobBackoffCounts[ii] = newBackoff;
|
|
+ }
|
|
+ // Paper end - per player mob spawning backoff
|
|
}
|
|
spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index c75812c195cc83dbe02eebc9ba67b2a9c29ca9a4..89ed20e9c629cf39a24c7a0ce5c4fee41fc64fd5 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -279,6 +279,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
|
|
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
|
|
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
|
|
// Paper end - Optional per player mob spawns
|
|
+ public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff
|
|
|
|
// CraftBukkit start
|
|
public CraftPlayer.TransferCookieConnection transferCookieConnection;
|
|
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
index 0679636530ca1afd077c43b0fa605a2ac74e0522..ed8032495af9ce9c23419224814b8d27e4a97c17 100644
|
|
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
@@ -272,6 +272,11 @@ public final class NaturalSpawner {
|
|
|
|
// Paper start - PreCreatureSpawnEvent
|
|
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
|
+ // Paper start - per player mob count backoff
|
|
+ if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
|
|
+ world.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(blockposition_mutableblockposition.getX() >> 4, blockposition_mutableblockposition.getZ() >> 4, group);
|
|
+ }
|
|
+ // Paper end - per player mob count backoff
|
|
if (doSpawning == PreSpawnStatus.ABORT) {
|
|
return j; // Paper - Optional per player mob spawns
|
|
}
|