Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: MiniDigger | Martin <admin@minidigger.dev>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com>
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
Nassim Jahnke
2025-04-12 17:26:44 +02:00
parent 0767902699
commit f00727c57e
2092 changed files with 50551 additions and 48729 deletions

View File

@@ -31,7 +31,7 @@ this fix, as the data will remain in the oversized file. Once the server returns
to a jar with this fix, the data will be restored.
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
index d0854fa02be52f560fc91adeb8495a6bd22f6f74..783a2d80f6197dd0af0dc81909f0353a8ea2ecf4 100644
index 43d38cf26224919cd53d7479753d658f4ab40dbc..4eb07097986aac67421dd8e6a17cc5436da91187 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -53,6 +53,7 @@ public class RegionFile implements AutoCloseable {
@@ -119,7 +119,7 @@ index d0854fa02be52f560fc91adeb8495a6bd22f6f74..783a2d80f6197dd0af0dc81909f0353a
+ // Paper end
}
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 5ac84d6b47e7fdc16e1c09b739829de3d316bf5b..51bf310423013d0ae9d3202d66e36a053a767197 100644
index 5ac84d6b47e7fdc16e1c09b739829de3d316bf5b..763879cdc389fc4d80135b38aa96a5bec448ae9e 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -47,6 +47,43 @@ public final class RegionFileStorage implements AutoCloseable {
@@ -139,10 +139,10 @@ index 5ac84d6b47e7fdc16e1c09b739829de3d316bf5b..51bf310423013d0ae9d3202d66e36a05
+ if (oversizedData == null) {
+ return chunk;
+ }
+ CompoundTag oversizedLevel = oversizedData.getCompound("Level");
+ CompoundTag oversizedLevel = oversizedData.getCompoundOrEmpty("Level");
+
+ mergeChunkList(chunk.getCompound("Level"), oversizedLevel, "Entities", "Entities");
+ mergeChunkList(chunk.getCompound("Level"), oversizedLevel, "TileEntities", "TileEntities");
+ mergeChunkList(chunk.getCompoundOrEmpty("Level"), oversizedLevel, "Entities", "Entities");
+ mergeChunkList(chunk.getCompoundOrEmpty("Level"), oversizedLevel, "TileEntities", "TileEntities");
+
+ return chunk;
+ } catch (Throwable throwable) {
@@ -153,8 +153,8 @@ index 5ac84d6b47e7fdc16e1c09b739829de3d316bf5b..51bf310423013d0ae9d3202d66e36a05
+ }
+
+ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key, String oversizedKey) {
+ net.minecraft.nbt.ListTag levelList = level.getList(key, net.minecraft.nbt.Tag.TAG_COMPOUND);
+ net.minecraft.nbt.ListTag oversizedList = oversizedLevel.getList(oversizedKey, net.minecraft.nbt.Tag.TAG_COMPOUND);
+ net.minecraft.nbt.ListTag levelList = level.getListOrEmpty(key);
+ net.minecraft.nbt.ListTag oversizedList = oversizedLevel.getListOrEmpty(oversizedKey);
+
+ if (!oversizedList.isEmpty()) {
+ levelList.addAll(oversizedList);

View File

@@ -15,7 +15,7 @@ Adds villagers as separate config
diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
new file mode 100644
index 0000000000000000000000000000000000000000..ade6110cc6adb1263c0359ff7e96e96b959e61f3
index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae69f36157e
--- /dev/null
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
@@ -0,0 +1,318 @@
@@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..ade6110cc6adb1263c0359ff7e96e96b
+import net.minecraft.world.entity.ai.Brain;
+import net.minecraft.world.entity.animal.Animal;
+import net.minecraft.world.entity.animal.Bee;
+import net.minecraft.world.entity.animal.Sheep;
+import net.minecraft.world.entity.animal.sheep.Sheep;
+import net.minecraft.world.entity.animal.horse.Llama;
+import net.minecraft.world.entity.boss.EnderDragonPart;
+import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
@@ -338,7 +338,7 @@ index 0000000000000000000000000000000000000000..ade6110cc6adb1263c0359ff7e96e96b
+ }
+}
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index d95413af04121fe91ca0f3b0c70025b9808acef9..ad665c7535c615d2b03a3e7864be435f933235dd 100644
index 88b81a5fbc88e6240f86c1e780d80eb4b601df8c..00a5ed09caa2689543bd47bcd93d5a6141d0af46 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableList;
@@ -357,19 +357,11 @@ index d95413af04121fe91ca0f3b0c70025b9808acef9..ad665c7535c615d2b03a3e7864be435f
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
@@ -95,7 +93,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
-import net.minecraft.world.phys.Vec3;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.slf4j.Logger;
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac184da3960f 100644
index 156f7ddc2fdc96b762598bad2a2b21f433518dc0..ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -551,6 +551,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -544,6 +544,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
profilerFiller.pop();
}
@@ -377,7 +369,7 @@ index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac18
this.entityTickList
.forEach(
entity -> {
@@ -980,12 +981,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -982,12 +983,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
entity.totalEntityAge++; // Paper - age-like counter for all entities
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString());
profilerFiller.incrementCounter("tickNonPassenger");
@@ -394,7 +386,7 @@ index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac18
}
// Paper start - log detailed entity tick information
} finally {
@@ -996,7 +1000,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -998,7 +1002,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - log detailed entity tick information
}
@@ -403,7 +395,7 @@ index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac18
if (passengerEntity.isRemoved() || passengerEntity.getVehicle() != ridingEntity) {
passengerEntity.stopRiding();
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
@@ -1006,12 +1010,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1008,12 +1012,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString());
profilerFiller.incrementCounter("tickPassenger");
@@ -427,10 +419,10 @@ index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac18
}
}
diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java
index a9f01e616ef6b0d74caf57cd68eb371a4fd30fd5..179f4e4b9b1eb57f78bbb2f9fa34b11ea79b7a88 100644
index f9cfa9dd17bd259cfbc0d96bf48a17556b365d8b..201c6d6e2f5799a7678b16f01c85508bc72e8af5 100644
--- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java
@@ -126,6 +126,23 @@ public abstract class AgeableMob extends PathfinderMob {
@@ -129,6 +129,23 @@ public abstract class AgeableMob extends PathfinderMob {
super.onSyncedDataUpdated(key);
}
@@ -455,10 +447,10 @@ index a9f01e616ef6b0d74caf57cd68eb371a4fd30fd5..179f4e4b9b1eb57f78bbb2f9fa34b11e
public void aiStep() {
super.aiStep();
diff --git a/net/minecraft/world/entity/AreaEffectCloud.java b/net/minecraft/world/entity/AreaEffectCloud.java
index 24735284fda151414d99faad401d25ba60995f9a..23b342cc31c7e72ade0e1ccad86a9ccf34380f13 100644
index bf44f6b9c8710e0c9a85d44f6217501abc98a7b1..bfd904e468bbf2cc1a5b3353d3a69ad5087c81ae 100644
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -128,6 +128,16 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
@@ -144,6 +144,16 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
this.duration = duration;
}
@@ -476,10 +468,10 @@ index 24735284fda151414d99faad401d25ba60995f9a..23b342cc31c7e72ade0e1ccad86a9ccf
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 2facc7ad69bfe28c2f928a026ba5ab37387ab039..6256d7f8f4ee8bd4e3673b4e069af5cc0069c8f2 100644
index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc879d602c48 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -381,6 +381,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -388,6 +388,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
private final int despawnTime; // Paper - entity despawn time limit
public int totalEntityAge; // Paper - age-like counter for all entities
public final io.papermc.paper.entity.activation.ActivationType activationType = io.papermc.paper.entity.activation.ActivationType.activationTypeFor(this); // Paper - EAR 2/tracking ranges
@@ -492,10 +484,10 @@ index 2facc7ad69bfe28c2f928a026ba5ab37387ab039..6256d7f8f4ee8bd4e3673b4e069af5cc
+ public void inactiveTick() {
+ }
+ // Paper end - EAR 2
// CraftBukkit end
public void setOrigin(@javax.annotation.Nonnull org.bukkit.Location location) {
this.origin = location.toVector();
@@ -414,6 +423,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper start
@@ -403,6 +412,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.position = Vec3.ZERO;
this.blockPosition = BlockPos.ZERO;
this.chunkPosition = ChunkPos.ZERO;
@@ -509,16 +501,18 @@ index 2facc7ad69bfe28c2f928a026ba5ab37387ab039..6256d7f8f4ee8bd4e3673b4e069af5cc
SynchedEntityData.Builder builder = new SynchedEntityData.Builder(this);
builder.define(DATA_SHARED_FLAGS_ID, (byte)0);
builder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply());
@@ -978,6 +994,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -958,6 +974,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
this.wasOnFire = this.isOnFire();
if (type == MoverType.PISTON) {
+ this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20); // Paper - EAR 2
+ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20); // Paper - EAR 2
+ // Paper start - EAR 2
+ this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20);
+ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20);
+ // Paper end - EAR 2
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -991,6 +1009,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -971,6 +991,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stuckSpeedMultiplier = Vec3.ZERO;
this.setDeltaMovement(Vec3.ZERO);
}
@@ -533,10 +527,10 @@ index 2facc7ad69bfe28c2f928a026ba5ab37387ab039..6256d7f8f4ee8bd4e3673b4e069af5cc
movement = this.maybeBackOffFromEdge(movement, type);
Vec3 vec3 = this.collide(movement);
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index e0c310d970a687945b6a771b4ecb94044128c33c..4546aca8e2e144ec207653c713fc49f849908827 100644
index 4123354a660f85905c8c2db1c5377201c2b8267e..7ba7a00b8dee651ca7a3cab5b64b4ae11aa66da9 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3103,6 +3103,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3163,6 +3163,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
return false;
}
@@ -552,10 +546,10 @@ index e0c310d970a687945b6a771b4ecb94044128c33c..4546aca8e2e144ec207653c713fc49f8
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index e12b47ca5eeb842bae606c0c7a8e3e4cf7d468a9..e330bf990e4874baed1b21cd8c9b44d66ec5b823 100644
index 8f5c377540f83911c8d245fb00569f08dbc6a690..73ba442b9d39bc021cd5eb6c1c0f98aed94a5a02 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -215,6 +215,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -203,6 +203,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
return this.lookControl;
}
@@ -651,10 +645,10 @@ index 789fea258d70e60d38271ebb31270562dc7eb3ab..d0ab3db7bbd2942db19f473474371b20
}
}
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index 8b034b6bda937b25dbb3d09b8293fed6d7dc512c..52a7ed0d991758bad0dcedcb7f97fb15ac6c6d04 100644
index ea3afc27600cde05a17197b071f14972d2c832e6..6c0ebfb2be4e8b884456a2aa3d5fdc87e45a0e3c 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -124,6 +124,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
@@ -131,6 +131,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
return 0.04;
}
@@ -685,10 +679,10 @@ index 8b034b6bda937b25dbb3d09b8293fed6d7dc512c..52a7ed0d991758bad0dcedcb7f97fb15
public void tick() {
if (this.getItem().isEmpty()) {
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
index 27568a1604d2dd5d46e836bbc25431929e218aa1..2b83262e4a13eae86df82913ce4f3121e3631a43 100644
index 94032c60944f161519f0ddee69426cbfe3075170..e0e0d2ea7fc60e3142c675404d152eca60263240 100644
--- a/net/minecraft/world/entity/npc/Villager.java
+++ b/net/minecraft/world/entity/npc/Villager.java
@@ -265,11 +265,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -268,11 +268,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return this.assignProfessionWhenSpawned;
}
@@ -706,7 +700,7 @@ index 27568a1604d2dd5d46e836bbc25431929e218aa1..2b83262e4a13eae86df82913ce4f3121
+ this.customServerAiStep(this.level().getMinecraftWorld(), true);
+ }
+ }
+ maybeDecayGossip();
+ this.maybeDecayGossip();
+ super.inactiveTick();
+ }
+ // Paper end - EAR 2
@@ -725,7 +719,7 @@ index 27568a1604d2dd5d46e836bbc25431929e218aa1..2b83262e4a13eae86df82913ce4f3121
profilerFiller.pop();
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
@@ -293,7 +317,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -296,7 +320,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
this.lastTradedPlayer = null;
}
@@ -734,19 +728,19 @@ index 27568a1604d2dd5d46e836bbc25431929e218aa1..2b83262e4a13eae86df82913ce4f3121
Raid raidAt = level.getRaidAt(this.blockPosition());
if (raidAt != null && raidAt.isActive() && !raidAt.isOver()) {
level.broadcastEntityEvent(this, (byte)42);
@@ -303,6 +327,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) {
@@ -307,6 +331,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
this.stopTrading();
}
+ if (inactive) return; // Paper - EAR 2
+ if (inactive) return; // Paper - EAR 2
super.customServerAiStep(level);
}
diff --git a/net/minecraft/world/entity/projectile/Arrow.java b/net/minecraft/world/entity/projectile/Arrow.java
index c1e09e701757a300183b62d343ded03033e63aa7..56574f8ef879159edc0114da09300143a2c79a35 100644
index 1f22f44abb21d1ed9a4870f668779efb8fd9b295..91ead824718eeea2afba3bc0ef619b8a24bb24b9 100644
--- a/net/minecraft/world/entity/projectile/Arrow.java
+++ b/net/minecraft/world/entity/projectile/Arrow.java
@@ -66,6 +66,16 @@ public class Arrow extends AbstractArrow {
@@ -70,6 +70,16 @@ public class Arrow extends AbstractArrow {
builder.define(ID_EFFECT_COLOR, -1);
}
@@ -764,10 +758,10 @@ index c1e09e701757a300183b62d343ded03033e63aa7..56574f8ef879159edc0114da09300143
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
index a3e4605a81eeaca77cc3a3ab937b75a415d83037..c7ae41b2cbc1eb85a6eb9c16813bd326fb8f49f0 100644
index dcb7714b2edeab8cfb0358929d07bd04cead26bf..e0e193078e550225e163149638bf9e053c0531f8 100644
--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
+++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
@@ -102,6 +102,21 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
@@ -109,6 +109,21 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
return super.shouldRender(x, y, z) && !this.isAttachedToEntity();
}
@@ -790,10 +784,10 @@ index a3e4605a81eeaca77cc3a3ab937b75a415d83037..c7ae41b2cbc1eb85a6eb9c16813bd326
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/vehicle/MinecartHopper.java b/net/minecraft/world/entity/vehicle/MinecartHopper.java
index c553cf0592dfa606dbbb1e6854d3377b9feb5efb..8341e7f01606fca90e69384c16fc19bb9e20d1b7 100644
index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98ae0a0989a 100644
--- a/net/minecraft/world/entity/vehicle/MinecartHopper.java
+++ b/net/minecraft/world/entity/vehicle/MinecartHopper.java
@@ -47,6 +47,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -48,6 +48,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
if (flag != this.isEnabled()) {
this.setEnabled(flag);
}
@@ -801,7 +795,7 @@ index c553cf0592dfa606dbbb1e6854d3377b9feb5efb..8341e7f01606fca90e69384c16fc19bb
}
public boolean isEnabled() {
@@ -100,11 +101,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -101,11 +102,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
public boolean suckInItems() {
if (HopperBlockEntity.suckInItems(this.level(), this)) {
@@ -815,7 +809,7 @@ index c553cf0592dfa606dbbb1e6854d3377b9feb5efb..8341e7f01606fca90e69384c16fc19bb
return true;
}
}
@@ -139,4 +142,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -140,4 +143,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
public AbstractContainerMenu createMenu(int id, Inventory playerInventory) {
return new HopperMenu(id, playerInventory, this);
}
@@ -828,27 +822,27 @@ index c553cf0592dfa606dbbb1e6854d3377b9feb5efb..8341e7f01606fca90e69384c16fc19bb
+
}
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 32f184288f6065259c921293922c1b0163df4dc4..0f346faa82b988e86834c38837f6f11bea7f31c6 100644
index 1aa98e4f70627632d3e676395c28fa0ecca72f56..1f26826b2161cfeb27e5b2060e178b493e9142d9 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -153,6 +153,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates
@@ -143,6 +143,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@Nullable
public List<net.minecraft.world.entity.item.ItemEntity> captureDrops;
public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
+ // Paper start
+ // Paper start - EAR 2
+ public int wakeupInactiveRemainingAnimals;
+ public int wakeupInactiveRemainingFlying;
+ public int wakeupInactiveRemainingMonsters;
+ public int wakeupInactiveRemainingVillagers;
+ // Paper end
+ // Paper end - EAR 2
public boolean populating;
public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
// Paper start - add paper world config
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index ce880bd45fbda4829d17de8507034b3a39c68cbb..ee2f8e8deb35059824b5730a1442f383dc79f01c 100644
index f8d10be7a0aa7f66f05126e75187025c040e3494..1669b76800756000a2f620610b3c8c8b6c48dd4a 100644
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -149,6 +149,10 @@ public class PistonMovingBlockEntity extends BlockEntity {
@@ -153,6 +153,10 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
entity.setDeltaMovement(d1, d2, d3);

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Anti-Xray
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
index 81ff677e970ffbe7ad5381e56852e33cf7a8ea45..184e6c6fe2ba522d0ea0774604839320c4152371 100644
index b9a838d638571bca1d00a620cedf169a3fa87e9d..329e9562e9c2b25228b04c21ff7353d2d8d6e5f6 100644
--- a/io/papermc/paper/FeatureHooks.java
+++ b/io/papermc/paper/FeatureHooks.java
@@ -37,20 +37,25 @@ public final class FeatureHooks {
@@ -55,10 +55,10 @@ index d4872b7f4e9591b3b1c67406312905851303f521..cb41460e94161675e2ab43f4b1b5286e
}
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 5d1943d37dfad0c12e77179f0866851532d983e9..3aea76690bc3e35758d3bf274777130af17d8a0f 100644
index 89761bd368d75b8fb84f850fb3f8162fa280e236..272da41db7ce4619a8e459a2f0a2221e42f58a40 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -28,7 +28,13 @@ public class ClientboundLevelChunkPacketData {
@@ -33,13 +33,23 @@ public class ClientboundLevelChunkPacketData {
private final byte[] buffer;
private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
@@ -69,12 +69,10 @@ index 5d1943d37dfad0c12e77179f0866851532d983e9..3aea76690bc3e35758d3bf274777130a
+ }
+ public ClientboundLevelChunkPacketData(LevelChunk levelChunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
+ // Paper end
this.heightmaps = new CompoundTag();
for (Entry<Heightmap.Types, Heightmap> entry : levelChunk.getHeightmaps()) {
@@ -38,7 +44,11 @@ public class ClientboundLevelChunkPacketData {
}
this.heightmaps = levelChunk.getHeightmaps()
.stream()
.filter(entry1 -> entry1.getKey().sendToClient())
.collect(Collectors.toMap(Entry::getKey, entry1 -> (long[])entry1.getValue().getRawData().clone()));
this.buffer = new byte[calculateChunkSize(levelChunk)];
- extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk);
+ // Paper start - Anti-Xray - Add chunk packet info
@@ -84,8 +82,8 @@ index 5d1943d37dfad0c12e77179f0866851532d983e9..3aea76690bc3e35758d3bf274777130a
+ extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk, chunkPacketInfo);
this.blockEntitiesData = Lists.newArrayList();
for (Entry<BlockPos, BlockEntity> entryx : levelChunk.getBlockEntities().entrySet()) {
@@ -85,9 +95,17 @@ public class ClientboundLevelChunkPacketData {
for (Entry<BlockPos, BlockEntity> entry : levelChunk.getBlockEntities().entrySet()) {
@@ -82,9 +92,17 @@ public class ClientboundLevelChunkPacketData {
return byteBuf;
}
@@ -145,10 +143,10 @@ index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index da8848e2a3e3745949eb2356a049451d30f763a7..192977dd661ee795ada13db895db770293e9b402 100644
index ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b..fe9b4484d683fe48f435a053c9c90557fdf80e7b 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -348,7 +348,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -343,7 +343,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
org.bukkit.generator.BiomeProvider biomeProvider // CraftBukkit
) {
// CraftBukkit start
@@ -156,13 +154,13 @@ index da8848e2a3e3745949eb2356a049451d30f763a7..192977dd661ee795ada13db895db7702
+ super(serverLevelData, dimension, server.registryAccess(), levelStem.type(), false, isDebug, biomeZoomSeed, server.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> server.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(levelStorageAccess.levelDirectory.path(), serverLevelData.getLevelName(), dimension.location(), spigotConfig, server.registryAccess(), serverLevelData.getGameRules())), dispatcher); // Paper - create paper world configs; Async-Anti-Xray: Pass executor
this.pvpMode = server.isPvpAllowed();
this.levelStorageAccess = levelStorageAccess;
this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getUUID(levelStorageAccess.levelDirectory.path().toFile());
this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getOrCreate(levelStorageAccess.levelDirectory.path().toFile());
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index 47ed3ad5c0b4753f58e0bafff5e5e70b2f0bb40b..623c069f1fe079e020c6391a3db1a3d95cd3dbf5 100644
index b5378d6d73b6dab56bf664024f3f82496e9a9487..b604cba2490a747661d6819251bc3b9a1d35c7d4 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -299,6 +299,7 @@ public class ServerPlayerGameMode {
org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
@@ -296,6 +296,7 @@ public class ServerPlayerGameMode {
org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelectedItem()); // CraftBukkit
}
}
+ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, action, face, maxBuildHeight, sequence); // Paper - Anti-Xray
@@ -188,10 +186,10 @@ index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 600a08d6b45cb19dbe551cefbf726e68684a0837..ff0315cffdb282fdc0a1ffd15e2954caa76835c9 100644
index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49426b581c 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -403,7 +403,7 @@ public abstract class PlayerList {
@@ -407,7 +407,7 @@ public abstract class PlayerList {
.getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, player.chunkPosition(), plains),
@@ -201,18 +199,18 @@ index 600a08d6b45cb19dbe551cefbf726e68684a0837..ff0315cffdb282fdc0a1ffd15e2954ca
}
// Paper end - Send empty chunk
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 0f346faa82b988e86834c38837f6f11bea7f31c6..771d6ed6a7c889c09efd4ff6e20298c851eaa79f 100644
index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd751911198 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -168,6 +168,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
// Paper end - add paper world config
@@ -132,6 +132,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
private long subTickCount;
// CraftBukkit start
+ public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
public static BlockPos lastPhysicsProblem; // Spigot
private org.spigotmc.TickLimiter entityLimiter;
private org.spigotmc.TickLimiter tileLimiter;
@@ -214,7 +215,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
private final CraftWorld world;
public boolean pvpMode;
public org.bukkit.generator.ChunkGenerator generator;
@@ -201,7 +202,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit
org.bukkit.World.Environment env, // CraftBukkit
java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
@@ -222,24 +220,24 @@ index 0f346faa82b988e86834c38837f6f11bea7f31c6..771d6ed6a7c889c09efd4ff6e20298c8
) {
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
@@ -295,6 +297,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -278,6 +280,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {}
});
// CraftBukkit end
this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
+ this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new io.papermc.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : io.papermc.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray
}
// Paper start - Cancel hit for vanished players
@@ -495,6 +498,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// CraftBukkit end
BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag
@@ -483,6 +486,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
snapshot.setFlags(flags); // Paper - always set the flag of the most recent call to mitigate issues with multiple update at the same pos with different flags
}
BlockState blockState = chunkAt.setBlockState(pos, state, flags);
+ this.chunkPacketBlockController.onBlockChange(this, pos, state, blockState, flags, recursionLeft); // Paper - Anti-Xray
// CraftBukkit end
if (blockState == null) {
// CraftBukkit start - remove blockstate if failed (or the same)
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index c82780db7fe5b1557a7802d3111f38099be55ac1..d63d745a0220963a297cfedf1e8983aeb471a045 100644
index c378f9e226df80ab0d4ebd06ae54ce556d0d94e7..97231db28146df56c727c9765f36277634d59a64 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@@ -261,10 +259,10 @@ index c82780db7fe5b1557a7802d3111f38099be55ac1..d63d745a0220963a297cfedf1e8983ae
}
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index ce781ba2c8b3f9f051201d3809a9cb041036f93a..cad71ac79fc52225a192aa5c5d07b13c831fc2c1 100644
index 8fa871512ad52c345f15b1f5fb1baf54bb2ec93b..08e2442f6965cc6eaab67bdf9340a5152c08db2a 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -109,7 +109,7 @@ public class LevelChunk extends ChunkAccess {
@@ -110,7 +110,7 @@ public class LevelChunk extends ChunkAccess {
@Nullable LevelChunk.PostLoadProcessor postLoad,
@Nullable BlendingData blendingData
) {
@@ -274,7 +272,7 @@ index ce781ba2c8b3f9f051201d3809a9cb041036f93a..cad71ac79fc52225a192aa5c5d07b13c
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
index b3d600b0d6deaf44f232dfc86e1456c867e1c07f..a7fabde0f32f09d7f7bed65576ce469f069a21fa 100644
index 2399a0f8839c0925a9923bae87362c2c9a217197..1aa4e39431a93a7789b74a2e3476a3e47605e2cc 100644
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -38,9 +38,15 @@ public class LevelChunkSection {
@@ -310,12 +308,12 @@ index b3d600b0d6deaf44f232dfc86e1456c867e1c07f..a7fabde0f32f09d7f7bed65576ce469f
- this.biomes.write(buffer);
+ this.states.write(buffer, chunkPacketInfo, chunkSectionIndex);
+ this.biomes.write(buffer, null, chunkSectionIndex);
+ // Paper end - Anti-Xray
+ // Paper end - Anti-Xray - Add chunk packet info
}
public int getSerializedSize() {
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
index e8ec28ce3fe13561b45c4654e174776d9d2d7b71..a6028a54c75de068515e95913b21160ab4326985 100644
index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a336a3ae55 100644
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -28,6 +28,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -454,7 +452,7 @@ index e8ec28ce3fe13561b45c4654e174776d9d2d7b71..a6028a54c75de068515e95913b21160a
this.acquire();
@@ -172,24 +239,35 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
data.palette.read(buffer);
buffer.readLongArray(data.storage.getRaw());
buffer.readFixedSizeLongArray(data.storage.getRaw());
this.data = data;
+ this.addPresetValues(); // Paper - Anti-Xray - Add preset values (inefficient, but this isn't used by the server)
} finally {
@@ -527,10 +525,10 @@ index e8ec28ce3fe13561b45c4654e174776d9d2d7b71..a6028a54c75de068515e95913b21160a
+ if (chunkPacketInfo != null) {
+ chunkPacketInfo.setBits(chunkSectionIndex, this.configuration.bits());
+ chunkPacketInfo.setPalette(chunkSectionIndex, this.palette);
+ chunkPacketInfo.setIndex(chunkSectionIndex, buffer.writerIndex() + VarInt.getByteSize(this.storage.getRaw().length));
+ chunkPacketInfo.setIndex(chunkSectionIndex, buffer.writerIndex());
+ }
+ // Paper end
buffer.writeLongArray(this.storage.getRaw());
+ // Paper end - Anti-Xray - Add chunk packet info
buffer.writeFixedSizeLongArray(this.storage.getRaw());
}
diff --git a/net/minecraft/world/level/chunk/PalettedContainerRO.java b/net/minecraft/world/level/chunk/PalettedContainerRO.java
@@ -550,7 +548,7 @@ index bfbb1a2bb4abbb369a24f2f01439e9ea3e16794b..8d6ed8be4d93f7d4e6ea80c351020d88
int getSerializedSize();
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index c7c87bc8df86ceeef3e15a8f23fc252d4cee1984..3b55e7fb27d680204b8621666ae9200870def3eb 100644
index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f96d5f6ec 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -94,7 +94,7 @@ public record SerializableChunkData(
@@ -560,51 +558,46 @@ index c7c87bc8df86ceeef3e15a8f23fc252d4cee1984..3b55e7fb27d680204b8621666ae92008
- Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()
+ Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null // Paper - Anti-Xray
);
private static final Logger LOGGER = LogUtils.getLogger();
private static final String TAG_UPGRADE_DATA = "UpgradeData";
@@ -128,6 +128,7 @@ public record SerializableChunkData(
private static final Codec<List<SavedTick<Block>>> BLOCK_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.BLOCK.byNameCodec()).listOf();
private static final Codec<List<SavedTick<Fluid>>> FLUID_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.FLUID.byNameCodec()).listOf();
@@ -130,6 +130,7 @@ public record SerializableChunkData(
@Nullable
public static SerializableChunkData parse(LevelHeightAccessor levelHeightAccessor, RegistryAccess registries, CompoundTag tag) {
+ net.minecraft.server.level.ServerLevel serverLevel = (net.minecraft.server.level.ServerLevel) levelHeightAccessor; // Paper - Anti-Xray This is is seemingly only called from ChunkMap, where, we have a server level. We'll fight this later if needed.
if (!tag.contains("Status", 8)) {
if (tag.getString("Status").isEmpty()) {
return null;
} else {
@@ -212,18 +213,21 @@ public record SerializableChunkData(
Codec<PalettedContainer<Holder<Biome>>> codec = makeBiomeCodecRW(registry); // CraftBukkit - read/write
for (int i2 = 0; i2 < list7.size(); i2++) {
- CompoundTag compound2 = list7.getCompound(i2);
+ CompoundTag compound2 = list7.getCompound(i2); final CompoundTag sectionData = compound2; // Paper - Anti-Xray - OBFHELPER
int _byte = compound2.getByte("Y");
LevelChunkSection levelChunkSection;
if (_byte >= levelHeightAccessor.getMinSectionY() && _byte <= levelHeightAccessor.getMaxSectionY()) {
+ // Paper start - Anti-Xray - Add preset block states
+ BlockState[] presetBlockStates = serverLevel.chunkPacketBlockController.getPresetBlockStates(serverLevel, chunkPos, _byte);
PalettedContainer<BlockState> palettedContainer;
if (compound2.contains("block_states", 10)) {
- palettedContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, compound2.getCompound("block_states"))
+ Codec<PalettedContainer<BlockState>> blockStateCodec = presetBlockStates == null ? BLOCK_STATE_CODEC : PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), presetBlockStates); // Paper - Anti-Xray
+ palettedContainer = blockStateCodec.parse(NbtOps.INSTANCE, sectionData.getCompound("block_states")) // Paper - Anti-Xray
.promotePartial(string -> logErrors(chunkPos, _byte, string))
.getOrThrow(SerializableChunkData.ChunkReadException::new);
} else {
palettedContainer = new PalettedContainer<>(
- Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES
+ Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, presetBlockStates // Paper - Anti-Xray
);
}
@@ -234,7 +238,7 @@ public record SerializableChunkData(
.getOrThrow(SerializableChunkData.ChunkReadException::new);
} else {
palettedContainerRo = new PalettedContainer<>(
- registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES
+ registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null // Paper - Anti-Xray - Add preset biomes
);
}
@@ -414,7 +418,7 @@ public record SerializableChunkData(
@@ -190,15 +191,17 @@ public record SerializableChunkData(
int byteOr = compoundTag.getByteOr("Y", (byte)0);
LevelChunkSection levelChunkSection;
if (byteOr >= levelHeightAccessor.getMinSectionY() && byteOr <= levelHeightAccessor.getMaxSectionY()) {
+ final BlockState[] presetBlockStates = serverLevel.chunkPacketBlockController.getPresetBlockStates(serverLevel, chunkPos, byteOr); // Paper - Anti-Xray - Add preset block states
+ final Codec<PalettedContainer<BlockState>> blockStateCodec = presetBlockStates == null ? BLOCK_STATE_CODEC : PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), presetBlockStates); // Paper - Anti-Xray
PalettedContainer<BlockState> palettedContainer = compoundTag.getCompound("block_states")
.map(
- compoundTag1 -> BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, compoundTag1)
+ compoundTag1 -> blockStateCodec.parse(NbtOps.INSTANCE, compoundTag1) // Paper - Anti-Xray
.promotePartial(string -> logErrors(chunkPos, byteOr, string))
.getOrThrow(SerializableChunkData.ChunkReadException::new)
)
.orElseGet(
() -> new PalettedContainer<>(
- Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES
+ Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, presetBlockStates // Paper - Anti-Xray - Add preset biomes
)
);
PalettedContainer<Holder<Biome>> palettedContainerRo = compoundTag.getCompound("biomes") // CraftBukkit - read/write
@@ -209,7 +212,7 @@ public record SerializableChunkData(
)
.orElseGet(
() -> new PalettedContainer<>(
- registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES
+ registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null // Paper - Anti-Xray - Add preset biomes
)
);
levelChunkSection = new LevelChunkSection(palettedContainer, palettedContainerRo);
@@ -382,7 +385,7 @@ public record SerializableChunkData(
// CraftBukkit start - read/write
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> biomeRegistry) {

View File

@@ -269,7 +269,7 @@ index bc674b08a41d5529fe06c6d3f077051cf4138f73..ea8a894158c44c2e7943dea43ecd8e1f
+ // Paper end - Use Velocity cipher
}
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
index ad8f8428b75e37097487cdfbd0db2421ee4cbe37..208efae06c7c44f220d4192219a86ec55c98a2fe 100644
index 2040b9555c430420a8a8697cc131d42eafb96fa1..4ed9611994c5c8da01fede690197527c5b3a5731 100644
--- a/net/minecraft/network/Connection.java
+++ b/net/minecraft/network/Connection.java
@@ -772,11 +772,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -336,10 +336,10 @@ index 7de11ba404f0b60e7f7b7c16954811a343688219..bd07e6a5aa1883786d789ea71711a0c0
this.channels
.add(
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index bb28453d230921d662ed69c8dd48021f428ef060..6689aeacf50d1498e8d23cce696fb4fecbd1cf39 100644
index 5d48487568994860c153351ad4c6c33bc8aa5309..7950f4f88d8a83ed5610b7af4e134557d32da3f0 100644
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -276,11 +276,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
@@ -275,11 +275,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
}
SecretKey secretKey = packet.getSecretKey(_private);

View File

@@ -14,19 +14,19 @@ movement will load only the chunk the player enters anyways and avoids loading
massive amounts of surrounding chunks due to large AABB lookups.
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 054ece1d539d69a4b7eec57e681179343c7e75c3..6f35067c64f378e955261e763f2bda9a0a6d0153 100644
index a8eaccde3ec9ed912cbc6df0b29e9f8136a46578..0f6ca6ef161ac2934ba761a1eca3215290c7262b 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -218,6 +218,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -223,6 +223,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Share random for entities to make them more random
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
+ public boolean collisionLoadChunks = false; // Paper
private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
diff --git a/net/minecraft/world/level/BlockCollisions.java b/net/minecraft/world/level/BlockCollisions.java
index fd2c338db43aad070cc32c24891b40599c544ac9..2861ea4b699d403b1245f8be5a62503d366ded65 100644
index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd3385dd7a 100644
--- a/net/minecraft/world/level/BlockCollisions.java
+++ b/net/minecraft/world/level/BlockCollisions.java
@@ -80,16 +80,37 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
@@ -76,7 +76,7 @@ index fd2c338db43aad070cc32c24891b40599c544ac9..2861ea4b699d403b1245f8be5a62503d
&& (nextType != 2 || blockState.is(Blocks.MOVING_PISTON))) {
VoxelShape collisionShape = this.context.getCollisionShape(blockState, this.collisionGetter, this.pos);
diff --git a/net/minecraft/world/level/CollisionGetter.java b/net/minecraft/world/level/CollisionGetter.java
index cb54c3aadd8f3c719d3f7ef1fda4aa517919b7c3..844f76a38884e823a558fe59c421ffd4711f80b4 100644
index 79af1e4dd1f84580e509ac3e9a77bcd5531c8da6..a031d39854eb049a701f3de9e11c73419883d5ca 100644
--- a/net/minecraft/world/level/CollisionGetter.java
+++ b/net/minecraft/world/level/CollisionGetter.java
@@ -50,11 +50,13 @@ public interface CollisionGetter extends BlockGetter {

View File

@@ -67,10 +67,10 @@ index 60b56a5086b8aad0fad693f686b89138b3a4c80d..5b079ec43c259368d0eed4e838588071
this.firstIndices = new int[i];
this.secondIndices = new int[i];
diff --git a/net/minecraft/world/phys/shapes/Shapes.java b/net/minecraft/world/phys/shapes/Shapes.java
index e1b4c4b53844b0755e0640a05e8782fd9a7700a2..e759221fb54aa510d2d8bbba47e1d794367aec6d 100644
index fe8361535526d9aabdf80390aa84570c580981aa..e6038bbe8513e434daa9ea10bfa817afef0445db 100644
--- a/net/minecraft/world/phys/shapes/Shapes.java
+++ b/net/minecraft/world/phys/shapes/Shapes.java
@@ -279,9 +279,22 @@ public final class Shapes {
@@ -286,9 +286,22 @@ public final class Shapes {
}
@VisibleForTesting
@@ -94,7 +94,7 @@ index e1b4c4b53844b0755e0640a05e8782fd9a7700a2..e759221fb54aa510d2d8bbba47e1d794
if (list1 instanceof CubePointRange && list2 instanceof CubePointRange) {
long l = lcm(i, i1);
if (size * l <= 256L) {
@@ -289,14 +302,21 @@ public final class Shapes {
@@ -296,14 +309,21 @@ public final class Shapes {
}
}

View File

@@ -9,11 +9,11 @@ creating too large of a packet to sed.
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 3aea76690bc3e35758d3bf274777130af17d8a0f..9e321ef1c3d5803519b243685f4ee598dc0cf640 100644
index 272da41db7ce4619a8e459a2f0a2221e42f58a40..526c117e0d53ad527eb610c79cdc46ec16b18c0c 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -27,6 +27,14 @@ public class ClientboundLevelChunkPacketData {
private final CompoundTag heightmaps;
@@ -32,6 +32,14 @@ public class ClientboundLevelChunkPacketData {
private final Map<Heightmap.Types, long[]> heightmaps;
private final byte[] buffer;
private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
+ // Paper start - Handle oversized block entities in chunks
@@ -27,23 +27,23 @@ index 3aea76690bc3e35758d3bf274777130af17d8a0f..9e321ef1c3d5803519b243685f4ee598
// Paper start - Anti-Xray - Add chunk packet info
@Deprecated @io.papermc.paper.annotation.DoNotUse
@@ -50,8 +58,18 @@ public class ClientboundLevelChunkPacketData {
@@ -51,8 +59,18 @@ public class ClientboundLevelChunkPacketData {
}
extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk, chunkPacketInfo);
this.blockEntitiesData = Lists.newArrayList();
+ int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
for (Entry<BlockPos, BlockEntity> entryx : levelChunk.getBlockEntities().entrySet()) {
for (Entry<BlockPos, BlockEntity> entry : levelChunk.getBlockEntities().entrySet()) {
+ // Paper start - Handle oversized block entities in chunks
+ if (++totalTileEntities > BLOCK_ENTITY_LIMIT) {
+ net.minecraft.network.protocol.Packet<ClientGamePacketListener> packet = entryx.getValue().getUpdatePacket();
+ net.minecraft.network.protocol.Packet<ClientGamePacketListener> packet = entry.getValue().getUpdatePacket();
+ if (packet != null) {
+ this.extraPackets.add(packet);
+ continue;
+ }
+ }
+ // Paper end - Handle oversized block entities in chunks
this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entryx.getValue()));
this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entry.getValue()));
}
}
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] optimize dirt and snow spreading
diff --git a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
index 11937aa74efe08bdbd66a619c7a825f91d971afd..722f2b9a24679e0fc67aae2cd27051f96f962efe 100644
index d1c112a50ca2c16e4a5c91be2cc91c302918a1c7..f8cc3f870d88715386bb4de0da81a74fa04fd216 100644
--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
+++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
@@ -17,8 +17,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
@@ -58,7 +58,7 @@ index 11937aa74efe08bdbd66a619c7a825f91d971afd..722f2b9a24679e0fc67aae2cd27051f9
for (int i = 0; i < 4; i++) {
BlockPos blockPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
- if (level.getBlockState(blockPos).is(Blocks.DIRT) && canPropagate(blockState, level, blockPos)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState.setValue(SNOWY, Boolean.valueOf(isSnowySetting(level.getBlockState(blockPos.above()))))); // CraftBukkit
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState.setValue(SNOWY, isSnowySetting(level.getBlockState(blockPos.above()))), 3); // CraftBukkit
+ // Paper start - Perf: optimize dirt and snow spreading
+ if (pos.getX() == blockPos.getX() && pos.getY() == blockPos.getY() && pos.getZ() == blockPos.getZ()) {
+ continue;
@@ -71,7 +71,7 @@ index 11937aa74efe08bdbd66a619c7a825f91d971afd..722f2b9a24679e0fc67aae2cd27051f9
+ access = level.getChunkAt(blockPos);
+ }
+ if (access.getBlockState(blockPos).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(access, blockState, level, blockPos)) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, (BlockState) blockState.setValue(SpreadingSnowyDirtBlock.SNOWY, isSnowySetting(access.getBlockState(blockPos.above())))); // CraftBukkit
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState.setValue(SNOWY, isSnowySetting(access.getBlockState(blockPos.above()))), 3); // CraftBukkit
+ // Paper end - Perf: optimize dirt and snow spreading
}
}

View File

@@ -7,10 +7,10 @@ bypass the need to get a player chunk, then get the either,
then unwrap it...
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index c3553385074108d686425a7637b8975076d906b9..2f49dbc919f7f5eea9abce6106723c72f5ae45fb 100644
index 006d8abe66b2d66740b984d8ff7f56a41b9929f7..52104bcd74107bb9a475109230ca85dd2eba5b06 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -218,6 +218,12 @@ public class ServerChunkCache extends ChunkSource {
@@ -224,6 +224,12 @@ public class ServerChunkCache extends ChunkSource {
if (Thread.currentThread() != this.mainThread) {
return CompletableFuture.<ChunkAccess>supplyAsync(() -> this.getChunk(x, z, chunkStatus, requireChunk), this.mainThreadProcessor).join();
} else {
@@ -23,7 +23,7 @@ index c3553385074108d686425a7637b8975076d906b9..2f49dbc919f7f5eea9abce6106723c72
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.incrementCounter("getChunk");
long packedChunkPos = ChunkPos.asLong(x, z);
@@ -252,30 +258,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -258,30 +264,7 @@ public class ServerChunkCache extends ChunkSource {
if (Thread.currentThread() != this.mainThread) {
return null;
} else {

View File

@@ -84,7 +84,7 @@ index 98f0b1cf19d7a035849a9a2fa25e2be3a4c5a980..a81694a22e94cca6f7110f7d5b205d13
public static long getFlatIndex(long packedPos) {
diff --git a/net/minecraft/core/SectionPos.java b/net/minecraft/core/SectionPos.java
index 1780d8e14cea62971da75e4dcc80d1805434037b..ce8c394ea1a7bc5bf5c568c82e6158b19df517d8 100644
index ce076662d2ffbb570c8c225e9635de490ea535e8..2fb2e3434c0e495ab4d5cb6d2718717cd0a269f2 100644
--- a/net/minecraft/core/SectionPos.java
+++ b/net/minecraft/core/SectionPos.java
@@ -38,7 +38,7 @@ public class SectionPos extends Vec3i {
@@ -167,7 +167,7 @@ index 1780d8e14cea62971da75e4dcc80d1805434037b..ce8c394ea1a7bc5bf5c568c82e6158b1
}
public static long getZeroNode(int x, int z) {
@@ -205,15 +210,17 @@ public class SectionPos extends Vec3i {
@@ -209,15 +214,17 @@ public class SectionPos extends Vec3i {
return asLong(blockToSectionCoord(blockPos.getX()), blockToSectionCoord(blockPos.getY()), blockToSectionCoord(blockPos.getZ()));
}
@@ -190,7 +190,7 @@ index 1780d8e14cea62971da75e4dcc80d1805434037b..ce8c394ea1a7bc5bf5c568c82e6158b1
}
@Override
@@ -226,16 +233,13 @@ public class SectionPos extends Vec3i {
@@ -230,16 +237,13 @@ public class SectionPos extends Vec3i {
}
public static Stream<SectionPos> cube(SectionPos center, int radius) {

View File

@@ -98,18 +98,27 @@ index c215d97c24e6501e1a48a76fc08bf48ff4dfe462..bd31d1cac0d022a72bd536c41d1ef811
}
}
diff --git a/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
index 2c839dc80f451c83135828a97aced1a531004bab..b74a4ce1b629d440681a1f5c026997ccaf1d0373 100644
index d93ef8d7ff04ffd3d7434ea6e2d476115203215b..425ca1931fb0a5c33ba7aaf4f639409c9fea836f 100644
--- a/net/minecraft/world/entity/ai/gossip/GossipContainer.java
+++ b/net/minecraft/world/entity/ai/gossip/GossipContainer.java
@@ -59,8 +59,22 @@ public class GossipContainer {
return this.gossips.entrySet().stream().flatMap(gossip -> gossip.getValue().unpack(gossip.getKey()));
@@ -28,7 +28,7 @@ import net.minecraft.util.VisibleForDebug;
public class GossipContainer {
public static final Codec<GossipContainer> CODEC = GossipContainer.GossipEntry.CODEC
.listOf()
- .xmap(GossipContainer::new, gossipContainer -> gossipContainer.unpack().toList());
+ .xmap(GossipContainer::new, gossipContainer -> gossipContainer.decompress()); // Paper - Perf: Remove streams from hot code
public static final int DISCARD_THRESHOLD = 2;
public final Map<UUID, GossipContainer.EntityGossips> gossips = new HashMap<>();
@@ -65,8 +65,22 @@ public class GossipContainer {
return this.gossips.entrySet().stream().flatMap(entry -> entry.getValue().unpack(entry.getKey()));
}
+ // Paper start - Perf: Remove streams from hot code
+ private List<GossipContainer.GossipEntry> decompress() {
+ List<GossipContainer.GossipEntry> list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
+ for (Map.Entry<UUID, GossipContainer.EntityGossips> entry : this.gossips.entrySet()) {
+ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) {
+ final List<GossipContainer.GossipEntry> list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
+ for (final Map.Entry<UUID, GossipContainer.EntityGossips> entry : this.gossips.entrySet()) {
+ for (final GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) {
+ if (cur.weightedValue() != 0) {
+ list.add(cur);
+ }
@@ -125,16 +134,7 @@ index 2c839dc80f451c83135828a97aced1a531004bab..b74a4ce1b629d440681a1f5c026997cc
if (list.isEmpty()) {
return Collections.emptyList();
} else {
@@ -145,7 +159,7 @@ public class GossipContainer {
public <T> T store(DynamicOps<T> ops) {
return GossipContainer.GossipEntry.LIST_CODEC
- .encodeStart(ops, this.unpack().toList())
+ .encodeStart(ops, this.decompress()) // Paper - Perf: Remove streams from hot code
.resultOrPartial(errorMessage -> LOGGER.warn("Failed to serialize gossips: {}", errorMessage))
.orElseGet(ops::emptyList);
}
@@ -172,12 +186,23 @@ public class GossipContainer {
@@ -176,12 +190,23 @@ public class GossipContainer {
final Object2IntMap<GossipType> entries = new Object2IntOpenHashMap<>();
public int weightedValue(Predicate<GossipType> gossipType) {
@@ -194,7 +194,7 @@ index 38873e56e95dc772b184e4271f7af1fb411ac9f8..09fd13e2d958da8326276c4dadf25bf4
}
}
diff --git a/net/minecraft/world/level/levelgen/Beardifier.java b/net/minecraft/world/level/levelgen/Beardifier.java
index 1a09da5aa1ae047a002d6779326c2a29e47d32b5..131923282c9ecbcb1d7f45a826da907c02bd2716 100644
index 8bc2dd4fa128fc2f88b974b8712cb0953a024eaa..74d8202b5c9bb2a3ee832be70f95c0b5cbecb460 100644
--- a/net/minecraft/world/level/levelgen/Beardifier.java
+++ b/net/minecraft/world/level/levelgen/Beardifier.java
@@ -35,9 +35,10 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
@@ -211,7 +211,7 @@ index 1a09da5aa1ae047a002d6779326c2a29e47d32b5..131923282c9ecbcb1d7f45a826da907c
TerrainAdjustment terrainAdjustment = structureStart.getStructure().terrainAdaptation();
for (StructurePiece structurePiece : structureStart.getPieces()) {
@@ -65,8 +66,7 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
@@ -64,8 +65,7 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
}
}
}

View File

@@ -48,10 +48,10 @@ index db31989ebe3d7021cfd2311439e9a00f819b0841..1373977b339405ef59bb3ea03d195285
serverEntity.getLastSentYRot(),
entity.getType(),
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 3dff97f13586be3b52bbe786852c185f6753a019..ff6503bf8eb88d1264c3d848a89d0255b4b3ae68 100644
index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589a7781070 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1208,6 +1208,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1278,6 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.serverEntity.addPairing(player);
}
// Paper end - entity tracking events
@@ -60,10 +60,10 @@ index 3dff97f13586be3b52bbe786852c185f6753a019..ff6503bf8eb88d1264c3d848a89d0255
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b75c7d7e59 100644
index 0005a1784ccaa00e5d6d67e7be98445150487982..257ecbcf7d463eefb951867a5426eaf24e356305 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -90,6 +90,13 @@ public class ServerEntity {
@@ -103,6 +103,13 @@ public class ServerEntity {
this.trackedDataValues = entity.getEntityData().getNonDefaultValues();
}
@@ -77,7 +77,7 @@ index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b7
public void sendChanges() {
// Paper start - optimise collisions
if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) {
@@ -131,7 +138,7 @@ public class ServerEntity {
@@ -136,7 +143,7 @@ public class ServerEntity {
this.sendDirtyEntityData();
}
@@ -86,7 +86,7 @@ index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b7
byte b = Mth.packDegrees(this.entity.getYRot());
byte b1 = Mth.packDegrees(this.entity.getXRot());
boolean flag = Math.abs(b - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1;
@@ -166,7 +173,7 @@ public class ServerEntity {
@@ -171,7 +178,7 @@ public class ServerEntity {
long l1 = this.positionCodec.encodeY(vec3);
long l2 = this.positionCodec.encodeZ(vec3);
boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L;
@@ -95,7 +95,7 @@ index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b7
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
@@ -231,6 +238,7 @@ public class ServerEntity {
@@ -236,6 +243,7 @@ public class ServerEntity {
}
this.entity.hasImpulse = false;

View File

@@ -978,10 +978,10 @@ index 0000000000000000000000000000000000000000..ff747a1ecdf3c888bca0d69de4f85dcd
+ }
+}
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 84e6c986917128d4488afa23d29c689cadb4f55d..f02232ce97779db0d12a5d5da1d767326d78ea4c 100644
index cbdf514e190385339476a17c7426c55daec9f2a1..50eceaed6907a596c0c1cd87f5927e07d33a5dbb 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -290,6 +290,60 @@ public class RedStoneWireBlock extends Block {
@@ -265,6 +265,60 @@ public class RedStoneWireBlock extends Block {
return state.isFaceSturdy(level, pos, Direction.UP) || state.is(Blocks.HOPPER);
}
@@ -1042,7 +1042,7 @@ index 84e6c986917128d4488afa23d29c689cadb4f55d..f02232ce97779db0d12a5d5da1d76732
private void updatePowerStrength(Level level, BlockPos pos, BlockState state, @Nullable Orientation orientation, boolean updateShape) {
if (useExperimentalEvaluator(level)) {
new ExperimentalRedstoneWireEvaluator(this).updatePowerStrength(level, pos, state, orientation, updateShape);
@@ -318,7 +372,7 @@ public class RedStoneWireBlock extends Block {
@@ -293,7 +347,7 @@ public class RedStoneWireBlock extends Block {
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
if (!oldState.is(state.getBlock()) && !level.isClientSide) {
@@ -1051,16 +1051,16 @@ index 84e6c986917128d4488afa23d29c689cadb4f55d..f02232ce97779db0d12a5d5da1d76732
for (Direction direction : Direction.Plane.VERTICAL) {
level.updateNeighborsAt(pos.relative(direction), this);
@@ -337,7 +391,7 @@ public class RedStoneWireBlock extends Block {
level.updateNeighborsAt(pos.relative(direction), this);
}
- this.updatePowerStrength(level, pos, state, null, false);
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Paper - Optimize redstone
this.updateNeighborsOfNeighboringWires(level, pos);
@@ -310,7 +364,7 @@ public class RedStoneWireBlock extends Block {
level.updateNeighborsAt(pos.relative(direction), this);
}
- this.updatePowerStrength(level, pos, state, null, false);
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Paper - Optimize redstone
this.updateNeighborsOfNeighboringWires(level, pos);
}
@@ -363,7 +417,7 @@ public class RedStoneWireBlock extends Block {
}
@@ -335,7 +389,7 @@ public class RedStoneWireBlock extends Block {
if (!level.isClientSide) {
if (neighborBlock != this || !useExperimentalEvaluator(level)) {
if (state.canSurvive(level, pos)) {
@@ -1070,7 +1070,7 @@ index 84e6c986917128d4488afa23d29c689cadb4f55d..f02232ce97779db0d12a5d5da1d76732
dropResources(state, level, pos);
level.removeBlock(pos, false);
diff --git a/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java b/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
index 380fc51a252022195e178daccd8aa53dd1d71a2e..2d77780b6727f82ffc3cb216ca5f2d6483496cfd 100644
index 3f6f3ca5a5e412e57fad635f52cd152520d6dca2..abcc144a086a45bf4cfa4d1a33e2ae10952e0da2 100644
--- a/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
+++ b/net/minecraft/world/level/redstone/DefaultRedstoneWireEvaluator.java
@@ -44,7 +44,7 @@ public class DefaultRedstoneWireEvaluator extends RedstoneWireEvaluator {

View File

@@ -2326,18 +2326,18 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
+ }
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index a293d1481b5f4a1d18addc3e518486c639223f09..5bf38ab129451e867b638cfbd2d7be59cbf7f38d 100644
index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -214,6 +214,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final UUID uuid;
@@ -210,6 +210,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final java.util.UUID uuid;
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
+ private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
public LevelChunk getChunkIfLoaded(int x, int z) {
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
@@ -2557,6 +2558,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
@@ -2552,6 +2553,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.chunkSource.getGenerator().getSeaLevel();
}
@@ -2352,12 +2352,12 @@ index a293d1481b5f4a1d18addc3e518486c639223f09..5bf38ab129451e867b638cfbd2d7be59
@Override
public void onCreated(Entity entity) {
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index a768f041fd16d253ec4ab5eb75288b1771d5cb00..1dbe7c7c1051c3972105534a07ce50d4cf98fc85 100644
index eb4d03cfdb34243901cfba832d35559d5be9e876..013ed7dbe2309f562f63e66203179a90566e8115 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -2099,6 +2099,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public abstract FuelValues fuelValues();
@@ -2096,6 +2096,17 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
return 0;
}
+ // Paper start - optimize redstone (Alternate Current)
+ public alternate.current.wire.WireHandler getWireHandler() {
@@ -2374,10 +2374,10 @@ index a768f041fd16d253ec4ab5eb75288b1771d5cb00..1dbe7c7c1051c3972105534a07ce50d4
NONE("none"),
BLOCK("block"),
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index f02232ce97779db0d12a5d5da1d767326d78ea4c..12c9d60314c99fb65e640d255a2d0c6b7790ad4d 100644
index 50eceaed6907a596c0c1cd87f5927e07d33a5dbb..1943a6aad888647953e2d9dbbeedb0bd81c6f9df 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -290,7 +290,7 @@ public class RedStoneWireBlock extends Block {
@@ -265,7 +265,7 @@ public class RedStoneWireBlock extends Block {
return state.isFaceSturdy(level, pos, Direction.UP) || state.is(Blocks.HOPPER);
}
@@ -2386,7 +2386,7 @@ index f02232ce97779db0d12a5d5da1d767326d78ea4c..12c9d60314c99fb65e640d255a2d0c6b
// The bulk of the new functionality is found in RedstoneWireTurbo.java
io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo(this);
@@ -372,7 +372,13 @@ public class RedStoneWireBlock extends Block {
@@ -347,7 +347,13 @@ public class RedStoneWireBlock extends Block {
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
if (!oldState.is(state.getBlock()) && !level.isClientSide) {
@@ -2401,22 +2401,22 @@ index f02232ce97779db0d12a5d5da1d767326d78ea4c..12c9d60314c99fb65e640d255a2d0c6b
for (Direction direction : Direction.Plane.VERTICAL) {
level.updateNeighborsAt(pos.relative(direction), this);
@@ -391,7 +397,13 @@ public class RedStoneWireBlock extends Block {
level.updateNeighborsAt(pos.relative(direction), this);
}
- this.updateSurroundingRedstone(level, pos, state, null, false); // Paper - Optimize redstone
+ // Paper start - optimize redstone - replace call to updatePowerStrength
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
+ } else {
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
+ }
+ // Paper end - optimize redstone
this.updateNeighborsOfNeighboringWires(level, pos);
@@ -364,7 +370,13 @@ public class RedStoneWireBlock extends Block {
level.updateNeighborsAt(pos.relative(direction), this);
}
- this.updateSurroundingRedstone(level, pos, state, null, false); // Paper - Optimize redstone
+ // Paper start - optimize redstone - replace call to updatePowerStrength
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
+ } else {
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
+ }
+ // Paper end - optimize redstone
this.updateNeighborsOfNeighboringWires(level, pos);
}
@@ -415,9 +427,15 @@ public class RedStoneWireBlock extends Block {
}
@@ -387,9 +399,15 @@ public class RedStoneWireBlock extends Block {
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {
if (!level.isClientSide) {

View File

@@ -150,7 +150,7 @@ index 0000000000000000000000000000000000000000..f47c12e9dd6cfa857ca07a764edc22de
+ }
+}
diff --git a/net/minecraft/recipebook/ServerPlaceRecipe.java b/net/minecraft/recipebook/ServerPlaceRecipe.java
index 6475509689439636275b06b9eac33f0922d8fcfd..6c398c91909f42e352e80d0781549df9d834a060 100644
index 6d3e3ec045d5b15a435f7217369968b33e082724..b7a3758af337270737041f84d10eb43784e42279 100644
--- a/net/minecraft/recipebook/ServerPlaceRecipe.java
+++ b/net/minecraft/recipebook/ServerPlaceRecipe.java
@@ -40,6 +40,7 @@ public class ServerPlaceRecipe<R extends Recipe<?>> {
@@ -204,10 +204,10 @@ index 6475509689439636275b06b9eac33f0922d8fcfd..6c398c91909f42e352e80d0781549df9
int i = this.inventory.findSlotMatchingCraftingIngredient(item, item1);
if (i == -1) {
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
index 8a29d771046667db22fba166fa5337de1896cd0d..839cbb67d3d38960d9114a4db5bab911b66a573c 100644
index 24d32c0163d27a7886bd4048d508591b89f714a4..dd406c5becacbc2d05b062726a8af88a1d6faba9 100644
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -185,12 +185,12 @@ public class Inventory implements Container, Nameable {
@@ -230,12 +230,12 @@ public class Inventory implements Container, Nameable {
return !stack.isDamaged() && !stack.isEnchanted() && !stack.has(DataComponents.CUSTOM_NAME);
}

View File

@@ -45,7 +45,7 @@ index 984db72272d552c7210bd6f437ea88694ddd2828..dea2823a9d1d69dcb0a4759d8ea9b301
public void close() throws IOException {
ByteBuffer byteBuffer = ByteBuffer.wrap(this.buf, 0, this.count);
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index e35bb5534e2fbd2e30154a15ff6d39baa121608f..d263f78fa610ce6f6fb5a0f5e064e3d8335c2199 100644
index 50bbd8c778bfa9fc9ce93ed09a6fe4dc1f516d51..e9c7e56343238cfce3f4a3c658f2983ca1ef3f0e 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -15,6 +15,7 @@ import net.minecraft.util.ExceptionCollector;

View File

@@ -9,7 +9,7 @@ defaults are only included for certain entites, this allows setting
limits for any entity type.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
index 7aea4e343581b977d11af90f9f65eac3532eade1..d21ce54ebb5724c04eadf56a2cde701d5eeb5db2 100644
index 1c82dcd38f789707e15e8cbec72ef9cdc7efdf56..ba20e87d2105ce53cdaf4049de2388d05fcd1b56 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
@@ -104,7 +104,18 @@ public final class ChunkEntitySlices {
@@ -32,35 +32,35 @@ index 7aea4e343581b977d11af90f9f65eac3532eade1..d21ce54ebb5724c04eadf56a2cde701d
if (entity.save(compoundTag)) {
entitiesTag.add(compoundTag);
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 73cdfa5a315ed259b38dfa946a0b7955d9ac9f50..49201d6664656ebe34c84c1c84b5ea4878729062 100644
index 4c57990c94721dd0973477669e1dadfab5f16404..8af02ed823da098a5592ef195c9fe8ed8f245b53 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1420,9 +1420,20 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
public static Stream<Entity> loadEntitiesRecursive(final List<? extends Tag> entityTags, final Level level, final EntitySpawnReason spawnReason) {
final Spliterator<? extends Tag> spliterator = entityTags.spliterator();
return StreamSupport.stream(new Spliterator<Entity>() {
+ final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
@Override
public boolean tryAdvance(Consumer<? super Entity> consumer) {
return spliterator.tryAdvance(tag -> EntityType.loadEntityRecursive((CompoundTag)tag, level, spawnReason, entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (this.loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return null;
+ }
+ this.loadedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
consumer.accept(entity);
return entity;
}));
@@ -1430,9 +1430,20 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}
public static Stream<Entity> loadEntitiesRecursive(List<? extends Tag> entityTags, Level level, EntitySpawnReason spawnReason) {
+ final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
return entityTags.stream()
.flatMap(tag -> tag.asCompound().stream())
.mapMulti((compoundTag, consumer) -> loadEntityRecursive(compoundTag, level, spawnReason, entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return null;
+ }
+ loadedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
consumer.accept(entity);
return entity;
}));
diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java
index da05fb780c55381a7a08ced51d01764a645740b2..2856206eafddfcbcc1b65408deda40357f43a6f8 100644
index bcc2a4081fac07c4579c3aabfe4353743f8cd876..f9fb1380be9cbe960127c208c65c19f770e50b6d 100644
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -93,7 +93,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
@@ -87,7 +87,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
}
} else {
ListTag listTag = new ListTag();

View File

@@ -617,7 +617,7 @@ index dea2823a9d1d69dcb0a4759d8ea9b3015ede20dc..0c41177462cca5c4bbab6490e323b953
return byteBuffer;
}
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index d263f78fa610ce6f6fb5a0f5e064e3d8335c2199..dad7f94b611cf0fc68b1a3878c458233f6bb6d61 100644
index e9c7e56343238cfce3f4a3c658f2983ca1ef3f0e..f3ea8b9e8f4510112ec5e41727ebc0cf9ecee195 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -23,6 +23,36 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -686,7 +686,7 @@ index d263f78fa610ce6f6fb5a0f5e064e3d8335c2199..dad7f94b611cf0fc68b1a3878c458233
return var4;
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java b/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
index 0c739ca5b01ac0ec35a11fd01c5fc65de97c2852..de7deee4b79c969a7797bd57b657a16404c15303 100644
index 1649119f45d970a9bf1683d676c47ecfc18ad047..cc544f3199cd6af29e50362923d0651705877f16 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
@@ -21,7 +21,7 @@ import org.slf4j.Logger;
@@ -699,10 +699,10 @@ index 0c739ca5b01ac0ec35a11fd01c5fc65de97c2852..de7deee4b79c969a7797bd57b657a164
public static final RegionFileVersion VERSION_GZIP = register(
new RegionFileVersion(
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 879d411775a2fece1d8a970300cb3a550baa6305..6b6aaeca14178b5b709e20ae13552d42217f15c0 100644
index 03d1527073cf827fc3e191915fe5f7f064e36c3b..749096358fccbd5d1d13801092255c51096eb001 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -120,6 +120,18 @@ public record SerializableChunkData(
@@ -122,6 +122,18 @@ public record SerializableChunkData(
}
}
// Paper end - guard against serializing mismatching coordinates
@@ -711,17 +711,17 @@ index 879d411775a2fece1d8a970300cb3a550baa6305..6b6aaeca14178b5b709e20ae13552d42
+ public static long getLastWorldSaveTime(final CompoundTag chunkData) {
+ final int dataVersion = ChunkStorage.getVersion(chunkData);
+ if (dataVersion < 2842) { // Level tag is removed after this version
+ final CompoundTag levelData = chunkData.getCompound("Level");
+ return levelData.getLong("LastUpdate");
+ final CompoundTag levelData = chunkData.getCompoundOrEmpty("Level");
+ return levelData.getLongOr("LastUpdate", 0L);
+ } else {
+ return chunkData.getLong("LastUpdate");
+ return chunkData.getLongOr("LastUpdate", 0L);
+ }
+ }
+ // Paper end - Attempt to recalculate regionfile header if it is corrupt
// Paper start - Do not let the server load chunks from newer versions
private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion();
@@ -604,7 +616,7 @@ public record SerializableChunkData(
@@ -571,7 +583,7 @@ public record SerializableChunkData(
compoundTag.putInt("xPos", this.chunkPos.x);
compoundTag.putInt("yPos", this.minSectionY);
compoundTag.putInt("zPos", this.chunkPos.z);
@@ -729,4 +729,4 @@ index 879d411775a2fece1d8a970300cb3a550baa6305..6b6aaeca14178b5b709e20ae13552d42
+ compoundTag.putLong("LastUpdate", this.lastUpdateTime); // Paper - Diff on change
compoundTag.putLong("InhabitedTime", this.inhabitedTime);
compoundTag.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(this.chunkStatus).toString());
if (this.blendingData != null) {
compoundTag.storeNullable("blending_data", BlendingData.Packed.CODEC, this.blendingData);

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 409c1134327bfcc338c3ac5e658a83cc396645d1..cc2d442682496197d29ace79b22e6cf6fb7edf5e 100644
index 00f7f4356d6bffdd31f58b9d798c755edd9cd3ff..ea85cac4a41075efe8525c40755e7ebac6ca9dea 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -960,7 +960,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -952,7 +952,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
boolean var4;
try {
this.isSaving = true;
@@ -17,7 +17,7 @@ index 409c1134327bfcc338c3ac5e658a83cc396645d1..cc2d442682496197d29ace79b22e6cf6
var4 = this.saveAllChunks(suppressLog, flush, forced);
} finally {
this.isSaving = false;
@@ -1533,9 +1533,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1531,9 +1531,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
this.ticksUntilAutosave--;
@@ -50,11 +50,11 @@ index 409c1134327bfcc338c3ac5e658a83cc396645d1..cc2d442682496197d29ace79b22e6cf6
ProfilerFiller profilerFiller = Profiler.get();
this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 42995dac38248032b6abecc27124adfe12ec4cab..28a67294c3e678e01d5dfd68b950234213d8e55c 100644
index debc511cf18d0be813803c200bd1cf0b07ba7974..2a4a40976215ea858c562c3f530db378896c6fcb 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1318,6 +1318,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
@@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !(entity instanceof Player player && (this.server.isUnderSpawnProtection(this, pos, player) || !this.getWorldBorder().isWithinBounds(pos)));
}
+ // Paper start - Incremental chunk and player saving
@@ -83,10 +83,10 @@ index 42995dac38248032b6abecc27124adfe12ec4cab..28a67294c3e678e01d5dfd68b9502342
// Paper start - add close param
this.save(progress, flush, skipSave, false);
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index f44600604a7bf68c990cd74a1ac2d7900ff6e88e..69b8074e18775c846d5991f40bc2e0a5186500ac 100644
index bc901bc689c2690ac19e590bff1ae612b7071ee9..8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -180,6 +180,7 @@ import org.slf4j.Logger;
@@ -189,6 +189,7 @@ import org.slf4j.Logger;
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
private static final Logger LOGGER = LogUtils.getLogger();
@@ -95,10 +95,10 @@ index f44600604a7bf68c990cd74a1ac2d7900ff6e88e..69b8074e18775c846d5991f40bc2e0a5
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4..5a4960fdbd97d830ac79845697eea9372c48a13b 100644
index 72524ff3399a4477dfa3db2f4e79bb14f6519a8b..6e22aedd36add8e39a82248193f324b36dfa27b5 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -482,6 +482,7 @@ public abstract class PlayerList {
@@ -486,6 +486,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
@@ -106,7 +106,7 @@ index 7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4..5a4960fdbd97d830ac79845697eea937
this.playerIo.save(player);
ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) {
@@ -1064,9 +1065,23 @@ public abstract class PlayerList {
@@ -1068,9 +1069,23 @@ public abstract class PlayerList {
}
public void saveAll() {

View File

@@ -980,7 +980,7 @@ index 5c5724f5e3ad640f55aecbc1d8f71d1f59ecdc62..618fc0eb4fe70e46e55f3aa28e8eac1d
public boolean release(BlockPos pos) {
diff --git a/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/net/minecraft/world/entity/ai/village/poi/PoiSection.java
index 39cd1e3d8192d7077d6b7864d33933097cc6b986..b92ba4d194fd3af94c7af5d8e150fc4297c73ab8 100644
index c3bcb494afe464207e805f8c40b03c700059c64a..063fca9686a6a048ba279a49271f4144beeff3b9 100644
--- a/net/minecraft/world/entity/ai/village/poi/PoiSection.java
+++ b/net/minecraft/world/entity/ai/village/poi/PoiSection.java
@@ -26,7 +26,7 @@ import org.slf4j.Logger;
@@ -1011,7 +1011,7 @@ index 778bd73a938c94ecb85ca0f8b686ff4e1baee040..79d4ce7712f16995b0de3be86477fb43
return Optional.empty();
} else {
diff --git a/net/minecraft/world/level/portal/PortalForcer.java b/net/minecraft/world/level/portal/PortalForcer.java
index ada2da62d3a40d67e64f5f8d7299f78b5c6f53cb..90ae71eb8cc7f925eb212f39731d70f3bff5ef0a 100644
index aa31439af40e13006eff0036cef2905ac59390b3..b84d658bb06ab7b51cfc18d7405238554f65d2a5 100644
--- a/net/minecraft/world/level/portal/PortalForcer.java
+++ b/net/minecraft/world/level/portal/PortalForcer.java
@@ -48,13 +48,38 @@ public class PortalForcer {

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Optional per player mob spawns
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index ff6503bf8eb88d1264c3d848a89d0255b4b3ae68..9eed24939fc09f00a9dbce1be2ab9c34d024fd29 100644
index 886340232b58afd59caa6df29e211589a7781070..4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -236,11 +236,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -243,11 +243,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper - rewrite chunk system
}
@@ -43,20 +43,11 @@ index ff6503bf8eb88d1264c3d848a89d0255b4b3ae68..9eed24939fc09f00a9dbce1be2ab9c34
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 87d4291a3944f706a694536da6de0f28c548ab8d..5576bf1d1d70ab7a010653d3207909b5de867e70 100644
index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378eca2cf650b 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -517,7 +517,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
profilerFiller.popPush("shuffleChunks");
// Paper start - chunk tick iteration optimisation
this.shuffleRandom.setSeed(this.level.random.nextLong());
- Util.shuffle(list, this.shuffleRandom);
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
// Paper end - chunk tick iteration optimisation
this.tickChunks(profilerFiller, l, list);
profilerFiller.pop();
@@ -571,9 +571,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private void tickChunks(ProfilerFiller profiler, long timeInhabited, List<LevelChunk> chunks) {
@@ -541,9 +541,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private void tickChunks(ProfilerFiller profiler, long timeInhabited) {
profiler.popPush("naturalSpawnCount");
int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
- NaturalSpawner.SpawnState spawnState = NaturalSpawner.createState(
@@ -77,13 +68,22 @@ index 87d4291a3944f706a694536da6de0f28c548ab8d..5576bf1d1d70ab7a010653d3207909b5
this.lastSpawnState = spawnState;
profiler.popPush("spawnAndTick");
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
@@ -572,7 +581,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
profiler.popPush("shuffleSpawningChunks");
// Paper start - chunk tick iteration optimisation
this.shuffleRandom.setSeed(this.level.random.nextLong());
- Util.shuffle(list, this.shuffleRandom);
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
// Paper end - chunk tick iteration optimisation
profiler.popPush("tickSpawningChunks");
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 02fb30a3adf92de0795aee213caf94a228b01ca0..67f6e40216e0be063a3cfb61427f095f7c74d785 100644
index 8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0..73a450e045eba5dbfc7a4e861e4c614c8f60d6b4 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -375,6 +375,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -403,6 +403,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public boolean queueHealthUpdatePacket;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end - cancellable death event
+ // Paper start - Optional per player mob spawns
+ public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
@@ -93,10 +93,10 @@ index 02fb30a3adf92de0795aee213caf94a228b01ca0..67f6e40216e0be063a3cfb61427f095f
public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection;
public String displayName;
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7efff5a93e03 100644
index 3a864c568cd66a680760bb4df2cb020e323e9a9d..c710e08ab48075ce7854e56826adb8f0364b025b 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -72,6 +72,14 @@ public final class NaturalSpawner {
@@ -66,6 +66,14 @@ public final class NaturalSpawner {
public static NaturalSpawner.SpawnState createState(
int spawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator
) {
@@ -111,7 +111,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
PotentialCalculator potentialCalculator = new PotentialCalculator();
Object2IntOpenHashMap<MobCategory> map = new Object2IntOpenHashMap<>();
@@ -93,11 +101,16 @@ public final class NaturalSpawner {
@@ -87,11 +95,16 @@ public final class NaturalSpawner {
potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge());
}
@@ -129,7 +129,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
});
}
}
@@ -135,7 +148,7 @@ public final class NaturalSpawner {
@@ -129,7 +142,7 @@ public final class NaturalSpawner {
if ((spawnFriendlies || !mobCategory.isFriendly())
&& (spawnEnemies || mobCategory.isFriendly())
&& (spawnPassives || !mobCategory.isPersistent())
@@ -138,7 +138,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
list.add(mobCategory);
// CraftBukkit end
}
@@ -149,8 +162,37 @@ public final class NaturalSpawner {
@@ -143,8 +156,37 @@ public final class NaturalSpawner {
profilerFiller.push("spawner");
for (MobCategory mobCategory : categories) {
@@ -150,8 +150,8 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
+ if (level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ // Copied from getFilteredSpawningCategories
+ int limit = mobCategory.getMaxInstancesPerChunk();
+ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
+ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ org.bukkit.entity.SpawnCategory spawnCategory = org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(mobCategory);
+ if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ limit = level.getWorld().getSpawnLimit(spawnCategory);
+ }
+
@@ -178,7 +178,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
}
}
@@ -170,9 +212,16 @@ public final class NaturalSpawner {
@@ -164,9 +206,16 @@ public final class NaturalSpawner {
public static void spawnCategoryForChunk(
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback
) {
@@ -196,7 +196,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
}
}
@@ -189,6 +238,12 @@ public final class NaturalSpawner {
@@ -183,6 +232,12 @@ public final class NaturalSpawner {
NaturalSpawner.SpawnPredicate filter,
NaturalSpawner.AfterSpawnCallback callback
) {
@@ -209,7 +209,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
StructureManager structureManager = level.structureManager();
ChunkGenerator generator = level.getChunkSource().getGenerator();
int y = pos.getY();
@@ -252,9 +307,14 @@ public final class NaturalSpawner {
@@ -247,9 +302,14 @@ public final class NaturalSpawner {
++i;
++i3;
callback.run(mobForSpawn, chunk);
@@ -225,7 +225,7 @@ index 913ea92ace9d610c25bf28f703a3b227044aea63..ef8bacbbb43a9b80281a313ca43b7eff
return;
}
@@ -565,7 +625,7 @@ public final class NaturalSpawner {
@@ -563,7 +623,7 @@ public final class NaturalSpawner {
this.spawnPotential.addCharge(blockPos, d);
MobCategory category = type.getCategory();
this.mobCategoryCounts.addTo(category, 1);

View File

@@ -6,10 +6,10 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 9eed24939fc09f00a9dbce1be2ab9c34d024fd29..b3f498558614243cf633dcd71e3c49c2c55e6e0f 100644
index 4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957..0d8aefe8c886eaa4c33cbab53b0ad1c016f0531f 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -255,8 +255,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -262,8 +262,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
}
@@ -37,10 +37,10 @@ index 9eed24939fc09f00a9dbce1be2ab9c34d024fd29..b3f498558614243cf633dcd71e3c49c2
// Paper end - Optional per player mob spawns
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 5576bf1d1d70ab7a010653d3207909b5de867e70..6540b2d6a1062d883811ce240c49d30d1925b291 100644
index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d77584d8cc 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -576,7 +576,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -546,7 +546,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
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) {
@@ -60,10 +60,10 @@ index 5576bf1d1d70ab7a010653d3207909b5de867e70..6540b2d6a1062d883811ce240c49d30d
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
} else {
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 67f6e40216e0be063a3cfb61427f095f7c74d785..3de65c4025be91d938a350c884975cb6edc234d3 100644
index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171f73b3d07 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -379,6 +379,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -407,6 +407,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
// Paper end - Optional per player mob spawns
@@ -72,10 +72,10 @@ index 67f6e40216e0be063a3cfb61427f095f7c74d785..3de65c4025be91d938a350c884975cb6
public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection;
public String displayName;
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index ef8bacbbb43a9b80281a313ca43b7efff5a93e03..17ce115e887cbbb06ad02ab7ddb488e27342c0e4 100644
index 17b13baa3465530b11ff918c806c772eb5c39a2c..afd6da5c361e1dcf311a9afe8a7efe2faef2556a 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -285,6 +285,11 @@ public final class NaturalSpawner {
@@ -279,6 +279,11 @@ public final class NaturalSpawner {
// Paper start - PreCreatureSpawnEvent
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(level, category, structureManager, generator, spawnerData, mutableBlockPos, d2);

View File

@@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
+ }
+}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index cc2d442682496197d29ace79b22e6cf6fb7edf5e..ae220a732c78ab076261f20b5a54c71d7fceb407 100644
index ea85cac4a41075efe8525c40755e7ebac6ca9dea..7af29d3dc7b337d74cee5df7cbca35c420643370 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1708,6 +1708,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1706,6 +1706,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
@@ -60,10 +60,10 @@ index cc2d442682496197d29ace79b22e6cf6fb7edf5e..ae220a732c78ab076261f20b5a54c71d
/* Drop global time updates
if (this.tickCount % 20 == 0) {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index b393be76bead3c66ab0bd8a0e6fd9b9ef81d8e28..76f50437396f8f856381d0fbef52953ef7c263f6 100644
index 5329dc9259f30011d277336bfc76da18c15d5d81..8391f51b7dd584dd346bda5dccbee900d4fa9c2d 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -827,10 +827,16 @@ public final class ItemStack implements DataComponentHolder {
@@ -832,10 +832,16 @@ public final class ItemStack implements DataComponentHolder {
}
public ItemStack copy() {
@@ -83,18 +83,18 @@ index b393be76bead3c66ab0bd8a0e6fd9b9ef81d8e28..76f50437396f8f856381d0fbef52953e
return itemStack;
}
diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java
index 2ebdf1ad323bb53dfe9eed319e25856b35a1443c..77618757c0e678532dbab814aceed83f7f1cd892 100644
index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81aa9d34c48 100644
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -26,6 +26,7 @@ import net.minecraft.world.level.block.state.BlockState;
@@ -33,6 +33,7 @@ import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
public abstract class BlockEntity {
+ static boolean ignoreBlockEntityUpdates; // Paper - Perf: Optimize Hoppers
// CraftBukkit start - data containers
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
public org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer;
@@ -196,6 +197,7 @@ public abstract class BlockEntity {
public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer;
@@ -202,6 +203,7 @@ public abstract class BlockEntity {
public void setChanged() {
if (this.level != null) {
@@ -103,10 +103,10 @@ index 2ebdf1ad323bb53dfe9eed319e25856b35a1443c..77618757c0e678532dbab814aceed83f
}
}
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78fa880b4cd 100644
index 9a03934dd4d96184f37b9ff5661eb7bd76150464..15d4f60942c0cc612c1468b4c0fda886867a67cb 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -139,18 +139,56 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -143,18 +143,56 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
@@ -166,7 +166,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
}
if (flag) {
@@ -174,6 +212,206 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -178,6 +216,206 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
return true;
}
@@ -373,7 +373,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
Container attachedContainer = getAttachedContainer(level, pos, blockEntity);
if (attachedContainer == null) {
@@ -183,57 +421,60 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -187,57 +425,60 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (isFullContainer(attachedContainer, opposite)) {
return false;
} else {
@@ -485,7 +485,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
}
}
}
@@ -288,6 +529,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -292,6 +533,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
Container sourceContainer = getSourceContainer(level, hopper, blockPos, blockState);
if (sourceContainer != null) {
Direction direction = Direction.DOWN;
@@ -493,7 +493,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
for (int i : getSlots(sourceContainer, direction)) {
if (tryTakeInItemFromSlot(hopper, sourceContainer, i, direction, level)) { // Spigot
@@ -313,55 +555,58 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -317,55 +559,58 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction, Level level) { // Spigot
ItemStack item = container.getItem(slot);
if (!item.isEmpty() && canTakeItemFromContainer(hopper, container, item, slot, direction)) {
@@ -601,7 +601,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
}
return false;
@@ -370,13 +615,15 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -374,13 +619,15 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public static boolean addItem(Container container, ItemEntity item) {
boolean flag = false;
// CraftBukkit start
@@ -618,7 +618,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
ItemStack itemStack = item.getItem().copy();
ItemStack itemStack1 = addItem(null, container, itemStack, null);
if (itemStack1.isEmpty()) {
@@ -431,7 +678,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -435,7 +682,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
stack = stack.split(destination.getMaxStackSize());
}
// Spigot end
@@ -628,7 +628,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
stack = leftover; // Paper - Make hoppers respect inventory max stack size
flag = true;
} else if (canMergeItems(item, stack)) {
@@ -519,13 +768,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -523,13 +772,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@Nullable
public static Container getContainerAt(Level level, BlockPos pos) {
@@ -650,7 +650,7 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
blockContainer = getEntityContainer(level, x, y, z);
}
@@ -551,14 +806,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -555,14 +810,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@Nullable
private static Container getEntityContainer(Level level, double x, double y, double z) {
@@ -669,10 +669,10 @@ index e58a32593e8b42bfc534d13457240860293dd3f4..5cd1326ad5d046c88b2b3449d610a78f
@Override
diff --git a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
index 73b3ddb120d6b6f89e478960e78bed415baea205..f9c31da81d84033abfc1179fc643bceffe35da17 100644
index 1c98d003907feb16de8f26377fceedf728afe7fb..eed5f8f912544b79c8ed54dcdc5eeacb6dcfaccd 100644
--- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@@ -53,7 +53,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@@ -54,7 +54,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@Override
public ItemStack getItem(int index) {

View File

@@ -6,27 +6,27 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e9876667fd1807 100644
index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062b48d43fa 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -563,7 +563,7 @@ public class ServerGamePacketListenerImpl
@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl
return;
}
- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
+ AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet
+ final AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet
d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -573,6 +573,7 @@ public class ServerGamePacketListenerImpl
@@ -565,6 +565,7 @@ public class ServerGamePacketListenerImpl
}
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
+ boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
double verticalDelta = d4; // Paper - Decompile fix, was named d11 previously, is now gone in the source
+ final boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost
d3 = d - rootVehicle.getX();
d4 = d1 - rootVehicle.getY();
@@ -584,14 +585,22 @@ public class ServerGamePacketListenerImpl
@@ -576,14 +577,22 @@ public class ServerGamePacketListenerImpl
d7 = d3 * d3 + d4 * d4 + d5 * d5;
boolean flag2 = false;
if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
@@ -35,24 +35,24 @@ index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e98766
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
}
rootVehicle.absMoveTo(d, d1, d2, f, f1);
this.player.absMoveTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
rootVehicle.absSnapTo(d, d1, d2, f, f1);
this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
- if (flag && (flag2 || !flag3)) {
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = flag2; // violating this is always a fail
+ if (!teleportBack) {
+ // note: only call after setLocation, or else getBoundingBox is wrong
+ AABB newBox = rootVehicle.getBoundingBox();
+ final AABB newBox = rootVehicle.getBoundingBox();
+ if (didCollide || !oldBox.equals(newBox)) {
+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, oldBox, newBox);
+ } // else: no collision at all detected, why do we care?
+ }
+ if (teleportBack) { // Paper end - optimise out extra getCubes
rootVehicle.absMoveTo(x, y, z, f, f1);
this.player.absMoveTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
rootVehicle.absSnapTo(x, y, z, f, f1);
this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
@@ -669,9 +678,32 @@ public class ServerGamePacketListenerImpl
@@ -661,9 +670,32 @@ public class ServerGamePacketListenerImpl
}
private boolean noBlocksAround(Entity entity) {
@@ -60,22 +60,22 @@ index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e98766
- .getBlockStates(entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0))
- .allMatch(BlockBehaviour.BlockStateBase::isAir);
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
+ AABB box = entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0);
+ int minX = Mth.floor(box.minX);
+ int minY = Mth.floor(box.minY);
+ int minZ = Mth.floor(box.minZ);
+ int maxX = Mth.floor(box.maxX);
+ int maxY = Mth.floor(box.maxY);
+ int maxZ = Mth.floor(box.maxZ);
+ final AABB box = entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0);
+ final int minX = Mth.floor(box.minX);
+ final int minY = Mth.floor(box.minY);
+ final int minZ = Mth.floor(box.minZ);
+ final int maxX = Mth.floor(box.maxX);
+ final int maxY = Mth.floor(box.maxY);
+ final int maxZ = Mth.floor(box.maxZ);
+
+ Level level = entity.level();
+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
+ final Level level = entity.level();
+ final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
+
+ for (int y = minY; y <= maxY; ++y) {
+ for (int z = minZ; z <= maxZ; ++z) {
+ for (int x = minX; x <= maxX; ++x) {
+ pos.set(x, y, z);
+ BlockState blockState = level.getBlockStateIfLoaded(pos);
+ final BlockState blockState = level.getBlockStateIfLoaded(pos);
+ if (blockState != null && !blockState.isAir()) {
+ return false;
+ }
@@ -88,43 +88,43 @@ index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e98766
}
@Override
@@ -1371,7 +1403,7 @@ public class ServerGamePacketListenerImpl
@@ -1430,7 +1462,7 @@ public class ServerGamePacketListenerImpl
}
}
}
- AABB boundingBox = this.player.getBoundingBox();
+ AABB boundingBox = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -1410,6 +1442,7 @@ public class ServerGamePacketListenerImpl
boolean flag1 = this.player.verticalCollisionBelow;
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1442,7 +1475,17 @@ public class ServerGamePacketListenerImpl
}
- AABB boundingBox = this.player.getBoundingBox();
+ AABB boundingBox = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -1469,6 +1501,7 @@ public class ServerGamePacketListenerImpl
boolean flag1 = this.player.verticalCollisionBelow;
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
+ final boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1501,7 +1534,17 @@ public class ServerGamePacketListenerImpl
}
// Paper start - Add fail move event
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
+ this.player.absMoveTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
+ AABB newBox = this.player.getBoundingBox();
+ if (didCollide || !boundingBox.equals(newBox)) {
+ // note: only call after setLocation, or else getBoundingBox is wrong
+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
+ } // else: no collision at all detected, why do we care?
+ }
+ // Paper end - optimise out extra getCubes
if (teleportBack) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false);
@@ -1578,7 +1621,7 @@ public class ServerGamePacketListenerImpl
// Paper start - Add fail move event
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
+ this.player.absSnapTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
+ final AABB newBox = this.player.getBoundingBox();
+ if (didCollide || !boundingBox.equals(newBox)) {
+ // note: only call after setLocation, or else getBoundingBox is wrong
+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
+ } // else: no collision at all detected, why do we care?
+ }
+ // Paper end - optimise out extra getCubes
if (teleportBack) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false);
@@ -1638,7 +1681,7 @@ public class ServerGamePacketListenerImpl
private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) {
@@ -133,7 +133,7 @@ index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e98766
this.awaitingTeleportTime = this.tickCount;
this.teleport(
this.awaitingPositionFromClient.x,
@@ -1597,6 +1640,33 @@ public class ServerGamePacketListenerImpl
@@ -1657,6 +1700,33 @@ public class ServerGamePacketListenerImpl
}
}

View File

@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 2 Feb 2025 10:57:48 -0800
Subject: [PATCH] Do not record movement for vehicles/players unaffected by
blocks
If the player is not affected by movement through blocks, then
storing the movement would eventually invoke logic to apply effects
caused by moving through such blocks. For example, moving through
a portal in spectator mode and then later switching to creative mode
would portal the player.
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 90e582ca30851857add5e2d830e9876667fd1807..c569cdfa4cba4f65892ffd4045c611837049f440 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -659,7 +659,7 @@ public class ServerGamePacketListenerImpl
// CraftBukkit end
this.player.serverLevel().getChunkSource().move(this.player);
- rootVehicle.recordMovementThroughBlocks(new Vec3(x, y, z), rootVehicle.position());
+ if (!rootVehicle.isSpectator() && rootVehicle.isAffectedByBlocks()) rootVehicle.recordMovementThroughBlocks(new Vec3(x, y, z), rootVehicle.position()); // Paper - Do not record movement for vehicles/players unaffected by blocks
Vec3 vec3 = new Vec3(rootVehicle.getX() - x, rootVehicle.getY() - y, rootVehicle.getZ() - z);
this.handlePlayerKnownMovement(vec3);
rootVehicle.setOnGroundWithMovement(packet.onGround(), vec3);
@@ -1577,7 +1577,7 @@ public class ServerGamePacketListenerImpl
Vec3 vec3 = new Vec3(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z);
this.player.setOnGroundWithMovement(packet.isOnGround(), packet.horizontalCollision(), vec3);
this.player.doCheckFallDamage(vec3.x, vec3.y, vec3.z, packet.isOnGround());
- this.player.recordMovementThroughBlocks(new Vec3(x, y, z), this.player.position());
+ if (!this.player.isSpectator() && this.player.isAffectedByBlocks()) this.player.recordMovementThroughBlocks(new Vec3(x, y, z), this.player.position()); // Paper - Do not record movement for vehicles/players unaffected by blocks
this.handlePlayerKnownMovement(vec3);
if (flag) {
this.player.resetFallDistance();

View File

@@ -1,6 +1,6 @@
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
@@ -1,0 +_,332 @@
@@ -1,0 +_,330 @@
+package ca.spottedleaf.moonrise.paper.util;
+
+import ca.spottedleaf.concurrentutil.util.Priority;
@@ -28,7 +28,7 @@
+
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final ChunkStep FULL_CHUNK_STEP = ChunkPyramid.GENERATION_PYRAMID.getStepTo(ChunkStatus.FULL);
+ private static final TicketType<Long> CHUNK_LOAD = TicketType.create("chunk_load", Long::compareTo);
+ private static final TicketType CHUNK_LOAD = TicketType.CHUNK_LOAD;
+
+ private long chunkLoadCounter = 0L;
+
@@ -82,11 +82,10 @@
+ }
+
+ final int minLevel = 33 + getDistance(toStatus);
+ final Long chunkReference = addTicket ? Long.valueOf(++this.chunkLoadCounter) : null;
+ final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
+
+ if (addTicket) {
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel);
+ }
+ level.chunkSource.runDistanceManagerUpdates();
+
@@ -100,8 +99,8 @@
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(thr);
+ } finally {
+ if (addTicket) {
+ level.chunkSource.addTicketAtLevel(net.minecraft.server.level.TicketType.UNKNOWN, chunkPos, minLevel, chunkPos);
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
+ level.chunkSource.addTicketAtLevel(net.minecraft.server.level.TicketType.UNKNOWN, chunkPos, minLevel);
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel);
+ }
+ }
+ };
@@ -149,11 +148,10 @@
+
+ final int minLevel = 33 - (toStatus.ordinal() - 1);
+ final int radius = toStatus.ordinal() - 1;
+ final Long chunkReference = addTicket ? Long.valueOf(++this.chunkLoadCounter) : null;
+ final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
+
+ if (addTicket) {
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
+ level.chunkSource.addTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel);
+ }
+ level.chunkSource.runDistanceManagerUpdates();
+
@@ -167,8 +165,8 @@
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(thr);
+ } finally {
+ if (addTicket) {
+ level.chunkSource.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, minLevel, chunkPos);
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel, chunkReference);
+ level.chunkSource.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, minLevel);
+ level.chunkSource.removeTicketAtLevel(CHUNK_LOAD, chunkPos, minLevel);
+ }
+ }
+ };

View File

@@ -1,6 +1,6 @@
--- a/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
+++ b/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java
@@ -44,6 +_,7 @@
@@ -47,6 +_,7 @@
.collect(Collectors.toSet());
final int page = 0;
@@ -8,7 +8,7 @@
for (final List<String> request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) {
final List<String> normalizedRequest = request.stream().map(YggdrasilGameProfileRepository::normalizeName).toList();
@@ -75,6 +_,12 @@
@@ -78,6 +_,12 @@
LOGGER.debug("Couldn't find profile {}", name);
callback.onProfileLookupFailed(name, new ProfileNotFoundException("Server did not find the requested profile"));
}

View File

@@ -1,9 +1,10 @@
--- a/com/mojang/logging/LogUtils.java
+++ b/com/mojang/logging/LogUtils.java
@@ -61,4 +_,9 @@
@@ -61,4 +_,10 @@
public static Logger getLogger() {
return LoggerFactory.getLogger(STACK_WALKER.getCallerClass());
}
+
+ // Paper start
+ public static Logger getClassLogger() {
+ return LoggerFactory.getLogger(STACK_WALKER.getCallerClass().getSimpleName());

View File

@@ -1,28 +1,34 @@
--- a/com/mojang/math/OctahedralGroup.java
+++ b/com/mojang/math/OctahedralGroup.java
@@ -111,6 +_,7 @@
this.permutation = permutation;
this.transformation = new Matrix3f().scaling(invertX ? -1.0F : 1.0F, invertY ? -1.0F : 1.0F, invertZ ? -1.0F : 1.0F);
this.transformation.mul(permutation.transformation());
+ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
}
@@ -123,6 +_,12 @@
}
);
private BooleanList packInversions() {
@@ -139,7 +_,7 @@
+ static {
+ for (OctahedralGroup octahedralGroup : values()) {
+ octahedralGroup.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
+ }
+ }
+
private OctahedralGroup(final String name, final SymmetricGroup3 permutation, final boolean invertX, final boolean invertY, final boolean invertZ) {
this.name = name;
this.invertX = invertX;
@@ -160,7 +_,7 @@
return this.name;
}
- public Direction rotate(Direction direction) {
+ public void initializeRotationDirections() { // Paper - Avoid Lazy Initialization for Enum Fields
if (this.rotatedDirections == null) {
this.rotatedDirections = Maps.newEnumMap(Direction.class);
Direction.Axis[] axiss = Direction.Axis.values();
@@ -154,6 +_,10 @@
}
this.rotatedDirections = Util.makeEnumMap(Direction.class, direction1 -> {
Direction.Axis axis = direction1.getAxis();
@@ -171,6 +_,11 @@
});
}
+ // Paper start - Avoid Lazy Initialization for Enum Fields
+ }
+
+ public Direction rotate(Direction direction) {
+ // Paper end - Avoid Lazy Initialization for Enum Fields
return this.rotatedDirections.get(direction);

View File

@@ -1,6 +1,6 @@
--- /dev/null
+++ b/io/papermc/paper/FeatureHooks.java
@@ -1,0 +_,234 @@
@@ -1,0 +_,238 @@
+package io.papermc.paper;
+
+import io.papermc.paper.command.PaperSubcommand;
@@ -139,16 +139,16 @@
+ public static java.util.Collection<org.bukkit.plugin.Plugin> getPluginChunkTickets(net.minecraft.server.level.ServerLevel world,
+ int x, int z) {
+ net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
+ net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkDistanceManager.tickets.get(ChunkPos.asLong(x, z));
+ List<net.minecraft.server.level.Ticket> tickets = chunkDistanceManager.ticketStorage.tickets.get(ChunkPos.asLong(x, z));
+
+ if (tickets == null) {
+ return java.util.Collections.emptyList();
+ }
+
+ com.google.common.collect.ImmutableList.Builder<org.bukkit.plugin.Plugin> ret = com.google.common.collect.ImmutableList.builder();
+ for (net.minecraft.server.level.Ticket<?> ticket : tickets) {
+ for (net.minecraft.server.level.Ticket ticket : tickets) {
+ if (ticket.getType() == net.minecraft.server.level.TicketType.PLUGIN_TICKET) {
+ ret.add((org.bukkit.plugin.Plugin) ticket.key);
+ ret.add((org.bukkit.plugin.Plugin) ticket.getIdentifier());
+ }
+ }
+
@@ -159,12 +159,12 @@
+ Map<org.bukkit.plugin.Plugin, com.google.common.collect.ImmutableList.Builder<Chunk>> ret = new HashMap<>();
+ net.minecraft.server.level.DistanceManager chunkDistanceManager = world.getChunkSource().chunkMap.distanceManager;
+
+ for (it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry<net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>>> chunkTickets : chunkDistanceManager.tickets.long2ObjectEntrySet()) {
+ for (it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry<List<net.minecraft.server.level.Ticket>> chunkTickets : chunkDistanceManager.ticketStorage.tickets.long2ObjectEntrySet()) {
+ long chunkKey = chunkTickets.getLongKey();
+ net.minecraft.util.SortedArraySet<net.minecraft.server.level.Ticket<?>> tickets = chunkTickets.getValue();
+ List<net.minecraft.server.level.Ticket> tickets = chunkTickets.getValue();
+
+ org.bukkit.Chunk chunk = null;
+ for (net.minecraft.server.level.Ticket<?> ticket : tickets) {
+ for (net.minecraft.server.level.Ticket ticket : tickets) {
+ if (ticket.getType() != net.minecraft.server.level.TicketType.PLUGIN_TICKET) {
+ continue;
+ }
@@ -173,7 +173,7 @@
+ chunk = world.getWorld().getChunkAt(ChunkPos.getX(chunkKey), ChunkPos.getZ(chunkKey));
+ }
+
+ ret.computeIfAbsent((org.bukkit.plugin.Plugin) ticket.key, (key) -> com.google.common.collect.ImmutableList.builder()).add(chunk);
+ ret.computeIfAbsent((org.bukkit.plugin.Plugin) ticket.getIdentifier(), (key) -> com.google.common.collect.ImmutableList.builder()).add(chunk);
+ }
+ }
+
@@ -215,7 +215,11 @@
+ }
+
+ public static void closeEntityManager(net.minecraft.server.level.ServerLevel world, boolean save) {
+ world.entityManager.close(save);
+ try {
+ world.entityManager.close(save);
+ } catch (final java.io.IOException exception) {
+ throw new RuntimeException("Failed to close entity manager", exception);
+ }
+ }
+
+ public static java.util.concurrent.Executor getWorldgenExecutor() {

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/ChatFormatting.java
+++ b/net/minecraft/ChatFormatting.java
@@ -112,6 +_,19 @@
@@ -118,6 +_,19 @@
return friendlyName == null ? null : FORMATTING_BY_NAME.get(cleanName(friendlyName));
}
+ // Paper start - add method to get by hex value
+ @Nullable
+ public static ChatFormatting getByHexValue(int i) {
+ public static ChatFormatting getByHexValue(int color) {
+ for (ChatFormatting value : values()) {
+ if (value.getColor() != null && value.getColor() == i) {
+ if (value.getColor() != null && value.getColor() == color) {
+ return value;
+ }
+ }

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/Util.java
+++ b/net/minecraft/Util.java
@@ -92,9 +_,26 @@
@@ -93,9 +_,26 @@
private static final int DEFAULT_MAX_THREADS = 255;
private static final int DEFAULT_SAFE_FILE_OPERATION_RETRIES = 10;
private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
@@ -28,7 +28,7 @@
private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
public static final int LINEAR_LOOKUP_THRESHOLD = 8;
private static final Set<String> ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https");
@@ -113,6 +_,7 @@
@@ -114,6 +_,7 @@
.findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
private static Consumer<String> thePauser = string -> {};
@@ -36,7 +36,7 @@
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Entry::getKey, Entry::getValue);
@@ -135,7 +_,7 @@
@@ -136,7 +_,7 @@
}
public static long getNanos() {
@@ -45,7 +45,7 @@
}
public static long getEpochMillis() {
@@ -146,9 +_,10 @@
@@ -147,9 +_,10 @@
return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
}
@@ -58,7 +58,7 @@
if (i <= 0) {
directExecutorService = MoreExecutors.newDirectExecutorService();
} else {
@@ -173,16 +_,30 @@
@@ -174,16 +_,30 @@
super.onTermination(throwOnTermination);
}
};
@@ -91,7 +91,7 @@
}
private static int getMaxThreads() {
@@ -233,6 +_,21 @@
@@ -234,6 +_,21 @@
}));
}
@@ -113,7 +113,7 @@
public static void throwAsRuntime(Throwable throwable) {
throw throwable instanceof RuntimeException ? (RuntimeException)throwable : new RuntimeException(throwable);
}
@@ -1075,16 +_,7 @@
@@ -1088,16 +_,7 @@
}
public void openUri(URI uri) {

View File

@@ -18,11 +18,10 @@
public CommandSourceStack(
CommandSource source,
@@ -187,6 +_,30 @@
this.chatMessageChainer
@@ -188,6 +_,30 @@
);
}
+
+ // Paper start - Expose 'with' functions from the CommandSourceStack
+ @Override
+ public CommandSourceStack withLocation(org.bukkit.Location location) {
@@ -46,9 +45,10 @@
+ );
+ }
+ // Paper end - Expose 'with' functions from the CommandSourceStack
+
public CommandSourceStack withRotation(Vec2 rotation) {
return this.rotation.equals(rotation)
? this
@@ -391,9 +_,44 @@
@Override
@@ -94,7 +94,7 @@
public Vec3 getPosition() {
return this.worldPosition;
}
@@ -499,20 +_,25 @@
@@ -498,20 +_,25 @@
Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC);
if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) {
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -123,7 +123,7 @@
}
}
@@ -523,7 +_,7 @@
@@ -522,7 +_,7 @@
@Override
public Collection<String> getOnlinePlayerNames() {
@@ -132,7 +132,7 @@
}
@Override
@@ -598,4 +_,16 @@
@@ -597,4 +_,16 @@
public boolean isSilent() {
return this.silent;
}

View File

@@ -127,7 +127,7 @@
StackTraceElement[] stackTrace = var12.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
@@ -309,18 +_,22 @@
@@ -308,18 +_,22 @@
}
@Nullable
@@ -148,12 +148,12 @@
int min = Math.min(var7.getInput().length(), var7.getCursor());
MutableComponent mutableComponent = Component.empty()
.withStyle(ChatFormatting.GRAY)
- .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command)));
+ .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + label))); // CraftBukkit // Paper
- .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + command)));
+ .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + label))); // CraftBukkit // Paper
if (min > 10) {
mutableComponent.append(CommonComponents.ELLIPSIS);
}
@@ -332,7 +_,17 @@
@@ -331,7 +_,17 @@
}
mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
@@ -172,7 +172,7 @@
}
return null;
@@ -360,26 +_,120 @@
@@ -359,26 +_,120 @@
}
public void sendCommands(ServerPlayer player) {
@@ -297,9 +297,9 @@
+ // we want the exact command instance to be used for equality checks
+ // when assigning serialization ids to each command node
if (argumentBuilder instanceof RequiredArgumentBuilder) {
RequiredArgumentBuilder<SharedSuggestionProvider, ?> requiredArgumentBuilder = (RequiredArgumentBuilder<SharedSuggestionProvider, ?>)argumentBuilder;
@@ -396,7 +_,7 @@
if (argumentBuilder instanceof RequiredArgumentBuilder requiredArgumentBuilder
&& requiredArgumentBuilder.getSuggestionsProvider() != null) {
@@ -393,7 +_,7 @@
commandNodeToSuggestionNode.put(commandNode, commandNode1);
rootSuggestion.addChild(commandNode1);
if (!commandNode.getChildren().isEmpty()) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/Direction.java
+++ b/net/minecraft/core/Direction.java
@@ -57,6 +_,12 @@
@@ -62,6 +_,12 @@
.sorted(Comparator.comparingInt(direction -> direction.data2d))
.toArray(Direction[]::new);
@@ -13,10 +13,10 @@
private Direction(
final int data3d,
final int oppositeIndex,
@@ -74,6 +_,11 @@
this.axisDirection = axisDirection;
@@ -80,6 +_,11 @@
this.normal = normal;
this.normalVec3 = Vec3.atLowerCornerOf(normal);
this.normalVec3f = new Vector3f(normal.getX(), normal.getY(), normal.getZ());
+ // Paper start - Perf: Inline shift direction fields
+ this.adjX = normal.getX();
+ this.adjY = normal.getY();
@@ -25,7 +25,7 @@
}
public static Direction[] orderedByNearest(Entity entity) {
@@ -247,15 +_,15 @@
@@ -252,15 +_,15 @@
}
public int getStepX() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java
@@ -33,17 +_,18 @@
@@ -32,17 +_,18 @@
public class MappedRegistry<T> implements WritableRegistry<T> {
private final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
@@ -24,7 +24,7 @@
@Override
public Stream<HolderSet.Named<T>> listTags() {
@@ -114,6 +_,7 @@
@@ -113,6 +_,7 @@
this.toId.put(value, size);
this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
@@ -32,7 +32,7 @@
return reference;
}
}
@@ -275,6 +_,7 @@
@@ -274,6 +_,7 @@
return this;
} else {
this.frozen = true;
@@ -40,7 +40,7 @@
this.byValue.forEach((object, reference) -> reference.bindValue((T)object));
List<ResourceLocation> list = this.byKey
.entrySet()
@@ -509,4 +_,13 @@
@@ -508,4 +_,13 @@
Stream<HolderSet.Named<T>> getTags();
}

View File

@@ -1,21 +1,25 @@
--- a/net/minecraft/core/Rotations.java
+++ b/net/minecraft/core/Rotations.java
@@ -34,6 +_,18 @@
this(tag.getFloat(0), tag.getFloat(1), tag.getFloat(2));
}
+ // Paper start - faster alternative constructor
+ private Rotations(float x, float y, float z, Void dummy_var) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
@@ -26,11 +_,22 @@
buffer.writeFloat(value.z);
}
};
+ // Paper start - add internal method for skipping validation for plugins
+ private static boolean SKIP_VALIDATION = false;
+ public static Rotations createWithoutValidityChecks(float x, float y, float z) {
+ return new Rotations(x, y, z, null);
+ SKIP_VALIDATION = true;
+ Rotations rotations = new Rotations(x, y, z);
+ SKIP_VALIDATION = false;
+ return rotations;
+ }
+ // Paper end - faster alternative constructor
+
public ListTag save() {
ListTag listTag = new ListTag();
listTag.add(FloatTag.valueOf(this.x));
+ // Paper end - add internal method for skipping validation for plugins
public Rotations(float x, float y, float z) {
+ if (SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins
x = !Float.isInfinite(x) && !Float.isNaN(x) ? x % 360.0F : 0.0F;
y = !Float.isInfinite(y) && !Float.isNaN(y) ? y % 360.0F : 0.0F;
z = !Float.isInfinite(z) && !Float.isNaN(z) ? z % 360.0F : 0.0F;
+ } // Paper - add internal method for skipping validation for plugins
this.x = x;
this.y = y;
this.z = z;

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/core/Vec3i.java
+++ b/net/minecraft/core/Vec3i.java
@@ -16,9 +_,9 @@
vec3i -> IntStream.of(vec3i.getX(), vec3i.getY(), vec3i.getZ())
);
@@ -22,9 +_,9 @@
ByteBufCodecs.VAR_INT, Vec3i::getX, ByteBufCodecs.VAR_INT, Vec3i::getY, ByteBufCodecs.VAR_INT, Vec3i::getZ, Vec3i::new
);
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
- private int x;
- private int y;
@@ -13,7 +13,7 @@
public static Codec<Vec3i> offsetCodec(int maxOffset) {
return CODEC.validate(
@@ -35,12 +_,12 @@
@@ -41,12 +_,12 @@
}
@Override
@@ -28,7 +28,7 @@
return (this.getY() + this.getZ() * 31) * 31 + this.getX();
}
@@ -53,15 +_,15 @@
@@ -59,15 +_,15 @@
}
}
@@ -47,7 +47,7 @@
return this.z;
}
@@ -235,4 +_,10 @@
@@ -241,4 +_,10 @@
public String toShortString() {
return this.getX() + ", " + this.getY() + ", " + this.getZ();
}

View File

@@ -122,13 +122,14 @@
)
);
addDefaultInteractions(map3);
@@ -202,15 +_,34 @@
@@ -202,15 +_,35 @@
Predicate<BlockState> statePredicate,
SoundEvent fillSound
) {
+ // Paper start - add hitDirection
+ return fillBucket(state, level, pos, player, hand, emptyStack, filledStack, statePredicate, fillSound, null); // Paper - add hitDirection
+ }
+
+ static InteractionResult fillBucket(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack emptyStack, ItemStack filledStack, Predicate<BlockState> statePredicate, SoundEvent fillSound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
+ // Paper end - add hitDirection
if (!statePredicate.test(state)) {
@@ -137,7 +138,7 @@
if (!level.isClientSide) {
+ // Paper start - fire PlayerBucketFillEvent
+ if (hitDirection != null) {
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
@@ -158,20 +159,21 @@
level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
}
@@ -222,12 +_,32 @@
@@ -222,12 +_,33 @@
static InteractionResult emptyBucket(
Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound
) {
+ // Paper start - add hitDirection
+ return emptyBucket(level, pos, player, hand, filledStackl, state, emptySound, null);
+ }
+
+ static InteractionResult emptyBucket(Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
+ // Paper end - add hitDirection
if (!level.isClientSide) {
+ // Paper start - fire PlayerBucketEmptyEvent
+ ItemStack output = new ItemStack(Items.BUCKET);
+ if (hitDirection != null) {
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, filledStackl, hand);
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent(level, player, pos, pos, hitDirection, filledStackl, hand);
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
@@ -193,7 +195,7 @@
level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
}
@@ -236,7 +_,7 @@
@@ -236,23 +_,23 @@
}
private static InteractionResult fillWaterInteraction(
@@ -201,13 +203,8 @@
+ BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack, final net.minecraft.core.Direction hitDirection // Paper - add hitDirection
) {
return emptyBucket(
level,
@@ -245,20 +_,20 @@
hand,
filledStack,
Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
- SoundEvents.BUCKET_EMPTY
+ SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
- level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY
+ level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
);
}
@@ -227,10 +224,10 @@
) {
return (InteractionResult)(isUnderWater(level, pos)
? InteractionResult.CONSUME
@@ -269,53 +_,68 @@
@@ -263,53 +_,68 @@
hand,
filledStack,
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3),
- SoundEvents.BUCKET_EMPTY_POWDER_SNOW
+ SoundEvents.BUCKET_EMPTY_POWDER_SNOW, hitDirection // Paper - add hitDirection
));

View File

@@ -1,50 +1,50 @@
--- a/net/minecraft/core/component/DataComponentPatch.java
+++ b/net/minecraft/core/component/DataComponentPatch.java
@@ -86,6 +_,11 @@
buffer.writeVarInt(0);
buffer.writeVarInt(0);
} else {
+ // Paper start - data sanitization for items
+ final io.papermc.paper.util.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
+ : io.papermc.paper.util.ItemObfuscationSession.currentSession();
+ // Paper end - data sanitization for items
int i = 0;
int i1 = 0;
@@ -106,6 +_,11 @@
buffer.writeVarInt(0);
buffer.writeVarInt(0);
} else {
+ // Paper start - data sanitization for items
+ final io.papermc.paper.util.sanitizer.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
+ : io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession();
+ // Paper end - data sanitization for items
int i = 0;
int i1 = 0;
@@ -93,7 +_,7 @@
value.map
)) {
if (entry.getValue().isPresent()) {
- i++;
+ if (!io.papermc.paper.util.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
} else {
i1++;
}
@@ -106,6 +_,7 @@
value.map
)) {
Optional<?> optional = entryx.getValue();
+ optional = io.papermc.paper.util.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
if (optional.isPresent()) {
DataComponentType<?> dataComponentType = entryx.getKey();
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
@@ -125,7 +_,13 @@
}
@@ -113,7 +_,7 @@
value.map
)) {
if (entry.getValue().isPresent()) {
- i++;
+ if (!io.papermc.paper.util.sanitizer.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
} else {
i1++;
}
@@ -126,6 +_,7 @@
value.map
)) {
Optional<?> optional = entryx.getValue();
+ optional = io.papermc.paper.util.sanitizer.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
if (optional.isPresent()) {
DataComponentType<?> dataComponentType = entryx.getKey();
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
@@ -145,7 +_,13 @@
}
private static <T> void encodeComponent(RegistryFriendlyByteBuf buffer, DataComponentType<T> component, Object value) {
- component.streamCodec().encode(buffer, (T)value);
+ // Paper start - codec errors of random anonymous classes are useless
+ try {
+ component.streamCodec().encode(buffer, (T)value);
+ } catch (final Exception e) {
+ throw new RuntimeException("Error encoding component " + component, e);
+ }
+ // Paper end - codec errors of random anonymous classes are useless
}
};
private static final String REMOVED_PREFIX = "!";
@@ -230,6 +_,42 @@
private <T> void encodeComponent(RegistryFriendlyByteBuf buffer, DataComponentType<T> component, Object value) {
- codecGetter.apply(component).encode(buffer, (T)value);
+ // Paper start - codec errors of random anonymous classes are useless
+ try {
+ codecGetter.apply(component).encode(buffer, (T)value);
+ } catch (final Exception e) {
+ throw new RuntimeException("Error encoding component " + component, e);
+ }
+ // Paper end - codec errors of random anonymous classes are useless
}
};
}
@@ -249,6 +_,42 @@
Builder() {
}

View File

@@ -1,24 +1,24 @@
--- a/net/minecraft/core/component/DataComponents.java
+++ b/net/minecraft/core/component/DataComponents.java
@@ -180,10 +_,10 @@
@@ -203,10 +_,10 @@
"map_post_processing", builder -> builder.networkSynchronized(MapPostProcessing.STREAM_CODEC)
);
public static final DataComponentType<ChargedProjectiles> CHARGED_PROJECTILES = register(
- "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(ChargedProjectiles.STREAM_CODEC).cacheEncoding()
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
);
public static final DataComponentType<BundleContents> BUNDLE_CONTENTS = register(
- "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(BundleContents.STREAM_CODEC).cacheEncoding()
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
);
public static final DataComponentType<PotionContents> POTION_CONTENTS = register(
"potion_contents", builder -> builder.persistent(PotionContents.CODEC).networkSynchronized(PotionContents.STREAM_CODEC).cacheEncoding()
@@ -250,7 +_,7 @@
@@ -286,7 +_,7 @@
"pot_decorations", builder -> builder.persistent(PotDecorations.CODEC).networkSynchronized(PotDecorations.STREAM_CODEC).cacheEncoding()
);
public static final DataComponentType<ItemContainerContents> CONTAINER = register(
- "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(ItemContainerContents.STREAM_CODEC).cacheEncoding()
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.CONTAINER).cacheEncoding() // Paper - sanitize container contents
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.CONTAINER).cacheEncoding() // Paper - sanitize container contents
);
public static final DataComponentType<BlockItemStateProperties> BLOCK_STATE = register(
"block_state", builder -> builder.persistent(BlockItemStateProperties.CODEC).networkSynchronized(BlockItemStateProperties.STREAM_CODEC).cacheEncoding()

View File

@@ -1,30 +1,27 @@
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
@@ -40,13 +_,39 @@
@@ -40,13 +_,36 @@
d4 = 0.0;
}
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
+ ItemStack singleItemStack = item.copyWithCount(1);
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;

View File

@@ -1,20 +1,11 @@
--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
@@ -10,23 +_,46 @@
@@ -9,24 +_,37 @@
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
private static final int DEFAULT_ACCURACY = 6;
+ // CraftBukkit start
+ private Direction direction; // Paper - cache facing direction
+ private boolean dropper;
+
+ public DefaultDispenseItemBehavior(boolean dropper) {
+ this.dropper = dropper;
+ }
+
+ public DefaultDispenseItemBehavior() {}
+ // CraftBukkit end
+
@Override
public final ItemStack dispense(BlockSource blockSource, ItemStack item) {
+ this.direction = blockSource.state().getValue(DispenserBlock.FACING); // Paper - cache facing direction
@@ -32,7 +23,7 @@
ItemStack itemStack = item.split(1);
- spawnItem(blockSource.level(), itemStack, 6, direction, dispensePosition);
+ // CraftBukkit start
+ if (!DefaultDispenseItemBehavior.spawnItem(blockSource.level(), itemStack, 6, this.direction, dispensePosition, blockSource, this.dropper)) {
+ if (!DefaultDispenseItemBehavior.spawnItem(blockSource.level(), itemStack, 6, this.direction, dispensePosition, blockSource)) {
+ item.grow(1);
+ }
+ // CraftBukkit end
@@ -50,37 +41,35 @@
double d = position.x();
double d1 = position.y();
double d2 = position.z();
@@ -43,7 +_,45 @@
@@ -43,7 +_,43 @@
level.random.triangle(0.2, 0.0172275 * speed),
level.random.triangle(facing.getStepZ() * d3, 0.0172275 * speed)
);
+ return itemEntity; // CraftBukkit
+ }
+
+ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper
+ public static boolean spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position dispensePosition, BlockSource blockSource, boolean dropper) {
+ // CraftBukkit start - void -> boolean return
+ public static boolean spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position position, BlockSource blockSource) {
+ if (stack.isEmpty()) return true;
+ ItemEntity itemEntity = DefaultDispenseItemBehavior.prepareItem(level, stack, speed, facing, dispensePosition);
+ ItemEntity itemEntity = DefaultDispenseItemBehavior.prepareItem(level, stack, speed, facing, position);
+
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(itemEntity.getDeltaMovement()));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ }
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ itemEntity.setItem(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
+ itemEntity.setDeltaMovement(org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getVelocity()));
+ itemEntity.setDeltaMovement(org.bukkit.craftbukkit.util.CraftVector.toVec3(event.getVelocity()));
+
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
+ if (blockSource.state().is(net.minecraft.world.level.block.Blocks.DISPENSER) && !event.getItem().getType().equals(craftItem.getType())) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior.getClass() != DefaultDispenseItemBehavior.class) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ } else {

View File

@@ -1,31 +1,28 @@
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -82,16 +_,48 @@
@@ -83,16 +_,45 @@
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
EntityType<?> type = ((SpawnEggItem)item.getItem()).getType(blockSource.level().registryAccess(), item);
+ // CraftBukkit start
+ ServerLevel serverLevel = blockSource.level();
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
+ ItemStack singleItemStack = item.copyWithCount(1);
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
@@ -46,42 +43,40 @@
}
- item.shrink(1);
+ if (shrink) item.shrink(1); // Paper - actually handle here
+ if (shrink) item.shrink(1);
+ // CraftBukkit end
blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos());
return item;
}
@@ -109,12 +_,40 @@
@@ -110,12 +_,38 @@
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
ServerLevel serverLevel = blockSource.level();
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
+ ItemStack singleItemStack = item.copyWithCount(1);
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ // CraftBukkit end
+
+ final ItemStack newStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()); // Paper - use event itemstack (unwrap is fine here because the stack won't be modified)
Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig(
- armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, item, null
@@ -90,76 +85,37 @@
ArmorStand armorStand = EntityType.ARMOR_STAND.spawn(serverLevel, consumer, blockPos, EntitySpawnReason.DISPENSER, false, false);
if (armorStand != null) {
- item.shrink(1);
+ if (shrink) item.shrink(1); // Paper - actually handle here
+ if (shrink) item.shrink(1); // Paper
}
return item;
@@ -134,7 +_,36 @@
livingEntity -> livingEntity instanceof Saddleable saddleable && !saddleable.isSaddled() && saddleable.isSaddleable()
);
if (!entitiesOfClass.isEmpty()) {
- ((Saddleable)entitiesOfClass.get(0)).equipSaddle(item.split(1), SoundSource.BLOCKS);
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
+ ServerLevel world = blockSource.level();
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
+ if (!DispenserBlock.eventFired) {
+ world.getCraftServer().getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ ((Saddleable) entitiesOfClass.get(0)).equipSaddle(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event
+ // CraftBukkit end
+ if (shrink) item.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return item;
} else {
@@ -156,8 +_,36 @@
@@ -135,8 +_,35 @@
new AABB(blockPos),
abstractChestedHorse1 -> abstractChestedHorse1.isAlive() && !abstractChestedHorse1.hasChest()
)) {
- if (abstractChestedHorse.isTamed() && abstractChestedHorse.getSlot(499).set(item)) {
- item.shrink(1);
+ if (abstractChestedHorse.isTamed()/* && abstractChestedHorse.getSlot(499).set(item)*/) {
+ ItemStack singleCopy = item.copyWithCount(1); // Paper - shrink below
+ // CraftBukkit start
+ ItemStack singleCopy = item.copyWithCount(1);
+ ServerLevel world = blockSource.level();
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleCopy);
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), abstractChestedHorse.getBukkitLivingEntity());
+ if (!DispenserBlock.eventFired) {
+ world.getCraftServer().getPluginManager().callEvent(event);
+ }
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below (this was actually missing and should be here, added it commented out to be consistent)
+ this.setSuccess(false);
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
@@ -171,30 +127,25 @@
this.setSuccess(true);
return item;
}
@@ -195,8 +_,50 @@
@@ -174,8 +_,45 @@
DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)item.getItem();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
Level level = blockSource.level();
+ // CraftBukkit start
+ int x = blockPos.getX();
+ int y = blockPos.getY();
+ int z = blockPos.getZ();
+ BlockState iblockdata = level.getBlockState(blockPos);
+ BlockState state = level.getBlockState(blockPos);
+ ItemStack dispensedItem = item; // Paper - track changed item from the dispense event
+ // Paper start - correctly check if the bucket place will succeed
+ /* Taken from SolidBucketItem#emptyContents */
+ boolean willEmptyContentsSolidBucketItem = dispensibleContainerItem instanceof net.minecraft.world.item.SolidBucketItem && level.isInWorldBounds(blockPos) && iblockdata.isAir();
+ boolean willEmptyContentsSolidBucketItem = dispensibleContainerItem instanceof net.minecraft.world.item.SolidBucketItem && level.isInWorldBounds(blockPos) && state.isAir();
+ /* Taken from BucketItem#emptyContents */
+ boolean willEmptyBucketItem = dispensibleContainerItem instanceof final net.minecraft.world.item.BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (iblockdata.isAir() || iblockdata.canBeReplaced(bucketItem.content) || (iblockdata.getBlock() instanceof net.minecraft.world.level.block.LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, level, blockPos, iblockdata, bucketItem.content)));
+ boolean willEmptyBucketItem = dispensibleContainerItem instanceof final net.minecraft.world.item.BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (state.isAir() || state.canBeReplaced(bucketItem.content) || (state.getBlock() instanceof net.minecraft.world.level.block.LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, level, blockPos, state, bucketItem.content)));
+ if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) {
+ // Paper end - correctly check if the bucket place will succeed
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return item;
@@ -203,7 +154,7 @@
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
@@ -223,7 +174,7 @@
return this.consumeWithRemainder(blockSource, item, new ItemStack(Items.BUCKET));
} else {
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
@@ -219,12 +_,37 @@
@@ -198,12 +_,19 @@
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
BlockState blockState = levelAccessor.getBlockState(blockPos);
if (blockState.getBlock() instanceof BucketPickup bucketPickup) {
@@ -234,64 +185,27 @@
} else {
levelAccessor.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos);
Item item1 = itemStack.getItem();
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ if (!DispenserBlock.eventFired) {
+ levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ return result;
+ }
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); // From above
+ // CraftBukkit end
+ // Paper end - Call BlockDispenseEvent
+ itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); // CraftBukkit - from above
return this.consumeWithRemainder(blockSource, item, new ItemStack(item1));
}
} else {
@@ -236,17 +_,44 @@
@Override
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
ServerLevel serverLevel = blockSource.level();
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ // CraftBukkit end
@@ -218,15 +_,26 @@
this.setSuccess(true);
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call BlockDispenseEvent
BlockState blockState = serverLevel.getBlockState(blockPos);
if (BaseFireBlock.canBePlacedAt(serverLevel, blockPos, direction)) {
- serverLevel.setBlockAndUpdate(blockPos, BaseFireBlock.getState(serverLevel, blockPos));
@@ -303,42 +217,26 @@
+ }
+ // CraftBukkit end
} else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) {
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, true));
serverLevel.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos);
- } else if (blockState.getBlock() instanceof TntBlock) {
+ } else if (blockState.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos())) { // CraftBukkit - TNTPrimeEvent
TntBlock.explode(serverLevel, blockPos);
serverLevel.removeBlock(blockPos, false);
} else {
@@ -266,11 +_,62 @@
} else if (blockState.getBlock() instanceof TntBlock) {
- if (TntBlock.prime(serverLevel, blockPos)) {
+ if (TntBlock.prime(serverLevel, blockPos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos()))) { // CraftBukkit - TNTPrimeEvent
serverLevel.removeBlock(blockPos, false);
} else {
this.setSuccess(false);
@@ -248,11 +_,46 @@
this.setSuccess(true);
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
+ // CraftBukkit start
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ level.captureTreeGeneration = true;
+ // CraftBukkit end
+ // Paper end - Call BlockDispenseEvent
+ level.captureTreeGeneration = true; // CraftBukkit
if (!BoneMealItem.growCrop(item, level, blockPos) && !BoneMealItem.growWaterPlant(item, level, blockPos, null)) {
this.setSuccess(false);
} else if (!level.isClientSide) {
@@ -346,26 +244,27 @@
}
+ // CraftBukkit start
+ level.captureTreeGeneration = false;
+ if (level.capturedBlockStates.size() > 0) {
+ if (!level.capturedBlockStates.isEmpty()) {
+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType;
+ net.minecraft.world.level.block.SaplingBlock.treeType = null;
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos, level.getWorld());
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(level.capturedBlockStates.values());
+ List<org.bukkit.block.BlockState> states = new java.util.ArrayList<>(level.capturedBlockStates.values());
+ level.capturedBlockStates.clear();
+ org.bukkit.event.world.StructureGrowEvent structureEvent = null;
+ if (treeType != null) {
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, blocks);
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, states);
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
+ }
+
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(location.getBlock(), null, blocks);
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(location.getBlock(), null, states);
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
+
+ if (!fertilizeEvent.isCancelled()) {
+ for (org.bukkit.block.BlockState blockstate : blocks) {
+ blockstate.update(true);
+ blockSource.level().checkCapturedTreeStateForObserverNotify(blockPos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
+ for (org.bukkit.block.BlockState state : states) {
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) state;
+ craftBlockState.place(craftBlockState.getFlags());
+ blockSource.level().checkCapturedTreeStateForObserverNotify(blockPos, craftBlockState); // Paper - notify observers even if grow failed
+ }
+ }
+ }
@@ -373,79 +272,61 @@
return item;
}
@@ -280,11 +_,39 @@
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
- PrimedTnt primedTnt = new PrimedTnt(level, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
+ // CraftBukkit start
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ PrimedTnt primedTnt = new PrimedTnt(level, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
+ // CraftBukkit end
level.addFreshEntity(primedTnt);
level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
- item.shrink(1);
+ if (shrink) item.shrink(1); // Paper - actually handle here
return item;
}
});
@@ -296,6 +_,29 @@
Level level = blockSource.level();
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
@@ -266,11 +_,36 @@
return item;
} else {
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
- PrimedTnt primedTnt = new PrimedTnt(serverLevel, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ PrimedTnt primedTnt = new PrimedTnt(serverLevel, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
+ // CraftBukkit end
serverLevel.addFreshEntity(primedTnt);
serverLevel.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
- serverLevel.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
- item.shrink(1);
+ serverLevel.gameEvent(null, GameEvent.ENTITY_PLACE, org.bukkit.craftbukkit.util.CraftVector.toBlockPos(event.getVelocity())); // Paper - update game event position
+ if (shrink) item.shrink(1); // Paper
this.setSuccess(true);
return item;
}
@@ -284,6 +_,13 @@
Level level = blockSource.level();
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
BlockPos blockPos = blockSource.pos().relative(direction);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call BlockDispenseEvent
if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, item)) {
level.setBlock(
blockPos,
@@ -313,7 +_,7 @@
@@ -299,7 +_,7 @@
item.shrink(1);
this.setSuccess(true);
} else {
@@ -454,37 +335,21 @@
}
return item;
@@ -326,6 +_,29 @@
@@ -312,6 +_,13 @@
Level level = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN;
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ if (!DispenserBlock.eventFired) {
+ level.getCraftServer().getPluginManager().callEvent(event);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ // CraftBukkit end
+ // Paper end - Call BlockDispenseEvent
if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) {
if (!level.isClientSide) {
level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3);
@@ -335,7 +_,7 @@
@@ -321,7 +_,7 @@
item.shrink(1);
this.setSuccess(true);
} else {
@@ -493,51 +358,34 @@
}
return item;
@@ -361,6 +_,29 @@
@@ -347,6 +_,12 @@
ServerLevel serverLevel = blockSource.level();
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
BlockState blockState = serverLevel.getBlockState(blockPos);
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - only single item in event
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ return result;
+ }
+
+ if (event.isCancelled()) {
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+ // CraftBukkit end
+ // Paper end - Call BlockDispenseEvent
if (blockState.is(
BlockTags.BEEHIVES,
blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock
@@ -389,6 +_,13 @@
@@ -375,6 +_,13 @@
this.setSuccess(true);
if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) {
+ // Paper start - Call missing BlockDispenseEvent
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
+ // Paper end - Call BlockDispenseEvent
RespawnAnchorBlock.charge(null, level, blockPos, blockState);
item.shrink(1);
} else {
@@ -412,6 +_,29 @@
@@ -398,6 +_,28 @@
this.setSuccess(false);
return item;
} else {
@@ -546,19 +394,18 @@
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ this.setSuccess(false);
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
@@ -567,30 +414,30 @@
for (Armadillo armadillo : entitiesOfClass) {
if (armadillo.brushOffScute()) {
item.hurtAndBreak(16, serverLevel, null, item1 -> {});
@@ -432,6 +_,13 @@
@@ -418,6 +_,13 @@
BlockState blockState = level.getBlockState(blockPos);
Optional<BlockState> waxed = HoneycombItem.getWaxed(blockState);
if (waxed.isPresent()) {
+ // Paper start - Call missing BlockDispenseEvent
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
+ // Paper end - Call BlockDispenseEvent
level.setBlockAndUpdate(blockPos, waxed.get());
level.levelEvent(3003, blockPos, 0);
item.shrink(1);
@@ -459,6 +_,12 @@
@@ -445,6 +_,12 @@
if (!serverLevel.getBlockState(blockPos1).is(BlockTags.CONVERTABLE_TO_MUD)) {
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
} else {
+ // Paper start - Call missing BlockDispenseEvent
+ // Paper start - Call BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos1, item, this);
+ if (result != null) {
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
+ // Paper end - Call BlockDispenseEvent
if (!serverLevel.isClientSide) {
for (int i = 0; i < 5; i++) {
serverLevel.sendParticles(

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
@@ -14,10 +_,16 @@
@@ -14,10 +_,17 @@
@Override
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
@@ -13,12 +13,13 @@
+ // Paper start
+ return dispenseEquipment(blockSource, item, null);
+ }
+
+ public static boolean dispenseEquipment(BlockSource blockSource, ItemStack item, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
+ // Paper end
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
List<LivingEntity> entitiesOfClass = blockSource.level()
.getEntitiesOfClass(LivingEntity.class, new AABB(blockPos), entity -> entity.canEquipWithDispenser(item));
@@ -26,13 +_,42 @@
@@ -26,13 +_,39 @@
} else {
LivingEntity livingEntity = entitiesOfClass.getFirst();
EquipmentSlot equipmentSlotForItem = livingEntity.getEquipmentSlotForItem(item);
@@ -31,22 +32,19 @@
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
+
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) livingEntity.getBukkitEntity());
+ if (!DispenserBlock.eventFired) {
+ world.getCraftServer().getPluginManager().callEvent(event);
+ }
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below
+ return false;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) {
+ dispenseItemBehavior.dispense(blockSource, eventStack);
+ return true;
+ }
@@ -55,7 +53,7 @@
+ livingEntity.setItemSlot(equipmentSlotForItem, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
+ // CraftBukkit end
if (livingEntity instanceof Mob mob) {
mob.setDropChance(equipmentSlotForItem, 2.0F);
mob.setGuaranteedDrop(equipmentSlotForItem);
mob.setPersistenceRequired();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
@@ -57,12 +_,38 @@
@@ -57,12 +_,35 @@
}
Vec3 vec31 = new Vec3(d, d1 + d3, d2);
@@ -11,22 +11,19 @@
+ org.bukkit.block.Block block2 = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec31.x, vec31.y, vec31.z));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(vec31));
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && dispenseItemBehavior != this) {
+ dispenseItemBehavior.dispense(blockSource, eventStack);
+ return item;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
+++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
@@ -27,17 +_,39 @@
@@ -27,17 +_,36 @@
ServerLevel serverLevel = blockSource.level();
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
Position dispensePosition = this.dispenseConfig.positionFunction().getDispensePosition(blockSource, direction);
@@ -15,38 +15,35 @@
- this.dispenseConfig.uncertainty()
- );
- item.shrink(1);
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ()));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(direction.getStepX(), direction.getStepY(), direction.getStepZ()));
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ // item.grow(1); // Paper - shrink below
+ return item;
+ }
+
+ boolean shrink = true; // Paper
+ boolean shrink = true;
+ if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ shrink = false;
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+ idispensebehavior.dispense(blockSource, eventStack);
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;
+ }
+ }
+
+ // SPIGOT-7923: Avoid create projectiles with empty item
+ if (!itemstack1.isEmpty()) {
+ Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(serverLevel, dispensePosition, org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()), direction), serverLevel, itemstack1, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies
+ iprojectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(blockSource.blockEntity());
+ if (!singleItemStack.isEmpty()) {
+ Projectile projectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(serverLevel, dispensePosition, org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()), direction), serverLevel, singleItemStack, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies
+ projectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(blockSource.blockEntity());
+ }
+ if (shrink) item.shrink(1); // Paper - actually handle here
+ if (shrink) item.shrink(1);
+ // CraftBukkit end
return item;
}

View File

@@ -1,26 +1,24 @@
--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
@@ -20,9 +_,32 @@
@@ -20,9 +_,30 @@
@Override
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
ServerLevel serverLevel = blockSource.level();
+
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) {
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+ }
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ this.setSuccess(false);
+ return item;
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;

View File

@@ -1,17 +1,15 @@
--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
@@ -22,10 +_,38 @@
@@ -22,10 +_,36 @@
BlockPos blockPos = blockSource.pos().relative(direction);
Direction direction1 = blockSource.level().isEmptyBlock(blockPos.below()) ? direction : Direction.UP;
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(blockSource.level(), blockSource.pos());
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1));
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
+ if (!DispenserBlock.eventFired) {
+ blockSource.level().getCraftServer().getPluginManager().callEvent(event);
+ }
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
+ blockSource.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return item;
@@ -20,7 +18,7 @@
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
+ dispenseBehavior.dispense(blockSource, eventStack);
+ return item;

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/core/registries/BuiltInRegistries.java
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
@@ -296,6 +_,17 @@
public static final Registry<SlotDisplay.Type<?>> SLOT_DISPLAY = registerSimple(Registries.SLOT_DISPLAY, SlotDisplays::bootstrap);
public static final Registry<RecipeBookCategory> RECIPE_BOOK_CATEGORY = registerSimple(Registries.RECIPE_BOOK_CATEGORY, RecipeBookCategories::bootstrap);
@@ -311,6 +_,17 @@
);
public static final Registry<Consumer<GameTestHelper>> TEST_FUNCTION = registerSimple(Registries.TEST_FUNCTION, BuiltinTestFunctions::bootstrap);
public static final Registry<? extends Registry<?>> REGISTRY = WRITABLE_REGISTRY;
+ // Paper start - add built-in registry conversions
+ public static final io.papermc.paper.registry.data.util.Conversions BUILT_IN_CONVERSIONS = new io.papermc.paper.registry.data.util.Conversions(new net.minecraft.resources.RegistryOps.RegistryInfoLookup() {
@@ -18,7 +18,7 @@
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> key, BuiltInRegistries.RegistryBootstrap<T> bootstrap) {
return internalRegister(key, new MappedRegistry<>(key, Lifecycle.stable(), false), bootstrap);
@@ -321,6 +_,7 @@
@@ -336,6 +_,7 @@
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> bootstrap
) {
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
@@ -26,7 +26,7 @@
ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
@@ -328,16 +_,34 @@
@@ -343,16 +_,34 @@
}
public static void bootStrap() {
@@ -61,7 +61,7 @@
});
}
@@ -346,6 +_,7 @@
@@ -361,6 +_,7 @@
for (Registry<?> registry : REGISTRY) {
bindBootstrappedTagsToEmpty(registry);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/data/loot/packs/VanillaChestLoot.java
+++ b/net/minecraft/data/loot/packs/VanillaChestLoot.java
@@ -946,7 +_,6 @@
@@ -1000,7 +_,6 @@
.add(
LootItem.lootTableItem(Items.COMPASS)
.apply(SetItemCountFunction.setCount(ConstantValue.exactly(1.0F)))

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/GameTestInfo.java
+++ b/net/minecraft/gametest/framework/GameTestInfo.java
@@ -241,7 +_,7 @@
@@ -247,7 +_,7 @@
AABB structureBounds = this.getStructureBounds();
List<Entity> entitiesOfClass = this.getLevel()
.getEntitiesOfClass(Entity.class, structureBounds.inflate(1.0), entity -> !(entity instanceof Player));

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/gametest/framework/GameTestMainUtil.java
+++ b/net/minecraft/gametest/framework/GameTestMainUtil.java
@@ -77,7 +_,7 @@
copyPacks(string, string1);
}
- LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld");
+ LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld", net.minecraft.world.level.dimension.LevelStem.OVERWORLD); // Paper
PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess);
MinecraftServer.spin(
thread -> GameTestServer.create(thread, levelStorageAccess, packRepository, optionalFromOption(optionSet, tests), optionSet.has(verify))

View File

@@ -1,7 +1,7 @@
--- a/net/minecraft/gametest/framework/GameTestServer.java
+++ b/net/minecraft/gametest/framework/GameTestServer.java
@@ -139,6 +_,8 @@
BlockPos spawnPos
@@ -133,6 +_,8 @@
boolean verify
) {
super(
+ null, // Paper
@@ -9,7 +9,7 @@
serverThread,
storageSource,
packRepository,
@@ -154,8 +_,15 @@
@@ -148,8 +_,15 @@
@Override
public boolean initServer() {
@@ -25,9 +25,9 @@
+ this.loadLevel("blah");
+ // Paper end
ServerLevel serverLevel = this.overworld();
this.testBatches = Lists.newArrayList(GameTestBatchFactory.fromTestFunction(this.testFunctions, serverLevel));
serverLevel.setDefaultSpawnPos(this.spawnPos, 0.0F);
@@ -303,6 +_,13 @@
this.testBatches = this.evaluateTestsToRun(serverLevel);
LOGGER.info("Started game test server");
@@ -338,6 +_,13 @@
public boolean shouldInformAdmins() {
return false;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/StructureUtils.java
+++ b/net/minecraft/gametest/framework/StructureUtils.java
@@ -187,7 +_,7 @@
@@ -86,7 +_,7 @@
level.clearBlockEvents(boundingBox1);
AABB aabb = AABB.of(boundingBox1);
List<Entity> entitiesOfClass = level.getEntitiesOfClass(Entity.class, aabb, entity -> !(entity instanceof Player));

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/gametest/framework/TestCommand.java
+++ b/net/minecraft/gametest/framework/TestCommand.java
@@ -278,7 +_,7 @@
}
private static int resetGameTestInfo(GameTestInfo gameTestInfo) {
- gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED));
+ gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD)); // Paper
gameTestInfo.getStructureBlockEntity().placeStructure(gameTestInfo.getLevel());
StructureUtils.removeBarriers(gameTestInfo.getStructureBounds(), gameTestInfo.getLevel());
say(gameTestInfo.getLevel(), "Reset succeded for: " + gameTestInfo.getTestName(), ChatFormatting.GREEN);

View File

@@ -0,0 +1,30 @@
--- a/net/minecraft/gametest/framework/TestEnvironmentDefinition.java
+++ b/net/minecraft/gametest/framework/TestEnvironmentDefinition.java
@@ -132,11 +_,11 @@
MinecraftServer server = level.getServer();
for (TestEnvironmentDefinition.SetGameRules.Entry<Boolean, GameRules.BooleanValue> entry : this.boolRules) {
- gameRules.getRule(entry.key()).set(entry.value(), server);
+ gameRules.getRule(entry.key()).set(entry.value(), level); // Paper - per-world
}
for (TestEnvironmentDefinition.SetGameRules.Entry<Integer, GameRules.IntegerValue> entry : this.intRules) {
- gameRules.getRule(entry.key()).set(entry.value(), server);
+ gameRules.getRule(entry.key()).set(entry.value(), level); // Paper - per-world
}
}
@@ -146,11 +_,11 @@
MinecraftServer server = level.getServer();
for (TestEnvironmentDefinition.SetGameRules.Entry<Boolean, GameRules.BooleanValue> entry : this.boolRules) {
- gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), server);
+ gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), level); // Paper - per-world
}
for (TestEnvironmentDefinition.SetGameRules.Entry<Integer, GameRules.IntegerValue> entry : this.intRules) {
- gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), server);
+ gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), level); // Paper - per-world
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/nbt/CompoundTag.java
+++ b/net/minecraft/nbt/CompoundTag.java
@@ -49,7 +_,7 @@
@@ -54,7 +_,7 @@
private static CompoundTag loadCompound(DataInput input, NbtAccounter nbtAccounter) throws IOException {
nbtAccounter.accountBytes(48L);
@@ -9,55 +9,21 @@
byte b;
while ((b = input.readByte()) != 0) {
@@ -166,7 +_,7 @@
@@ -171,7 +_,7 @@
}
public CompoundTag() {
- this(Maps.newHashMap());
- this(new HashMap<>());
+ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - Reduce memory footprint of CompoundTag
}
@Override
@@ -232,14 +_,34 @@
}
public void putUUID(String key, UUID value) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ this.tags.remove(key + "Most");
+ this.tags.remove(key + "Least");
+ }
+ // Paper end - Support old UUID format
this.tags.put(key, NbtUtils.createUUID(value));
}
+
+ /**
+ * You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
+ */
public UUID getUUID(String key) {
+ // Paper start - Support old UUID format
+ if (!contains(key, 11) && this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
+ }
+ // Paper end - Support old UUID format
return NbtUtils.loadUUID(this.get(key));
}
public boolean hasUUID(String key) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return true;
+ }
+ // Paper end - Support old UUID format
Tag tag = this.get(key);
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
}
@@ -477,8 +_,16 @@
@@ -402,9 +_,16 @@
@Override
public CompoundTag copy() {
- Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
- HashMap<String, Tag> map = new HashMap<>();
- this.tags.forEach((string, tag) -> map.put(string, tag.copy()));
- return new CompoundTag(map);
+ // Paper start - Reduce memory footprint of CompoundTag
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
@@ -72,3 +38,55 @@
}
@Override
@@ -525,22 +_,47 @@
this.merge((CompoundTag)mapCodec.encoder().encodeStart(ops, data).getOrThrow());
}
- public <T> Optional<T> read(String key, Codec<T> codec) {
+ public <T> Optional<T> read(String key, Codec<T> codec) { // Paper - option to read via codec without logging errors - diff on change
return this.read(key, codec, NbtOps.INSTANCE);
}
- public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) {
+ public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
Tag tag = this.get(key);
return tag == null
? Optional.empty()
: codec.parse(ops, tag).resultOrPartial(string -> LOGGER.error("Failed to read field ({}={}): {}", key, tag, string));
}
- public <T> Optional<T> read(MapCodec<T> mapCodec) {
+ public <T> Optional<T> read(MapCodec<T> mapCodec) { // Paper - option to read via codec without logging errors - diff on change
return this.read(mapCodec, NbtOps.INSTANCE);
}
- public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
+ public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial(string -> LOGGER.error("Failed to read value ({}): {}", this, string));
}
+
+ // Paper start - option to read via codec without logging errors
+ // The below methods are 1 to 1 copies of the above-defined read methods without the logging part.
+ // Copying was chosen over overloading the read methods as a boolean parameter to mark a method as quiet
+ // is not intuitive and would require even more overloads.
+ // Not a lot of diff in these methods is expected
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec) {
+ return this.readQuiet(key, codec, NbtOps.INSTANCE);
+ }
+
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec, DynamicOps<Tag> ops) {
+ Tag tag = this.get(key);
+ return tag == null
+ ? Optional.empty()
+ : codec.parse(ops, tag).resultOrPartial();
+ }
+
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec) {
+ return this.readQuiet(mapCodec, NbtOps.INSTANCE);
+ }
+
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
+ return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial();
+ }
+ // Paper end - option to read via codec without logging errors
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/nbt/NbtIo.java
+++ b/net/minecraft/nbt/NbtIo.java
@@ -118,6 +_,11 @@
@@ -119,6 +_,11 @@
}
public static CompoundTag read(DataInput input, NbtAccounter accounter) throws IOException {

View File

@@ -1,15 +0,0 @@
--- a/net/minecraft/nbt/NbtUtils.java
+++ b/net/minecraft/nbt/NbtUtils.java
@@ -143,8 +_,10 @@
if (!tag.contains("Name", 8)) {
return Blocks.AIR.defaultBlockState();
} else {
- ResourceLocation resourceLocation = ResourceLocation.parse(tag.getString("Name"));
- Optional<? extends Holder<Block>> optional = blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation));
+ // Paper start - Validate resource location
+ ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getString("Name"));
+ Optional<? extends Holder<Block>> optional = resourceLocation != null ? blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty();
+ // Paper end - Validate resource location
if (optional.isEmpty()) {
return Blocks.AIR.defaultBlockState();
} else {

View File

@@ -0,0 +1,21 @@
--- a/net/minecraft/nbt/SnbtGrammar.java
+++ b/net/minecraft/nbt/SnbtGrammar.java
@@ -591,7 +_,7 @@
Atom<List<Entry<String, T>>> atom30 = Atom.of("map_entries");
dictionary.put(atom30, Term.repeatedWithTrailingSeparator(namedRule3, atom30, StringReaderTerms.character(',')), scope -> scope.getOrThrow(atom30));
Atom<T> atom31 = Atom.of("map_literal");
- dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), dictionary.named(atom30), StringReaderTerms.character('}')), scope -> {
+ dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), Scope.increaseDepth(), dictionary.named(atom30), Scope.decreaseDepth(), StringReaderTerms.character('}')), scope -> { // Paper - track depth
List<Entry<String, T>> list = scope.getOrThrow(atom30);
if (list.isEmpty()) {
return object2;
@@ -626,7 +_,9 @@
atom35,
Term.sequence(
StringReaderTerms.character('['),
+ Scope.increaseDepth(), // Paper - track depth
Term.alternative(Term.sequence(dictionary.named(atom33), StringReaderTerms.character(';'), dictionary.named(atom34)), dictionary.named(atom32)),
+ Scope.decreaseDepth(), // Paper - track depth
StringReaderTerms.character(']')
),
parseState -> {

View File

@@ -1,54 +0,0 @@
--- a/net/minecraft/nbt/TagParser.java
+++ b/net/minecraft/nbt/TagParser.java
@@ -49,6 +_,7 @@
}, CompoundTag::toString);
public static final Codec<CompoundTag> LENIENT_CODEC = Codec.withAlternative(AS_CODEC, CompoundTag.CODEC);
private final StringReader reader;
+ private int depth; // Paper
public static CompoundTag parseTag(String text) throws CommandSyntaxException {
return new TagParser(new StringReader(text)).readSingleStruct();
@@ -159,6 +_,7 @@
public CompoundTag readStruct() throws CommandSyntaxException {
this.expect('{');
+ this.increaseDepth(); // Paper
CompoundTag compoundTag = new CompoundTag();
this.reader.skipWhitespace();
@@ -182,6 +_,7 @@
}
this.expect('}');
+ this.depth--; // Paper
return compoundTag;
}
@@ -191,6 +_,7 @@
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else {
+ this.increaseDepth(); // Paper
ListTag listTag = new ListTag();
TagType<?> tagType = null;
@@ -216,6 +_,7 @@
}
this.expect(']');
+ this.depth--; // Paper
return listTag;
}
}
@@ -287,5 +_,11 @@
private void expect(char expected) throws CommandSyntaxException {
this.reader.skipWhitespace();
this.reader.expect(expected);
+ }
+ private void increaseDepth() throws CommandSyntaxException {
+ this.depth++;
+ if (this.depth > 512) {
+ throw new io.papermc.paper.brigadier.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512");
+ }
}
}

View File

@@ -36,7 +36,7 @@
}
public static <T> IntFunction<T> limitValue(IntFunction<T> function, int limit) {
@@ -527,7 +_,7 @@
@@ -539,7 +_,7 @@
try {
NbtIo.writeAnyTag(nbt, new ByteBufOutputStream(buffer));

View File

@@ -0,0 +1,33 @@
--- a/net/minecraft/network/HashedStack.java
+++ b/net/minecraft/network/HashedStack.java
@@ -17,7 +_,7 @@
}
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return stack.isEmpty();
}
};
@@ -27,7 +_,7 @@
hashedStack -> hashedStack instanceof HashedStack.ActualItem actualItem ? Optional.of(actualItem) : Optional.empty()
);
- boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator);
+ boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching); // Paper - add flag to simplify remote matching logic
static HashedStack create(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
return (HashedStack)(stack.isEmpty()
@@ -47,10 +_,10 @@
);
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return this.count == stack.getCount()
&& this.item.equals(stack.getItemHolder())
- && this.components.matches(stack.getComponentsPatch(), hashGenerator);
+ && (simplifyMatching || this.components.matches(stack.getComponentsPatch(), hashGenerator)); // Paper - add flag to simplify remote matching logic
}
}
}

View File

@@ -9,7 +9,7 @@
- Component decorate(@Nullable ServerPlayer player, Component message);
+ ChatDecorator PLAIN = (player, message) -> java.util.concurrent.CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events
+
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
+ java.util.concurrent.CompletableFuture<Component> decorate(@Nullable ServerPlayer player, Component message); // Paper - adventure; support async chat decoration events
+
+ // Paper start - adventure; support async chat decoration events

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/ComponentSerialization.java
+++ b/net/minecraft/network/chat/ComponentSerialization.java
@@ -37,9 +_,31 @@
@@ -35,9 +_,31 @@
public class ComponentSerialization {
public static final Codec<Component> CODEC = Codec.recursive("Component", ComponentSerialization::createCodec);
@@ -34,7 +34,7 @@
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
ByteBufCodecs::optional
);
@@ -102,7 +_,25 @@
@@ -94,7 +_,25 @@
return ExtraCodecs.orCompressed(mapCodec2, mapCodec1);
}
@@ -60,7 +60,7 @@
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{
PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
};
@@ -115,6 +_,34 @@
@@ -107,6 +_,34 @@
)
.apply(instance, MutableComponent::new)
);

View File

@@ -4,7 +4,7 @@
}
}
+ @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate.
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate.
public static Optional<MutableComponent> updateForEntity(
@Nullable CommandSourceStack commandSourceStack, Optional<Component> optionalComponent, @Nullable Entity entity, int recursionDepth
) throws CommandSyntaxException {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/PlayerChatMessage.java
+++ b/net/minecraft/network/chat/PlayerChatMessage.java
@@ -17,6 +_,43 @@
@@ -18,6 +_,43 @@
public record PlayerChatMessage(
SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask
) {
@@ -44,7 +44,7 @@
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
@@ -47,7 +_,14 @@
@@ -48,7 +_,14 @@
}
public PlayerChatMessage withUnsignedContent(Component message) {

View File

@@ -1,20 +1,20 @@
--- a/net/minecraft/network/chat/contents/NbtContents.java
+++ b/net/minecraft/network/chat/contents/NbtContents.java
@@ -115,7 +_,7 @@
}).map(Tag::getAsString);
@@ -119,7 +_,7 @@
if (this.interpreting) {
RegistryOps<Tag> registryOps = nbtPathPattern.registryAccess().createSerializationContext(NbtOps.INSTANCE);
Component component = DataFixUtils.orElse(
- ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR
+ ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR // Paper - validate separator
);
return stream.flatMap(text -> {
return stream.flatMap(tag -> {
try {
@@ -127,7 +_,7 @@
}
@@ -132,7 +_,7 @@
}).reduce((mutableComponent, component1) -> mutableComponent.append(component).append(component1)).orElseGet(Component::empty);
} else {
Stream<String> stream1 = stream.map(NbtContents::asString);
- return ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth)
+ return ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth) // Paper - validate separator
.map(
mutableComponent -> stream.map(Component::literal)
mutableComponent -> stream1.map(Component::literal)
.reduce((mutableComponent1, otherMutableComponent) -> mutableComponent1.append(mutableComponent).append(otherMutableComponent))

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/network/codec/ByteBufCodecs.java
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
@@ -378,6 +_,48 @@
@@ -389,6 +_,48 @@
};
}

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
@@ -35,6 +_,20 @@
this.items = ItemStack.OPTIONAL_LIST_STREAM_CODEC.decode(buffer);
this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
}
@@ -22,6 +_,21 @@
ClientboundContainerSetContentPacket::new
);
+ // Paper start - Handle large packets disconnecting client
+ @Override
+ public boolean hasLargePacketFallback() {
@@ -18,6 +18,7 @@
+ return true;
+ }
+ // Paper end - Handle large packets disconnecting client
private void write(RegistryFriendlyByteBuf buffer) {
buffer.writeContainerId(this.containerId);
+
@Override
public PacketType<ClientboundContainerSetContentPacket> type() {
return GamePacketTypes.CLIENTBOUND_CONTAINER_SET_CONTENT;

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -52,7 +_,7 @@
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
@@ -50,7 +_,7 @@
public ClientboundLevelChunkPacketData(RegistryFriendlyByteBuf buffer, int x, int z) {
this.heightmaps = HEIGHTMAPS_STREAM_CODEC.decode(buffer);
int varInt = buffer.readVarInt();
- if (varInt > 2097152) {
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
int varInt = buffer.readVarInt();
- if (varInt > 2097152) {
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.buffer = new byte[varInt];
@@ -154,6 +_,7 @@
this.buffer = new byte[varInt];
@@ -151,6 +_,7 @@
CompoundTag updateTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
BlockPos blockPos = blockEntity.getBlockPos();
int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());

View File

@@ -97,7 +97,7 @@
- true,
+ listed, // Paper - Add Listing API for Player
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.gameMode(),
player.getTabListDisplayName(),
@@ -172,6 +_,11 @@
Optionull.map(player.getChatSession(), RemoteChatSession::asData)

View File

@@ -4,7 +4,7 @@
}
private static void pack(List<SynchedEntityData.DataValue<?>> dataValues, RegistryFriendlyByteBuf buffer) {
+ try (io.papermc.paper.util.ItemObfuscationSession ignored = io.papermc.paper.util.ItemObfuscationSession.start(io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level)) { // Paper - data sanitization
+ try (io.papermc.paper.util.sanitizer.ItemObfuscationSession ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.start(io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level)) { // Paper - data sanitization
for (SynchedEntityData.DataValue<?> dataValue : dataValues) {
dataValue.write(buffer);
}

View File

@@ -18,7 +18,7 @@
buffer.writeVarInt(this.entity);
int size = this.slots.size();
+ try (final io.papermc.paper.util.ItemObfuscationSession ignored = io.papermc.paper.util.ItemObfuscationSession.start(this.sanitize ? io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level : io.papermc.paper.util.ItemObfuscationSession.ObfuscationLevel.NONE)) { // Paper - data sanitization
+ try (final io.papermc.paper.util.sanitizer.ItemObfuscationSession ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.start(this.sanitize ? io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level : io.papermc.paper.util.sanitizer.ItemObfuscationSession.ObfuscationLevel.NONE)) { // Paper - data sanitization
for (int i = 0; i < size; i++) {
Pair<EquipmentSlot, ItemStack> pair = this.slots.get(i);
EquipmentSlot equipmentSlot = pair.getFirst();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
@@ -30,6 +_,11 @@
@@ -31,6 +_,11 @@
private final Collection<String> players;
private final Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters;
@@ -12,12 +12,12 @@
private ClientboundSetPlayerTeamPacket(String name, int method, Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters, Collection<String> players) {
this.name = name;
this.method = method;
@@ -198,7 +_,7 @@
@@ -199,7 +_,7 @@
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.displayName);
buffer.writeByte(this.options);
buffer.writeUtf(this.nametagVisibility);
- buffer.writeUtf(this.collisionRule);
+ buffer.writeUtf(!io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER.name : this.collisionRule); // Paper - Configurable player collision
Team.Visibility.STREAM_CODEC.encode(buffer, this.nametagVisibility);
- Team.CollisionRule.STREAM_CODEC.encode(buffer, this.collisionRule);
+ Team.CollisionRule.STREAM_CODEC.encode(buffer, !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER : this.collisionRule); // Paper - Configurable player collision
buffer.writeEnum(this.color);
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerPrefix);
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerSuffix);

View File

@@ -6,7 +6,7 @@
);
+ // Spigot start
+ public ClientboundSystemChatPacket(net.md_5.bungee.api.chat.BaseComponent[] content, boolean overlay) {
+ this(org.bukkit.craftbukkit.util.CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(content)), overlay);
+ this(org.bukkit.craftbukkit.util.CraftChatMessage.bungeeToVanilla(content), overlay);
+ }
+ // Spigot end
+ // Paper start

View File

@@ -1,20 +0,0 @@
--- a/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
+++ b/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
@@ -17,7 +_,7 @@
);
private static final int MAX_SLOT_COUNT = 128;
private static final StreamCodec<RegistryFriendlyByteBuf, Int2ObjectMap<ItemStack>> SLOTS_STREAM_CODEC = ByteBufCodecs.map(
- Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC, 128
+ Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth), 128 // Paper - Track codec depth
);
private final int containerId;
private final int stateId;
@@ -46,7 +_,7 @@
this.buttonNum = buffer.readByte();
this.clickType = buffer.readEnum(ClickType.class);
this.changedSlots = Int2ObjectMaps.unmodifiable(SLOTS_STREAM_CODEC.decode(buffer));
- this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
+ this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth).decode(buffer); // Paper - Track codec depth
}
private void write(RegistryFriendlyByteBuf buffer) {

View File

@@ -4,8 +4,8 @@
public static final StreamCodec<RegistryFriendlyByteBuf, ServerboundSetCreativeModeSlotPacket> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.SHORT,
ServerboundSetCreativeModeSlotPacket::slotNum,
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC),
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC),
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
ServerboundSetCreativeModeSlotPacket::itemStack,
ServerboundSetCreativeModeSlotPacket::new
);

View File

@@ -1,14 +1,5 @@
--- a/net/minecraft/network/syncher/SynchedEntityData.java
+++ b/net/minecraft/network/syncher/SynchedEntityData.java
@@ -45,7 +_,7 @@
}
}
- private <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) {
+ public <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { // Paper - public
return (SynchedEntityData.DataItem<T>)this.itemsById[key.id()];
}
@@ -67,6 +_,13 @@
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/resources/RegistryDataLoader.java
+++ b/net/minecraft/resources/RegistryDataLoader.java
@@ -247,13 +_,14 @@
@@ -271,13 +_,14 @@
RegistryOps<JsonElement> ops,
ResourceKey<E> resourceKey,
Resource resource,
@@ -17,7 +17,7 @@
}
}
@@ -267,6 +_,7 @@
@@ -291,6 +_,7 @@
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
@@ -25,7 +25,7 @@
for (Entry<ResourceLocation, Resource> entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) {
ResourceLocation resourceLocation = entry.getKey();
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), fileToIdConverter.fileToId(resourceLocation));
@@ -274,7 +_,7 @@
@@ -298,7 +_,7 @@
RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(resource.knownPackInfo());
try {
@@ -34,7 +34,7 @@
} catch (Exception var14) {
loadingErrors.put(
resourceKey,
@@ -283,7 +_,9 @@
@@ -307,7 +_,9 @@
}
}
@@ -45,7 +45,7 @@
}
static <E> void loadContentsFromNetwork(
@@ -300,6 +_,7 @@
@@ -324,6 +_,7 @@
RegistryOps<JsonElement> registryOps1 = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
@@ -53,7 +53,7 @@
for (RegistrySynchronization.PackedRegistryEntry packedRegistryEntry : networkedRegistryData.elements) {
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), packedRegistryEntry.id());
Optional<Tag> optional = packedRegistryEntry.data();
@@ -318,7 +_,7 @@
@@ -342,7 +_,7 @@
try {
Resource resourceOrThrow = resourceProvider.getResourceOrThrow(resourceLocation);
@@ -62,7 +62,7 @@
} catch (Exception var17) {
loadingErrors.put(resourceKey, new IllegalStateException("Failed to parse local data", var17));
}
@@ -360,6 +_,7 @@
@@ -384,6 +_,7 @@
RegistryDataLoader.Loader<T> create(Lifecycle registryLifecycle, Map<ResourceKey<?>, Exception> loadingErrors) {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, registryLifecycle);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/resources/ResourceLocation.java
+++ b/net/minecraft/resources/ResourceLocation.java
@@ -32,6 +_,7 @@
@@ -23,6 +_,7 @@
public static final char NAMESPACE_SEPARATOR = ':';
public static final String DEFAULT_NAMESPACE = "minecraft";
public static final String REALMS_NAMESPACE = "realms";
@@ -8,7 +8,7 @@
private final String namespace;
private final String path;
@@ -40,6 +_,13 @@
@@ -31,6 +_,13 @@
assert isValidPath(path);
@@ -22,7 +22,7 @@
this.namespace = namespace;
this.path = path;
}
@@ -252,7 +_,7 @@
@@ -243,7 +_,7 @@
private static String assertValidNamespace(String namespace, String path) {
if (!isValidNamespace(namespace)) {
@@ -31,7 +31,7 @@
} else {
return namespace;
}
@@ -277,7 +_,7 @@
@@ -268,7 +_,7 @@
private static String assertValidPath(String namespace, String path) {
if (!isValidPath(path)) {

View File

@@ -8,7 +8,7 @@
if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) {
throw new IllegalStateException("Unable to load registries");
} else {
@@ -54,11 +_,80 @@
@@ -54,11 +_,85 @@
EntitySelectorOptions.bootStrap();
DispenseItemBehavior.bootStrap();
CauldronInteraction.bootStrap();
@@ -25,25 +25,30 @@
+ // CraftBukkit start
+ // TODO Check what of this is needed, maybe report it to Mojira. if deemed relevant, move to the respective classes
+ // Used in CraftLegacy
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}");
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign");
+ for (int i = 0; i <= 15; i++) {
+ net.minecraft.util.datafix.fixes.BlockStateData.register(
+ 1008 + i,
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
+ "Name", "minecraft:oak_sign",
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
+ "Name", "minecraft:standing_sign",
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
+ );
+ }
+
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440, "{Name:'minecraft:portal',Properties:{axis:'x'}}", "{Name:'minecraft:portal',Properties:{axis:'x'}}");
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440,
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
+ "Name", "minecraft:portal",
+ "Properties", java.util.Map.of("axis", "x")
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
+ "Name", "minecraft:portal",
+ "Properties", java.util.Map.of("axis", "x")
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
+ );
+
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard");
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals");

View File

@@ -52,13 +52,13 @@
+ File configFile = (File) optionSet.valueOf("bukkit-settings");
+ org.bukkit.configuration.file.YamlConfiguration configuration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(configFile);
+ configuration.options().copyDefaults(true);
+ configuration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), com.google.common.base.Charsets.UTF_8)));
+ configuration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), java.nio.charset.StandardCharsets.UTF_8)));
+ configuration.save(configFile);
+
+ File commandFile = (File) optionSet.valueOf("commands-settings");
+ org.bukkit.configuration.file.YamlConfiguration commandsConfiguration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(commandFile);
+ commandsConfiguration.options().copyDefaults(true);
+ commandsConfiguration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), com.google.common.base.Charsets.UTF_8)));
+ commandsConfiguration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), java.nio.charset.StandardCharsets.UTF_8)));
+ commandsConfiguration.save(commandFile);
+ // CraftBukkit end
LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath());
@@ -116,7 +116,7 @@
Dynamic<?> dataTag;
if (levelStorageAccess.hasWorldData()) {
LevelSummary summary;
@@ -169,12 +_,30 @@
@@ -169,12 +_,33 @@
}
Dynamic<?> dynamic = dataTag;
@@ -134,12 +134,15 @@
+ }
+ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta");
+ try {
+ com.google.common.io.Files.write("{\n"
+ + " \"pack\": {\n"
+ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n"
+ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(net.minecraft.server.packs.PackType.SERVER_DATA) + "\n"
+ + " }\n"
+ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8);
+ com.google.common.io.Files.asCharSink(mcMeta, java.nio.charset.StandardCharsets.UTF_8).write("""
+ {
+ "pack": {
+ "description": "Data pack for resources provided by Bukkit plugins",
+ "pack_format": %d
+ }
+ }
+ """.formatted(SharedConstants.getCurrentVersion().getPackVersion(net.minecraft.server.packs.PackType.SERVER_DATA))
+ );
+ } catch (java.io.IOException ex) {
+ throw new RuntimeException("Could not initialize Bukkit datapack", ex);
+ }
@@ -180,11 +183,11 @@
+ /*
RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess();
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
if (optionSet.has(optionSpec4) || hasOptionSpec1) {
@@ -245,9 +_,13 @@
WorldData worldData = worldStem.worldData();
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
@@ -245,9 +_,13 @@
}
levelStorageAccess.saveDataTag(frozen, worldData);
+ */
final DedicatedServer dedicatedServer = MinecraftServer.spin(
@@ -241,12 +244,12 @@
} catch (Exception var42) {
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var42);
}
@@ -316,7 +_,7 @@
@@ -317,7 +_,7 @@
RegistryAccess registryAccess,
boolean recreateRegionFiles
) {
- LOGGER.info("Forcing world upgrade!");
+ LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, registryAccess, eraseCache, recreateRegionFiles)) {
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, worldData, registryAccess, eraseCache, recreateRegionFiles)) {
Component component = null;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -174,11 +_,13 @@
@@ -173,11 +_,13 @@
import org.slf4j.Logger;
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource {
@@ -15,7 +15,7 @@
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
@@ -218,6 +_,7 @@
@@ -217,6 +_,7 @@
private Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap();
private PlayerList playerList;
private volatile boolean running = true;
@@ -23,7 +23,7 @@
private boolean stopped;
private int tickCount;
private int ticksUntilAutosave = 6000;
@@ -226,11 +_,15 @@
@@ -225,11 +_,15 @@
private boolean preventProxyConnections;
private boolean pvp;
private boolean allowFlight;
@@ -41,7 +41,7 @@
@Nullable
private KeyPair keyPair;
@Nullable
@@ -271,10 +_,37 @@
@@ -270,10 +_,37 @@
private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector();
private final DiscontinuousFrame tickFrame;
@@ -80,7 +80,7 @@
if (Runtime.getRuntime().availableProcessors() > 4) {
thread.setPriority(8);
}
@@ -286,6 +_,10 @@
@@ -285,6 +_,10 @@
}
public MinecraftServer(
@@ -91,7 +91,7 @@
Thread serverThread,
LevelStorageSource.LevelStorageAccess storageSource,
PackRepository packRepository,
@@ -296,9 +_,10 @@
@@ -295,9 +_,10 @@
ChunkProgressListenerFactory progressListenerFactory
) {
super("Server");
@@ -103,7 +103,7 @@
throw new IllegalStateException("Missing Overworld dimension data");
} else {
this.proxy = proxy;
@@ -309,7 +_,7 @@
@@ -308,7 +_,7 @@
services.profileCache().setExecutor(this);
}
@@ -112,7 +112,7 @@
this.tickRateManager = new ServerTickRateManager(this);
this.progressListenerFactory = progressListenerFactory;
this.storageSource = storageSource;
@@ -328,6 +_,38 @@
@@ -327,6 +_,38 @@
this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures());
this.tickFrame = TracyClient.createDiscontinuousFrame("Server Tick");
}
@@ -151,7 +151,7 @@
}
private void readScoreboard(DimensionDataStorage dataStorage) {
@@ -336,18 +_,13 @@
@@ -335,18 +_,13 @@
protected abstract boolean initServer() throws IOException;
@@ -172,7 +172,7 @@
if (profiledDuration != null) {
profiledDuration.finish(true);
}
@@ -364,25 +_,265 @@
@@ -363,25 +_,265 @@
protected void forceDifficulty() {
}
@@ -349,7 +349,7 @@
+
+ primaryLevelData.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end)
+ if (this.options.has("forceUpgrade")) {
+ net.minecraft.server.Main.forceUpgrade(levelStorageAccess, net.minecraft.util.datafix.DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> true, registryAccess, this.options.has("recreateRegionFiles"));
+ net.minecraft.server.Main.forceUpgrade(levelStorageAccess, primaryLevelData, net.minecraft.util.datafix.DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> true, registryAccess, this.options.has("recreateRegionFiles"));
+ }
+
+ // Now modelled off the createLevels method
@@ -457,7 +457,7 @@
if (!serverLevelData.isInitialized()) {
try {
setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld);
@@ -403,47 +_,30 @@
@@ -402,47 +_,30 @@
serverLevelData.setInitialized(true);
}
@@ -522,7 +522,7 @@
int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level);
if (spawnHeight < level.getMinY()) {
BlockPos worldPosition = chunkPos.getWorldPosition();
@@ -495,26 +_,31 @@
@@ -494,36 +_,48 @@
serverLevelData.setGameType(GameType.SPECTATOR);
}
@@ -557,12 +557,11 @@
- for (ServerLevel serverLevel1 : this.levels.values()) {
+ if (true) {
+ ServerLevel serverLevel1 = serverLevel;
+ final ServerLevel serverLevel1 = serverLevel;
+ // CraftBukkit end
ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks");
if (forcedChunksSavedData != null) {
LongIterator longIterator = forcedChunksSavedData.getChunks().iterator();
@@ -527,10 +_,17 @@
TicketStorage ticketStorage = serverLevel1.getDataStorage().get(TicketStorage.TYPE);
if (ticketStorage != null) {
ticketStorage.activateAllDeactivatedTickets();
}
}
@@ -583,11 +582,11 @@
}
public GameType getDefaultGameType() {
@@ -559,11 +_,14 @@
@@ -552,11 +_,14 @@
flag = true;
}
+ /* // CraftBukkit start - moved to WorldServer.save
+ /* // CraftBukkit start - moved to ServerLevel#save
ServerLevel serverLevel1 = this.overworld();
ServerLevelData serverLevelData = this.worldData.overworldData();
serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings());
@@ -598,7 +597,7 @@
if (flush) {
for (ServerLevel serverLevel2 : this.getAllLevels()) {
LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName());
@@ -593,18 +_,48 @@
@@ -586,18 +_,48 @@
this.stopServer();
}
@@ -648,7 +647,7 @@
}
LOGGER.info("Saving worlds");
@@ -646,6 +_,25 @@
@@ -639,6 +_,25 @@
} catch (IOException var4) {
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4);
}
@@ -674,7 +673,7 @@
}
public String getLocalIp() {
@@ -661,6 +_,14 @@
@@ -654,6 +_,14 @@
}
public void halt(boolean waitForServer) {
@@ -689,7 +688,7 @@
this.running = false;
if (waitForServer) {
try {
@@ -671,6 +_,57 @@
@@ -664,6 +_,57 @@
}
}
@@ -747,7 +746,7 @@
protected void runServer() {
try {
if (!this.initServer()) {
@@ -681,6 +_,35 @@
@@ -674,6 +_,35 @@
this.statusIcon = this.loadStatusIcon().orElse(null);
this.status = this.buildServerStatus();
@@ -783,7 +782,7 @@
while (this.running) {
long l;
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
@@ -693,11 +_,30 @@
@@ -686,11 +_,30 @@
if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l
&& this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) {
long l2 = l1 / l;
@@ -814,7 +813,7 @@
boolean flag = l == 0L;
if (this.debugCommandProfilerDelayStart) {
@@ -705,6 +_,8 @@
@@ -698,6 +_,8 @@
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
@@ -823,7 +822,7 @@
this.nextTickTimeNanos += l;
try (Profiler.Scope scope = Profiler.use(this.createProfiler())) {
@@ -755,7 +_,7 @@
@@ -748,7 +_,7 @@
this.services.profileCache().clearExecutor();
}
@@ -832,7 +831,7 @@
}
}
}
@@ -807,7 +_,14 @@
@@ -800,7 +_,14 @@
}
private boolean haveTime() {
@@ -848,7 +847,7 @@
}
public static boolean throwIfFatalException() {
@@ -852,6 +_,12 @@
@@ -845,6 +_,12 @@
@Override
public TickTask wrapRunnable(Runnable runnable) {
@@ -861,7 +860,7 @@
return new TickTask(this.tickCount, runnable);
}
@@ -871,15 +_,16 @@
@@ -864,15 +_,16 @@
if (super.pollTask()) {
return true;
} else {
@@ -880,7 +879,7 @@
}
}
@@ -927,26 +_,44 @@
@@ -920,26 +_,44 @@
}
public void tickServer(BooleanSupplier hasTimeLeft) {
@@ -926,7 +925,7 @@
this.tickCount++;
this.tickRateManager.tick();
this.tickChildren(hasTimeLeft);
@@ -956,11 +_,19 @@
@@ -949,11 +_,19 @@
}
this.ticksUntilAutosave--;
@@ -947,7 +946,7 @@
profilerFiller.push("tallying");
long l = Util.getNanos() - nanos;
int i1 = this.tickCount % 100;
@@ -968,12 +_,17 @@
@@ -961,12 +_,17 @@
this.aggregatedTickTimesNanos += l;
this.tickTimesNanos[i1] = l;
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
@@ -966,7 +965,7 @@
LOGGER.debug("Autosave started");
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("save");
@@ -1015,7 +_,7 @@
@@ -1008,7 +_,7 @@
private ServerStatus buildServerStatus() {
ServerStatus.Players players = this.buildPlayerStatus();
return new ServerStatus(
@@ -975,7 +974,7 @@
Optional.of(players),
Optional.of(ServerStatus.Version.current()),
Optional.ofNullable(this.statusIcon),
@@ -1029,7 +_,7 @@
@@ -1022,7 +_,7 @@
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
} else {
@@ -984,7 +983,7 @@
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
@@ -1046,17 +_,66 @@
@@ -1039,17 +_,66 @@
protected void tickChildren(BooleanSupplier hasTimeLeft) {
ProfilerFiller profilerFiller = Profiler.get();
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
@@ -1051,7 +1050,7 @@
profilerFiller.push("tick");
@@ -1070,7 +_,9 @@
@@ -1063,7 +_,9 @@
profilerFiller.pop();
profilerFiller.pop();
@@ -1061,7 +1060,7 @@
profilerFiller.popPush("connection");
this.tickConnection();
@@ -1148,6 +_,22 @@
@@ -1141,6 +_,22 @@
return this.levels.get(dimension);
}
@@ -1084,7 +1083,7 @@
public Set<ResourceKey<Level>> levelKeys() {
return this.levels.keySet();
}
@@ -1177,7 +_,7 @@
@@ -1170,7 +_,7 @@
@DontObfuscate
public String getServerModName() {
@@ -1093,7 +1092,7 @@
}
public SystemReport fillSystemReport(SystemReport systemReport) {
@@ -1212,7 +_,7 @@
@@ -1205,7 +_,7 @@
@Override
public void sendSystemMessage(Component component) {
@@ -1102,7 +1101,7 @@
}
public KeyPair getKeyPair() {
@@ -1250,11 +_,14 @@
@@ -1243,11 +_,14 @@
}
}
@@ -1112,9 +1111,9 @@
- this.updateMobSpawningFlags();
- this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
+ // Paper start - per level difficulty
+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forceUpdate) {
+ net.minecraft.world.level.storage.PrimaryLevelData worldData = (net.minecraft.world.level.storage.PrimaryLevelData) level.serverLevelData;
+ if (forceUpdate || !worldData.isDifficultyLocked()) {
+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forced) {
+ net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData;
+ if (forced || !worldData.isDifficultyLocked()) {
+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty);
+ level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters);
+ // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
@@ -1122,7 +1121,7 @@
}
}
@@ -1264,7 +_,7 @@
@@ -1257,7 +_,7 @@
private void updateMobSpawningFlags() {
for (ServerLevel serverLevel : this.getAllLevels()) {
@@ -1131,7 +1130,7 @@
}
}
@@ -1340,10 +_,20 @@
@@ -1333,10 +_,20 @@
@Override
public String getMotd() {
@@ -1153,7 +1152,7 @@
this.motd = motd;
}
@@ -1366,7 +_,7 @@
@@ -1359,7 +_,7 @@
}
public ServerConnectionListener getConnection() {
@@ -1162,7 +1161,7 @@
}
public boolean isReady() {
@@ -1452,7 +_,7 @@
@@ -1445,7 +_,7 @@
@Override
public void executeIfPossible(Runnable task) {
if (this.isStopped()) {
@@ -1171,7 +1170,7 @@
} else {
super.executeIfPossible(task);
}
@@ -1491,7 +_,13 @@
@@ -1484,7 +_,14 @@
return this.functionManager;
}
@@ -1180,12 +1179,13 @@
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds) {
+ return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
+ }
+
+ public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
+ // Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
() -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()),
this
@@ -1499,7 +_,7 @@
@@ -1492,7 +_,7 @@
.thenCompose(
list -> {
CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list);
@@ -1194,7 +1194,7 @@
return ReloadableServerResources.loadResources(
closeableResourceManager,
this.registries,
@@ -1520,20 +_,39 @@
@@ -1513,20 +_,39 @@
)
.thenAcceptAsync(
reloadableResources -> {
@@ -1236,7 +1236,7 @@
},
this
);
@@ -1550,7 +_,7 @@
@@ -1543,7 +_,7 @@
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
@@ -1245,7 +1245,7 @@
if (safeMode) {
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
} else {
@@ -1605,7 +_,7 @@
@@ -1598,7 +_,7 @@
private static WorldDataConfiguration configureRepositoryWithSelection(
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
) {
@@ -1254,7 +1254,7 @@
enableForcedFeaturePacks(packRepository, enabledFeatures);
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
@@ -1637,7 +_,7 @@
@@ -1630,7 +_,7 @@
}
}
@@ -1263,7 +1263,7 @@
}
}
@@ -1651,11 +_,12 @@
@@ -1644,11 +_,12 @@
public void kickUnlistedPlayers(CommandSourceStack commandSource) {
if (this.isEnforceWhitelist()) {
PlayerList playerList = commandSource.getServer().getPlayerList();
@@ -1278,7 +1278,7 @@
}
}
}
@@ -1859,6 +_,22 @@
@@ -1852,6 +_,17 @@
}
}
@@ -1289,19 +1289,14 @@
+ }
+
+ public static MinecraftServer getServer() {
+ return SERVER; // Paper
+ }
+
+ @Deprecated
+ public static RegistryAccess getDefaultRegistryAccess() {
+ return org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry();
+ return SERVER;
+ }
+ // CraftBukkit end
+
private ProfilerFiller createProfiler() {
if (this.willStartRecordingMetrics) {
this.metricsRecorder = ActiveMetricsRecorder.createStarted(
@@ -1980,16 +_,22 @@
@@ -1973,16 +_,22 @@
}
public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) {
@@ -1328,7 +1323,7 @@
}
public boolean logIPs() {
@@ -2122,4 +_,53 @@
@@ -2115,4 +_,53 @@
};
}
}

View File

@@ -68,7 +68,7 @@
});
}
@@ -247,7 +_,7 @@
public void flushDirty(ServerPlayer serverPlayer) {
public void flushDirty(ServerPlayer player, boolean showAdvancements) {
if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();
- Set<AdvancementHolder> set = new HashSet<>();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/ServerScoreboard.java
+++ b/net/minecraft/server/ServerScoreboard.java
@@ -39,9 +_,7 @@
@@ -43,9 +_,7 @@
protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) {
super.onScoreChanged(scoreHolder, objective, score);
if (this.trackedObjectives.contains(objective)) {
@@ -11,7 +11,7 @@
new ClientboundSetScorePacket(
scoreHolder.getScoreboardName(),
objective.getName(),
@@ -64,7 +_,7 @@
@@ -68,7 +_,7 @@
@Override
public void onPlayerRemoved(ScoreHolder scoreHolder) {
super.onPlayerRemoved(scoreHolder);
@@ -20,7 +20,7 @@
this.setDirty();
}
@@ -72,7 +_,7 @@
@@ -76,7 +_,7 @@
public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) {
super.onPlayerScoreRemoved(scoreHolder, objective);
if (this.trackedObjectives.contains(objective)) {
@@ -29,7 +29,7 @@
}
this.setDirty();
@@ -84,7 +_,7 @@
@@ -88,7 +_,7 @@
super.setDisplayObjective(slot, objective);
if (displayObjective != objective && displayObjective != null) {
if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) {
@@ -38,7 +38,7 @@
} else {
this.stopTrackingObjective(displayObjective);
}
@@ -92,7 +_,7 @@
@@ -96,7 +_,7 @@
if (objective != null) {
if (this.trackedObjectives.contains(objective)) {
@@ -47,7 +47,7 @@
} else {
this.startTrackingObjective(objective);
}
@@ -104,24 +_,50 @@
@@ -108,24 +_,50 @@
@Override
public boolean addPlayerToTeam(String playerName, PlayerTeam team) {
if (super.addPlayerToTeam(playerName, team)) {
@@ -112,7 +112,7 @@
@Override
public void onObjectiveAdded(Objective objective) {
@@ -133,7 +_,7 @@
@@ -137,7 +_,7 @@
public void onObjectiveChanged(Objective objective) {
super.onObjectiveChanged(objective);
if (this.trackedObjectives.contains(objective)) {
@@ -121,7 +121,7 @@
}
this.setDirty();
@@ -152,21 +_,21 @@
@@ -156,21 +_,21 @@
@Override
public void onTeamAdded(PlayerTeam playerTeam) {
super.onTeamAdded(playerTeam);
@@ -146,7 +146,7 @@
this.setDirty();
}
@@ -209,6 +_,7 @@
@@ -213,6 +_,7 @@
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -154,7 +154,7 @@
for (Packet<?> packet : startTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -234,6 +_,7 @@
@@ -238,6 +_,7 @@
List<Packet<?>> stopTrackingPackets = this.getStopTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@@ -162,9 +162,9 @@
for (Packet<?> packet : stopTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -267,6 +_,16 @@
private ScoreboardSaveData createData(CompoundTag tag, HolderLookup.Provider registries) {
return this.createData().load(tag, registries);
@@ -269,6 +_,16 @@
scoreboardSaveData.loadFrom(data);
return scoreboardSaveData;
}
+
+ // CraftBukkit start - Send to players

View File

@@ -7,11 +7,9 @@
- MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache
+ MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations // Paper - add paper configuration files
) {
- private static final String USERID_CACHE_FILE = "usercache.json";
-
public static final String USERID_CACHE_FILE = "usercache.json";
- public static Services create(YggdrasilAuthenticationService authenticationService, File profileRepository) {
+ public static final String USERID_CACHE_FILE = "usercache.json"; // Paper - private -> public
+
+ // Paper start - add paper configuration files
+ public Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache) {
+ this(sessionService, servicesKeySet, profileRepository, profileCache, null);

View File

@@ -8,15 +8,6 @@
int maxStackSize = itemStack.getMaxStackSize();
int i = maxStackSize * 100;
if (count > i) {
@@ -66,7 +_,7 @@
ItemStack itemStack1 = item.createItemStack(min, false);
boolean flag = serverPlayer.getInventory().add(itemStack1);
if (flag && itemStack1.isEmpty()) {
- ItemEntity itemEntity = serverPlayer.drop(itemStack, false);
+ ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event
if (itemEntity != null) {
itemEntity.makeFakeItem();
}
@@ -95,11 +_,11 @@
if (targets.size() == 1) {

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/server/commands/OpCommand.java
+++ b/net/minecraft/server/commands/OpCommand.java
@@ -46,7 +_,7 @@
if (!playerList.isOp(gameProfile)) {
playerList.op(gameProfile);
i++;
- source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfiles.iterator().next().getName()), true);
+ source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfile.getName()), true); // Paper - fixes MC-253721
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/PlaceCommand.java
+++ b/net/minecraft/server/commands/PlaceCommand.java
@@ -280,6 +_,7 @@
@@ -301,6 +_,7 @@
if (!structureStart.isValid()) {
throw ERROR_STRUCTURE_FAILED.create();
} else {

View File

@@ -6,10 +6,10 @@
+ final Collection<ServerPlayer> actualTargets = new java.util.ArrayList<>(); // Paper - Add PlayerSetSpawnEvent
for (ServerPlayer serverPlayer : targets) {
- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false);
- serverPlayer.setRespawnPosition(new ServerPlayer.RespawnConfig(resourceKey, pos, angle, true), false);
- }
+ // Paper start - Add PlayerSetSpawnEvent
+ if (serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
+ if (serverPlayer.setRespawnPosition(new ServerPlayer.RespawnConfig(resourceKey, pos, angle, true), false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
+ actualTargets.add(serverPlayer);
+ }
+ // Paper end - Add PlayerSetSpawnEvent

View File

@@ -3,7 +3,7 @@
@@ -82,6 +_,7 @@
ServerLevel level = source.getLevel();
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, EntitySpawnReason.COMMAND, entity1 -> {
entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
entity1.snapTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
+ entity1.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND; // Paper - Entity#getEntitySpawnReason
return entity1;
});

View File

@@ -33,56 +33,24 @@
this.serverTextFilter = ServerTextFilter.createFromConfig(settings.getProperties());
this.serverLinks = createServerLinks(settings);
}
@@ -102,26 +_,95 @@
@@ -102,6 +_,10 @@
Thread thread = new Thread("Server console handler") {
@Override
public void run() {
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
-
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.Main.useConsole) return;
+ if (!org.bukkit.craftbukkit.Main.useConsole) return; // CraftBukkit
+ // Paper start - Use TerminalConsoleAppender
+ new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
+ /*
+ jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader;
+ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return
+ try {
+ System.in.available();
+ } catch (IOException ex) {
+ return;
+ }
+ // CraftBukkit end
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
String string1;
try {
- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (string1 = bufferedReader.readLine()) != null) {
- DedicatedServer.this.handleConsoleInput(string1, DedicatedServer.this.createCommandSourceStack());
+ // CraftBukkit start - JLine disabling compatibility
+ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) {
+ if (org.bukkit.craftbukkit.Main.useJline) {
+ string1 = bufferedreader.readLine(">", null);
+ } else {
+ string1 = bufferedreader.readLine();
+ }
+
+ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null
+ if (string1 == null) {
+ try {
+ Thread.sleep(50L);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ continue;
+ }
+ if (string1.trim().length() > 0) { // Trim to filter lines which are just spaces
+ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener());
+ }
+ // CraftBukkit end
@@ -111,17 +_,41 @@
}
} catch (IOException var4) {
DedicatedServer.LOGGER.error("Exception handling console input", (Throwable)var4);
}
+ */
+ // Paper end
- }
+ }*/
+ // Paper end - Use TerminalConsoleAppender
}
};
+ // CraftBukkit start - TODO: handle command-line logging arguments
@@ -93,21 +61,7 @@
+ }
+ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler());
+
+ // Paper start - Not needed with TerminalConsoleAppender
+ final org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getRootLogger();
+ /*
+ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger());
+ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) {
+ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) {
+ logger.removeAppender(appender);
+ }
+ }
+
+ TerminalConsoleWriterThread writerThread = new TerminalConsoleWriterThread(System.out, this.reader);
+ this.reader.setCompletionHandler(new TerminalCompletionHandler(writerThread, this.reader.getCompletionHandler()));
+ writerThread.start();
+ */
+ // Paper end - Not needed with TerminalConsoleAppender
+
+ System.setOut(org.apache.logging.log4j.io.IoBuilder.forLogger(logger).setLevel(org.apache.logging.log4j.Level.INFO).buildPrintStream());
+ System.setErr(org.apache.logging.log4j.io.IoBuilder.forLogger(logger).setLevel(org.apache.logging.log4j.Level.WARN).buildPrintStream());
@@ -187,7 +141,7 @@
InetAddress inetAddress = null;
if (!this.getLocalIp().isEmpty()) {
inetAddress = InetAddress.getByName(this.getLocalIp());
@@ -147,36 +_,62 @@
@@ -147,36 +_,61 @@
if (this.getPort() < 0) {
this.setPort(properties.serverPort);
}
@@ -210,7 +164,6 @@
}
+ // CraftBukkit start
+ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up
+ this.server.loadPlugins();
+ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP);
+ // CraftBukkit end

View File

@@ -15,7 +15,7 @@
+ }
+
+ private String getOverride(String name, String value) {
+ if ((this.options != null) && (this.options.has(name))) {
+ if (this.options != null && this.options.has(name)) {
+ return String.valueOf(this.options.valueOf(name));
+ }
+

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -145,6 +_,33 @@
@@ -149,6 +_,33 @@
public int serverViewDistance;
private final WorldGenContext worldGenContext;
@@ -34,7 +34,7 @@
public ChunkMap(
ServerLevel level,
LevelStorageSource.LevelStorageAccess levelStorageAccess,
@@ -171,13 +_,19 @@
@@ -176,13 +_,19 @@
this.level = level;
RegistryAccess registryAccess = level.registryAccess();
long seed = level.getSeed();
@@ -56,7 +56,7 @@
this.mainThreadExecutor = mainThreadExecutor;
ConsecutiveExecutor consecutiveExecutor = new ConsecutiveExecutor(dispatcher, "worldgen");
this.progressListener = progressListener;
@@ -207,6 +_,12 @@
@@ -213,6 +_,12 @@
this.chunksToEagerlySave.add(chunkPos.toLong());
}
@@ -69,7 +69,7 @@
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
}
@@ -354,9 +_,9 @@
@@ -352,9 +_,9 @@
}
);
stringBuilder.append("Updating:").append(System.lineSeparator());
@@ -81,17 +81,15 @@
CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading");
CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading");
crashReportCategory.setDetail("Details", details);
@@ -392,6 +_,9 @@
@@ -390,6 +_,7 @@
holder.setTicketLevel(newLevel);
} else {
holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this::onLevelChange, this);
+ // Paper start
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder);
+ // Paper end
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder); // Paper
}
this.updatingChunkMap.put(chunkPos, holder);
@@ -420,8 +_,8 @@
@@ -418,8 +_,8 @@
protected void saveAllChunks(boolean flush) {
if (flush) {
@@ -102,7 +100,7 @@
.stream()
.filter(ChunkHolder::wasAccessibleSinceLastSave)
.peek(ChunkHolder::refreshAccessibility)
@@ -447,7 +_,7 @@
@@ -445,7 +_,7 @@
this.nextChunkSaveTime.clear();
long millis = Util.getMillis();
@@ -111,7 +109,7 @@
this.saveChunkIfNeeded(chunkHolder, millis);
}
}
@@ -468,6 +_,7 @@
@@ -466,6 +_,7 @@
public boolean hasWork() {
return this.lightEngine.hasLightWork()
|| !this.pendingUnloads.isEmpty()
@@ -119,7 +117,7 @@
|| !this.updatingChunkMap.isEmpty()
|| this.poiManager.hasWork()
|| !this.toDrop.isEmpty()
@@ -526,7 +_,11 @@
@@ -524,7 +_,11 @@
this.scheduleUnload(chunkPos, chunkHolder);
} else {
ChunkAccess latestChunk = chunkHolder.getLatestChunk();
@@ -132,7 +130,7 @@
if (latestChunk instanceof LevelChunk levelChunk) {
levelChunk.setLoaded(false);
}
@@ -540,7 +_,9 @@
@@ -538,7 +_,9 @@
this.lightEngine.tryScheduleUpdate();
this.progressListener.onStatusChange(latestChunk.getPos(), null);
this.nextChunkSaveTime.remove(latestChunk.getPos().toLong());
@@ -143,7 +141,7 @@
}
}, this.unloadQueue::add).whenComplete((_void, error) -> {
if (error != null) {
@@ -856,7 +_,7 @@
@@ -854,7 +_,7 @@
}
public int size() {
@@ -152,7 +150,7 @@
}
public net.minecraft.server.level.DistanceManager getDistanceManager() {
@@ -864,7 +_,7 @@
@@ -862,7 +_,7 @@
}
protected Iterable<ChunkHolder> getChunks() {
@@ -161,9 +159,9 @@
}
void dumpChunks(Writer writer) throws IOException {
@@ -888,10 +_,10 @@
@@ -885,10 +_,10 @@
.addColumn("fluid_ticks")
.build(writer);
TickingTracker tickingTracker = this.distanceManager.tickingTracker();
- for (Entry<ChunkHolder> entry : this.visibleChunkMap.long2ObjectEntrySet()) {
- long longKey = entry.getLongKey();
@@ -175,7 +173,7 @@
Optional<ChunkAccess> optional = Optional.ofNullable(chunkHolder.getLatestChunk());
Optional<LevelChunk> optional1 = optional.flatMap(chunk -> chunk instanceof LevelChunk ? Optional.of((LevelChunk)chunk) : Optional.empty());
csvOutput.writeRow(
@@ -931,11 +_,13 @@
@@ -928,11 +_,13 @@
}
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
@@ -191,18 +189,28 @@
+ // CraftBukkit end
}
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> action) {
@@ -951,12 +_,34 @@
void collectSpawningChunks(List<LevelChunk> output) {
@@ -942,7 +_,7 @@
ChunkHolder chunkHolder = this.visibleChunkMap.get(spawnCandidateChunks.nextLong());
if (chunkHolder != null) {
LevelChunk tickingChunk = chunkHolder.getTickingChunk();
- if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos())) {
+ if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos(), true)) { // Spigot
output.add(tickingChunk);
}
}
@@ -962,13 +_,35 @@
}
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) {
- return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos);
+ // Spigot start
+ return this.anyPlayerCloseEnoughForSpawning(chunkPos, false);
+ }
+
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos, boolean reducedRange) {
+ return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange);
TriState triState = this.distanceManager.hasPlayersNearby(chunkPos.toLong());
- return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos) : triState.toBoolean(true);
+ return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange) : triState.toBoolean(true);
+ // Spigot end
}
@@ -224,12 +232,12 @@
+ if (event == null || event.isCancelled()) continue;
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
+ }
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, blockRange)) {
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
return true;
}
}
@@ -972,7 +_,7 @@
@@ -984,7 +_,7 @@
Builder<ServerPlayer> builder = ImmutableList.builder();
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
@@ -238,7 +246,7 @@
builder.add(serverPlayer);
}
}
@@ -981,12 +_,12 @@
@@ -993,12 +_,12 @@
}
}
@@ -247,13 +255,13 @@
if (player.isSpectator()) {
return false;
} else {
double d = euclideanDistanceSquared(chunkPos, player);
double d = euclideanDistanceSquared(chunkPos, player.position());
- return d < 16384.0;
+ return d < range; // Spigot
}
}
@@ -1100,9 +_,19 @@
@@ -1120,9 +_,19 @@
}
public void addEntity(Entity entity) {
@@ -273,7 +281,7 @@
if (i != 0) {
int updateInterval = type.updateInterval();
if (this.entityMap.containsKey(entity.getId())) {
@@ -1126,6 +_,7 @@
@@ -1146,6 +_,7 @@
}
protected void removeEntity(Entity entity) {
@@ -281,16 +289,7 @@
if (entity instanceof ServerPlayer serverPlayer) {
this.updatePlayerStatus(serverPlayer, false);
@@ -1230,7 +_,7 @@
});
}
- class DistanceManager extends net.minecraft.server.level.DistanceManager {
+ public class DistanceManager extends net.minecraft.server.level.DistanceManager { // Paper - public
protected DistanceManager(final Executor dispatcher, final Executor mainThreadExecutor) {
super(dispatcher, mainThreadExecutor);
}
@@ -1258,10 +_,10 @@
@@ -1278,10 +_,10 @@
final Entity entity;
private final int range;
SectionPos lastSectionPos;
@@ -298,12 +297,12 @@
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast);
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this.seenBy); // CraftBukkit
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers);
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers, this.seenBy); // Paper
this.entity = entity;
this.range = range;
this.lastSectionPos = SectionPos.of(entity);
@@ -1297,24 +_,47 @@
@@ -1325,24 +_,47 @@
}
public void removePlayer(ServerPlayer player) {
@@ -356,7 +355,7 @@
}
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
@@ -1331,6 +_,7 @@
@@ -1359,6 +_,7 @@
for (Entity entity : this.entity.getIndirectPassengers()) {
int i1 = entity.getType().clientTrackingRange() * 16;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/DistanceManager.java
+++ b/net/minecraft/server/level/DistanceManager.java
@@ -107,6 +_,12 @@
@@ -72,6 +_,12 @@
}
if (!this.chunksToUpdateFutures.isEmpty()) {
@@ -13,51 +13,7 @@
for (ChunkHolder chunkHolder : this.chunksToUpdateFutures) {
chunkHolder.updateHighestAllowedStatus(chunkMap);
}
@@ -177,16 +_,42 @@
public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
long packedChunkPos = pos.toLong();
- this.addTicket(packedChunkPos, ticket);
+ this.addTicket(packedChunkPos, ticket); // Paper - diff on change above
this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
}
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
long packedChunkPos = pos.toLong();
+ this.removeTicket(packedChunkPos, ticket); // Paper - diff on change above
+ this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
+ }
+
+ // Paper start
+ public boolean addPluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
+ final long packedChunkPos = pos.toLong();
+ final Set<Ticket<?>> tickets = this.getTickets(packedChunkPos);
+ if (tickets.contains(ticket)) {
+ return false;
+ }
+ this.addTicket(packedChunkPos, ticket);
+ this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
+ return true;
+ }
+
+ public boolean removePluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
+ final long packedChunkPos = pos.toLong();
+ final Set<Ticket<?>> tickets = this.tickets.get(packedChunkPos); // Don't use getTickets, we don't want to create a new set
+ if (tickets == null || !tickets.contains(ticket)) {
+ return false;
+ }
this.removeTicket(packedChunkPos, ticket);
this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
+ return true;
}
+ // Paper end
private SortedArraySet<Ticket<?>> getTickets(long chunkPos) {
return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4));
@@ -217,8 +_,10 @@
@@ -121,8 +_,10 @@
ChunkPos chunkPos = sectionPos.chunk();
long packedChunkPos = chunkPos.toLong();
ObjectSet<ServerPlayer> set = this.playersPerChunk.get(packedChunkPos);
@@ -70,39 +26,3 @@
this.playersPerChunk.remove(packedChunkPos);
this.naturalSpawnChunkCounter.update(packedChunkPos, Integer.MAX_VALUE, false);
this.playerTicketManager.update(packedChunkPos, Integer.MAX_VALUE, false);
@@ -299,7 +_,7 @@
}
public void removeTicketsOnClosing() {
- ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN);
+ ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectIterator = this.tickets.long2ObjectEntrySet().fastIterator();
while (objectIterator.hasNext()) {
@@ -329,6 +_,26 @@
public boolean hasTickets() {
return !this.tickets.isEmpty();
}
+
+ // CraftBukkit start
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
+
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
+ if (tickets.remove(target)) {
+ // copied from removeTicket
+ this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
+
+ // can't use entry after it's removed
+ if (tickets.isEmpty()) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ // CraftBukkit end
class ChunkTicketTracker extends ChunkTracker {
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -73,6 +_,13 @@
@@ -77,6 +_,13 @@
@Nullable
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
@@ -14,7 +14,7 @@
public ServerChunkCache(
ServerLevel level,
@@ -121,6 +_,64 @@
@@ -127,6 +_,64 @@
this.clearCache();
}
@@ -46,12 +46,12 @@
+ return holder.getLatestChunk();
+ }
+
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
+ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
+ this.ticketStorage.addTicket(new Ticket(ticketType, ticketLevel), chunkPos);
+ }
+
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
+ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
+ this.ticketStorage.removeTicket(new Ticket(ticketType, ticketLevel), chunkPos);
+ }
+
+ // "real" get chunk if loaded
@@ -79,7 +79,7 @@
@Override
public ThreadedLevelLightEngine getLightEngine() {
return this.lightEngine;
@@ -160,7 +_,7 @@
@@ -166,7 +_,7 @@
for (int i = 0; i < 4; i++) {
if (packedChunkPos == this.lastChunkPos[i] && chunkStatus == this.lastChunkStatus[i]) {
ChunkAccess chunkAccess = this.lastChunk[i];
@@ -88,7 +88,7 @@
return chunkAccess;
}
}
@@ -169,6 +_,7 @@
@@ -175,6 +_,7 @@
profilerFiller.incrementCounter("getChunkCacheMiss");
CompletableFuture<ChunkResult<ChunkAccess>> chunkFutureMainThread = this.getChunkFutureMainThread(x, z, chunkStatus, requireChunk);
this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone);
@@ -96,7 +96,7 @@
ChunkResult<ChunkAccess> chunkResult = chunkFutureMainThread.join();
ChunkAccess chunkAccess1 = chunkResult.orElse(null);
if (chunkAccess1 == null && requireChunk) {
@@ -240,7 +_,15 @@
@@ -246,7 +_,15 @@
long packedChunkPos = chunkPos.toLong();
int i = ChunkLevel.byStatus(chunkStatus);
ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(packedChunkPos);
@@ -109,11 +109,11 @@
+ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
+ }
+ if (requireChunk && !currentlyUnloading) {
+ // CraftBukkit end
this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos);
+ // CraftBukkit end
this.addTicket(new Ticket(TicketType.UNKNOWN, i), chunkPos);
if (this.chunkAbsent(visibleChunkIfPresent, i)) {
ProfilerFiller profilerFiller = Profiler.get();
@@ -260,7 +_,7 @@
@@ -266,7 +_,7 @@
}
private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) {
@@ -122,16 +122,7 @@
}
@Override
@@ -287,7 +_,7 @@
return this.mainThreadProcessor.pollTask();
}
- boolean runDistanceManagerUpdates() {
+ public boolean runDistanceManagerUpdates() { // Paper - public
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
boolean flag1 = this.chunkMap.promoteChunkMap();
this.chunkMap.runGenerationTasks();
@@ -315,17 +_,39 @@
@@ -321,17 +_,39 @@
@Override
public void close() throws IOException {
@@ -155,7 +146,7 @@
+ ProfilerFiller gameprofilerfiller = Profiler.get();
+
+ gameprofilerfiller.push("purge");
+ this.distanceManager.purgeStaleTickets();
+ this.ticketStorage.purgeStaleTickets();
+ this.runDistanceManagerUpdates();
+ gameprofilerfiller.popPush("unload");
+ this.chunkMap.tick(() -> true);
@@ -170,10 +161,10 @@
profilerFiller.push("purge");
- if (this.level.tickRateManager().runsNormally() || !tickChunks) {
+ if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
this.distanceManager.purgeStaleTickets();
this.ticketStorage.purgeStaleTickets();
}
@@ -400,12 +_,20 @@
@@ -388,12 +_,20 @@
);
this.lastSpawnState = spawnState;
profiler.popPush("spawnAndTick");
@@ -197,16 +188,7 @@
} else {
filteredSpawningCategories = List.of();
}
@@ -413,7 +_,7 @@
for (LevelChunk levelChunk : chunks) {
ChunkPos pos = levelChunk.getPos();
levelChunk.incrementInhabitedTime(timeInhabited);
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos)) {
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
}
@@ -526,8 +_,13 @@
@@ -544,8 +_,13 @@
@Override
public void setSpawnSettings(boolean spawnSettings) {
@@ -221,7 +203,7 @@
}
public String getChunkDebugData(ChunkPos chunkPos) {
@@ -603,12 +_,18 @@
@@ -618,12 +_,18 @@
@Override
public boolean pollTask() {

Some files were not shown because too many files have changed in this diff Show More