Merge remote-tracking branch 'upstream/main' into update/1.21.4
This commit is contained in:
@@ -21,10 +21,6 @@ paperweight {
|
||||
// macheOldPath = file("F:\\Projects\\PaperTooling\\mache\\versions\\1.21.4\\src\\main\\java")
|
||||
// gitFilePatches = true
|
||||
|
||||
paper {
|
||||
reobfMappingsPatch = layout.projectDirectory.file("../build-data/reobf-mappings-patch.tiny")
|
||||
}
|
||||
|
||||
spigot {
|
||||
buildDataRef = "3edaf46ec1eed4115ce1b18d2846cded42577e42"
|
||||
packageVersion = "v1_21_R3" // also needs to be updated in MappingEnvironment
|
||||
@@ -124,7 +120,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":paper-api"))
|
||||
implementation("ca.spottedleaf:concurrentutil:0.0.2")
|
||||
implementation("ca.spottedleaf:concurrentutil:0.0.3")
|
||||
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
|
||||
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
|
||||
implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
||||
@@ -141,13 +137,14 @@ dependencies {
|
||||
runtimeOnly(log4jPlugins.output)
|
||||
alsoShade(log4jPlugins.output)
|
||||
|
||||
implementation("com.velocitypowered:velocity-native:3.3.0-SNAPSHOT") {
|
||||
implementation("com.velocitypowered:velocity-native:3.4.0-SNAPSHOT") {
|
||||
isTransitive = false
|
||||
}
|
||||
implementation("io.netty:netty-codec-haproxy:4.1.97.Final") // Add support for proxy protocol
|
||||
implementation("io.netty:netty-codec-haproxy:4.1.115.Final") // Add support for proxy protocol
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.24.1")
|
||||
implementation("org.ow2.asm:asm-commons:9.7.1")
|
||||
implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT")
|
||||
implementation("org.spongepowered:configurate-yaml:4.2.0-20250225.064233-199")
|
||||
implementation("org.spongepowered:configurate-core:4.2.0-20250225.064233-204") // Pinned dependency of above pinned yaml snapshot.
|
||||
implementation("commons-lang:commons-lang:2.6")
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.47.0.0")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:9.1.0")
|
||||
@@ -177,7 +174,7 @@ dependencies {
|
||||
|
||||
// Spark
|
||||
implementation("me.lucko:spark-api:0.1-20240720.200737-2")
|
||||
implementation("me.lucko:spark-paper:1.10.119-SNAPSHOT")
|
||||
implementation("me.lucko:spark-paper:1.10.119-20241121.092015-1")
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
|
||||
@@ -28,7 +28,7 @@ and then catch exceptions and close if they fire.
|
||||
Part of this commit was authored by: Spottedleaf, sandtechnology
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..ad8f8428b75e37097487cdfbd0db2421ee4cbe37 100644
|
||||
index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42eafb96fa1 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -85,7 +85,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -232,7 +232,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..ad8f8428b75e37097487cdfbd0db2421
|
||||
// Paper start - Add PlayerConnectionCloseEvent
|
||||
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
|
||||
/* Player was logged in, either game listener or configuration listener */
|
||||
@@ -797,4 +888,93 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -797,4 +888,97 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public void setBandwidthLogger(LocalSampleLogger bandwithLogger) {
|
||||
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwithLogger);
|
||||
}
|
||||
@@ -280,6 +280,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..ad8f8428b75e37097487cdfbd0db2421
|
||||
+ packet instanceof net.minecraft.network.protocol.common.ClientboundKeepAlivePacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSystemChatPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundDisguisedChatPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket ||
|
||||
@@ -290,7 +291,10 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..ad8f8428b75e37097487cdfbd0db2421
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSoundEntityPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundStopSoundPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket;
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket ||
|
||||
+ packet instanceof net.minecraft.network.protocol.ping.ClientboundPongResponsePacket;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -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..bd888ef719b9bfc93bace0b1d0fb771ac659f515
|
||||
index 0000000000000000000000000000000000000000..ade6110cc6adb1263c0359ff7e96e96b959e61f3
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
@@ -0,0 +1,318 @@
|
||||
@@ -105,10 +105,10 @@ index 0000000000000000000000000000000000000000..bd888ef719b9bfc93bace0b1d0fb771a
|
||||
+ * @return boolean If it should always tick.
|
||||
+ */
|
||||
+ public static boolean initializeEntityActivationState(final Entity entity, final SpigotWorldConfig config) {
|
||||
+ return (entity.activationType == ActivationType.MISC && config.miscActivationRange == 0)
|
||||
+ || (entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0)
|
||||
+ || (entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0)
|
||||
+ || (entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0)
|
||||
+ return (entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0)
|
||||
+ || (entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0)
|
||||
@@ -366,7 +366,7 @@ index d95413af04121fe91ca0f3b0c70025b9808acef9..ad665c7535c615d2b03a3e7864be435f
|
||||
import org.slf4j.Logger;
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 3164f3784131babf9a6663335517a12df7e88a7b..da8848e2a3e3745949eb2356a049451d30f763a7 100644
|
||||
index f45fb8ddb08d82ce76018b5a5c4fce5b3b319559..12f0dc36c5adcdbd9e1dad5f8512ac184da3960f 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
|
||||
@@ -377,8 +377,8 @@ index 3164f3784131babf9a6663335517a12df7e88a7b..da8848e2a3e3745949eb2356a049451d
|
||||
this.entityTickList
|
||||
.forEach(
|
||||
entity -> {
|
||||
@@ -979,12 +980,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
entity.tickCount++;
|
||||
@@ -980,12 +981,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");
|
||||
+ final boolean isActive = io.papermc.paper.entity.activation.ActivationRange.checkIfActive(entity); // Paper - EAR 2
|
||||
@@ -394,7 +394,7 @@ index 3164f3784131babf9a6663335517a12df7e88a7b..da8848e2a3e3745949eb2356a049451d
|
||||
}
|
||||
// Paper start - log detailed entity tick information
|
||||
} finally {
|
||||
@@ -995,7 +999,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -996,7 +1000,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Paper end - log detailed entity tick information
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ index 3164f3784131babf9a6663335517a12df7e88a7b..da8848e2a3e3745949eb2356a049451d
|
||||
if (passengerEntity.isRemoved() || passengerEntity.getVehicle() != ridingEntity) {
|
||||
passengerEntity.stopRiding();
|
||||
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
|
||||
@@ -1004,12 +1008,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1006,12 +1010,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");
|
||||
@@ -476,12 +476,12 @@ 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 e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c9837b2c7823 100644
|
||||
index 2facc7ad69bfe28c2f928a026ba5ab37387ab039..6256d7f8f4ee8bd4e3673b4e069af5cc0069c8f2 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -380,6 +380,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
public boolean fixedPose = false; // Paper - Expand Pose API
|
||||
@@ -381,6 +381,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
|
||||
+ // Paper start - EAR 2
|
||||
+ public final boolean defaultActivationState;
|
||||
@@ -495,7 +495,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983
|
||||
|
||||
public void setOrigin(@javax.annotation.Nonnull org.bukkit.Location location) {
|
||||
this.origin = location.toVector();
|
||||
@@ -417,6 +426,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -414,6 +423,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.position = Vec3.ZERO;
|
||||
this.blockPosition = BlockPos.ZERO;
|
||||
this.chunkPosition = ChunkPos.ZERO;
|
||||
@@ -509,7 +509,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983
|
||||
SynchedEntityData.Builder builder = new SynchedEntityData.Builder(this);
|
||||
builder.define(DATA_SHARED_FLAGS_ID, (byte)0);
|
||||
builder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply());
|
||||
@@ -981,6 +997,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -978,6 +994,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
} else {
|
||||
this.wasOnFire = this.isOnFire();
|
||||
if (type == MoverType.PISTON) {
|
||||
@@ -518,7 +518,7 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983
|
||||
movement = this.limitPistonMovement(movement);
|
||||
if (movement.equals(Vec3.ZERO)) {
|
||||
return;
|
||||
@@ -994,6 +1012,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -991,6 +1009,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.stuckSpeedMultiplier = Vec3.ZERO;
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
}
|
||||
@@ -533,10 +533,10 @@ index e7889c9c7b155db46730f5e168bb7fd3d1732a8c..334859c5ff7023c730513301cc11c983
|
||||
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 ff513e8c87bf42be756e46f4dbfec8dda2b8cb60..239c443ddc9bacc08a39a8ef2ab17016a2480549 100644
|
||||
index e0c310d970a687945b6a771b4ecb94044128c33c..4546aca8e2e144ec207653c713fc49f849908827 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3096,6 +3096,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
@@ -3103,6 +3103,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ index ff513e8c87bf42be756e46f4dbfec8dda2b8cb60..239c443ddc9bacc08a39a8ef2ab17016
|
||||
public void tick() {
|
||||
super.tick();
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index f7d69db61d1293510428ae275e8a50571dde5ddf..1ed07fd23985a6bf8cf8300f74c92b7531a79fc6 100644
|
||||
index e12b47ca5eeb842bae606c0c7a8e3e4cf7d468a9..e330bf990e4874baed1b21cd8c9b44d66ec5b823 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
|
||||
@@ -764,7 +764,7 @@ 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 7c0862c50b44555fb27ce7dc46f4ec95a3eb0022..774ca9e0b56fd175ae246051de762d0c4256ca58 100644
|
||||
index a3e4605a81eeaca77cc3a3ab937b75a415d83037..c7ae41b2cbc1eb85a6eb9c16813bd326fb8f49f0 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 {
|
||||
@@ -776,11 +776,11 @@ index 7c0862c50b44555fb27ce7dc46f4ec95a3eb0022..774ca9e0b56fd175ae246051de762d0c
|
||||
+ public void inactiveTick() {
|
||||
+ this.life++;
|
||||
+ if (this.life > this.lifetime && this.level() instanceof ServerLevel serverLevel) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
+ }
|
||||
+ super.inactiveTick();
|
||||
+ }
|
||||
@@ -845,7 +845,7 @@ index 32f184288f6065259c921293922c1b0163df4dc4..0f346faa82b988e86834c38837f6f11b
|
||||
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 754cfdcd5a28287aa3545aaffdce1e391cbefc1e..1e6e940fca9d96ef410c7bf05524bd9b24db4a79 100644
|
||||
index ce880bd45fbda4829d17de8507034b3a39c68cbb..ee2f8e8deb35059824b5730a1442f383dc79f01c 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 {
|
||||
|
||||
@@ -14,7 +14,7 @@ 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 334859c5ff7023c730513301cc11c9837b2c7823..45f69a914d5a0565196c4105d61541047301470f 100644
|
||||
index 054ece1d539d69a4b7eec57e681179343c7e75c3..6f35067c64f378e955261e763f2bda9a0a6d0153 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
|
||||
@@ -22,7 +22,7 @@ index 334859c5ff7023c730513301cc11c9837b2c7823..45f69a914d5a0565196c4105d6154104
|
||||
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
||||
|
||||
+ public boolean collisionLoadChunks = false; // Paper
|
||||
private org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
|
||||
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
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 22 Aug 2021 15:21:57 -0700
|
||||
Subject: [PATCH] Fix entity type tags suggestions in selectors
|
||||
|
||||
This would really be better as a client fix because just to fix it
|
||||
all EntityArguments have been told to ask the server for completions
|
||||
when if this was fixed on the client, that wouldn't be needed.
|
||||
|
||||
Mojira Issue: https://bugs.mojang.com/browse/MC-235045
|
||||
|
||||
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
|
||||
index 704a63890a06d793f8ac3452838917e7c7335232..75262c8c9eaecb4a88a94f4076d67119c67a97da 100644
|
||||
--- a/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -652,4 +652,20 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
|
||||
return this.source.getBukkitSender(this);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
|
||||
+ @Override
|
||||
+ public Collection<String> getSelectedEntities() {
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && this.source instanceof ServerPlayer player) {
|
||||
+ final Entity cameraEntity = player.getCamera();
|
||||
+ final double pickDistance = player.entityInteractionRange();
|
||||
+ final Vec3 min = cameraEntity.getEyePosition(1.0F);
|
||||
+ final Vec3 viewVector = cameraEntity.getViewVector(1.0F);
|
||||
+ final Vec3 max = min.add(viewVector.x * pickDistance, viewVector.y * pickDistance, viewVector.z * pickDistance);
|
||||
+ final net.minecraft.world.phys.AABB aabb = cameraEntity.getBoundingBox().expandTowards(viewVector.scale(pickDistance)).inflate(1.0D, 1.0D, 1.0D);
|
||||
+ final net.minecraft.world.phys.EntityHitResult hitResult = net.minecraft.world.entity.projectile.ProjectileUtil.getEntityHitResult(cameraEntity, min, max, aabb, (e) -> !e.isSpectator() && e.isPickable(), pickDistance * pickDistance);
|
||||
+ return hitResult != null ? java.util.Collections.singletonList(hitResult.getEntity().getStringUUID()) : SharedSuggestionProvider.super.getSelectedEntities();
|
||||
+ }
|
||||
+ return SharedSuggestionProvider.super.getSelectedEntities();
|
||||
+ }
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
}
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index fa8c5ba4e0efd0c36613aaa8eaafba0cb70ceb87..19ccf3abf14c67f72a1ca065e4a304f50e645ef4 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -509,6 +509,7 @@ public class Commands {
|
||||
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode
|
||||
) {
|
||||
commandNodeToSuggestionNode.keySet().removeIf((node) -> !org.spigotmc.SpigotConfig.sendNamespaced && node.getName().contains(":")); // Paper - Remove namedspaced from result nodes to prevent redirect trimming ~ see comment below
|
||||
+ boolean registeredAskServerSuggestionsForTree = false; // Paper - tell clients to ask server for suggestions for EntityArguments
|
||||
for (CommandNode<CommandSourceStack> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
|
||||
// Paper start - Brigadier API
|
||||
if (commandNode.clientNode != null) {
|
||||
@@ -572,6 +573,12 @@ public class Commands {
|
||||
RequiredArgumentBuilder<SharedSuggestionProvider, ?> requiredArgumentBuilder = (RequiredArgumentBuilder<SharedSuggestionProvider, ?>)argumentBuilder;
|
||||
if (requiredArgumentBuilder.getSuggestionsProvider() != null) {
|
||||
requiredArgumentBuilder.suggests(SuggestionProviders.safelySwap(requiredArgumentBuilder.getSuggestionsProvider()));
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
|
||||
+ registeredAskServerSuggestionsForTree = requiredArgumentBuilder.getSuggestionsProvider() == net.minecraft.commands.synchronization.SuggestionProviders.ASK_SERVER;
|
||||
+ } else if (io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && !registeredAskServerSuggestionsForTree && requiredArgumentBuilder.getType() instanceof net.minecraft.commands.arguments.EntityArgument) {
|
||||
+ requiredArgumentBuilder.suggests(requiredArgumentBuilder.getType()::listSuggestions);
|
||||
+ registeredAskServerSuggestionsForTree = true; // You can only
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/commands/arguments/EntityArgument.java b/net/minecraft/commands/arguments/EntityArgument.java
|
||||
index 0a01df6ebd14afe79bc76364cb1df5e0c5c08074..7a06ad9940d25e163178370bfa9ccc3bbd3d1189 100644
|
||||
--- a/net/minecraft/commands/arguments/EntityArgument.java
|
||||
+++ b/net/minecraft/commands/arguments/EntityArgument.java
|
||||
@@ -138,7 +138,7 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
final boolean permission = sharedSuggestionProvider instanceof CommandSourceStack stack
|
||||
? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector")
|
||||
: sharedSuggestionProvider.hasPermission(2);
|
||||
- EntitySelectorParser entitySelectorParser = new EntitySelectorParser(stringReader, permission);
|
||||
+ EntitySelectorParser entitySelectorParser = new EntitySelectorParser(stringReader, permission, true); // Paper - tell clients to ask server for suggestions for EntityArguments
|
||||
// Paper end - Fix EntityArgument permissions
|
||||
|
||||
try {
|
||||
@@ -149,7 +149,19 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
return entitySelectorParser.fillSuggestions(
|
||||
builder,
|
||||
offsetBuilder -> {
|
||||
- Collection<String> onlinePlayerNames = sharedSuggestionProvider.getOnlinePlayerNames();
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
|
||||
+ final Collection<String> onlinePlayerNames;
|
||||
+ if (sharedSuggestionProvider instanceof CommandSourceStack commandSourceStack && commandSourceStack.getEntity() instanceof ServerPlayer sourcePlayer) {
|
||||
+ onlinePlayerNames = new java.util.ArrayList<>();
|
||||
+ for (final ServerPlayer player : commandSourceStack.getServer().getPlayerList().getPlayers()) {
|
||||
+ if (sourcePlayer.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
+ onlinePlayerNames.add(player.getGameProfile().getName());
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ onlinePlayerNames = sharedSuggestionProvider.getOnlinePlayerNames();
|
||||
+ }
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
Iterable<String> iterable = (Iterable<String>)(this.playersOnly
|
||||
? onlinePlayerNames
|
||||
: Iterables.concat(onlinePlayerNames, sharedSuggestionProvider.getSelectedEntities()));
|
||||
diff --git a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
|
||||
index a6f232747df631f6afe440606bea94c588f1a0dd..fb42630741674c6cbd20b7d45d78dea1dc73a78f 100644
|
||||
--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
|
||||
@@ -115,8 +115,15 @@ public class EntitySelectorParser {
|
||||
private boolean hasScores;
|
||||
private boolean hasAdvancements;
|
||||
private boolean usesSelectors;
|
||||
+ public boolean parsingEntityArgumentSuggestions; // Paper - tell clients to ask server for suggestions for EntityArguments
|
||||
|
||||
public EntitySelectorParser(StringReader reader, boolean allowSelectors) {
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
|
||||
+ this(reader, allowSelectors, false);
|
||||
+ }
|
||||
+ public EntitySelectorParser(StringReader reader, boolean allowSelectors, boolean parsingEntityArgumentSuggestions) {
|
||||
+ this.parsingEntityArgumentSuggestions = parsingEntityArgumentSuggestions;
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
this.reader = reader;
|
||||
this.allowSelectors = allowSelectors;
|
||||
}
|
||||
diff --git a/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java b/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
index f6b58139aace70436034f0a16370236d975cb4ae..ee9949c41d38817b21b6f4fd728059a46fddf135 100644
|
||||
--- a/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
@@ -76,6 +76,19 @@ public class EntitySelectorOptions {
|
||||
public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType(
|
||||
type -> Component.translatableEscape("argument.entity.options.type.invalid", type)
|
||||
);
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments
|
||||
+ public static final DynamicCommandExceptionType ERROR_ENTITY_TAG_INVALID = new DynamicCommandExceptionType((object) -> {
|
||||
+ return io.papermc.paper.adventure.PaperAdventure
|
||||
+ .asVanilla(net.kyori.adventure.text.Component
|
||||
+ .text("Invalid or unknown entity type tag '" + object + "'")
|
||||
+ .hoverEvent(net.kyori.adventure.text.event.HoverEvent
|
||||
+ .showText(net.kyori.adventure.text.Component
|
||||
+ .text("You can disable this error in 'paper.yml'")
|
||||
+ )
|
||||
+ )
|
||||
+ );
|
||||
+ });
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
|
||||
private static void register(String id, EntitySelectorOptions.Modifier handler, Predicate<EntitySelectorParser> predicate, Component tooltip) {
|
||||
OPTIONS.put(id, new EntitySelectorOptions.Option(handler, predicate, tooltip));
|
||||
@@ -299,6 +312,12 @@ public class EntitySelectorOptions {
|
||||
|
||||
if (parser.isTag()) {
|
||||
TagKey<EntityType<?>> tagKey = TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.read(parser.getReader()));
|
||||
+ // Paper start - tell clients to ask server for suggestions for EntityArguments; throw error if invalid entity tag (only on suggestions to keep cmd success behavior)
|
||||
+ if (parser.parsingEntityArgumentSuggestions && io.papermc.paper.configuration.GlobalConfiguration.get().commands.fixTargetSelectorTagCompletion && net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(tagKey).isEmpty()) {
|
||||
+ parser.getReader().setCursor(cursor);
|
||||
+ throw ERROR_ENTITY_TAG_INVALID.createWithContext(parser.getReader(), tagKey);
|
||||
+ }
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
parser.addPredicate(entity -> entity.getType().is(tagKey) != shouldInvertValue);
|
||||
} else {
|
||||
ResourceLocation resourceLocation = ResourceLocation.read(parser.getReader());
|
||||
@@ -30621,7 +30621,7 @@ index 1110ca4075a1bbaa46b66686435dab91b275c945..c2218630c3074c8b3f82364e37503b12
|
||||
return structureTemplate.save(new CompoundTag());
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 0d65bf24f515b80701150fdc430f324a533cb478..b92a3da5c325e69f5601416d4205fb33429742b3 100644
|
||||
index e54b5a165ad4dc4d2158dab34c5008512e5f7885..841a41485af62470d833aba578069b19a0bd1e8d 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -23552,7 +23552,7 @@ index 2b46ca9a2a046063cad422bec00d76107537b091..9aa664537cc37e44db46d5a2a64ae311
|
||||
thread1 -> {
|
||||
DedicatedServer dedicatedServer1 = new DedicatedServer(
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index b92a3da5c325e69f5601416d4205fb33429742b3..d967d605c2e4227ae980c30f1c8b86edbc680d6d 100644
|
||||
index 841a41485af62470d833aba578069b19a0bd1e8d..409c1134327bfcc338c3ac5e658a83cc396645d1 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2;
|
||||
@@ -23737,7 +23737,7 @@ index b92a3da5c325e69f5601416d4205fb33429742b3..d967d605c2e4227ae980c30f1c8b86ed
|
||||
return true;
|
||||
} else {
|
||||
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
@@ -2472,6 +2554,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2473,6 +2555,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23751,7 +23751,7 @@ index b92a3da5c325e69f5601416d4205fb33429742b3..d967d605c2e4227ae980c30f1c8b86ed
|
||||
// CraftBukkit start
|
||||
public boolean isDebugging() {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index f8c81d795b19e73d56d6e0196c75e441ab4c2bef..97a294d2f5c1ddf0af7ffec3e1425eb329c5751b 100644
|
||||
index ac7bc193f7ea63cbbba73df49f54a17ef7cdec40..d2db6e3a4af13984b0a790fb38e83c253914a973 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -433,7 +433,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
@@ -26735,7 +26735,7 @@ index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7d
|
||||
if (!passengers.equals(this.lastPassengers)) {
|
||||
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521cd46fbb6f 100644
|
||||
index d1f235ebd835f58cf0c703c3a64d29825d98e183..080091efc19bc768bb9a660f366c42e831225505 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -170,7 +170,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
@@ -27305,7 +27305,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
// Paper start - log detailed entity tick information
|
||||
@@ -1033,6 +1316,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1035,6 +1318,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
|
||||
public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
|
||||
@@ -27317,7 +27317,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
ServerChunkCache chunkSource = this.getChunkSource();
|
||||
if (!skipSave) {
|
||||
org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld())); // CraftBukkit
|
||||
@@ -1045,13 +1333,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1047,13 +1335,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
progress.progressStage(Component.translatable("menu.savingChunks"));
|
||||
}
|
||||
|
||||
@@ -27341,7 +27341,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
|
||||
// CraftBukkit start - moved from MinecraftServer.saveChunks
|
||||
ServerLevel worldserver1 = this;
|
||||
@@ -1182,7 +1475,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1184,7 +1477,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.removePlayerImmediately((ServerPlayer)entity, Entity.RemovalReason.DISCARDED);
|
||||
}
|
||||
|
||||
@@ -27350,7 +27350,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -1213,7 +1506,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1215,7 +1508,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -27359,7 +27359,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,7 +1517,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1226,7 +1519,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
|
||||
public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
// CraftBukkit end
|
||||
@@ -27368,7 +27368,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
return false;
|
||||
} else {
|
||||
this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
|
||||
@@ -1959,7 +2252,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1961,7 +2254,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27377,7 +27377,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
bufferedWriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size()));
|
||||
bufferedWriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count()));
|
||||
bufferedWriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count()));
|
||||
@@ -1977,13 +2270,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1979,13 +2272,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
Path path1 = path.resolve("chunks.csv");
|
||||
|
||||
try (Writer bufferedWriter2 = Files.newBufferedWriter(path1)) {
|
||||
@@ -27393,7 +27393,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
Path path3 = path.resolve("entities.csv");
|
||||
@@ -2092,8 +2385,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2094,8 +2387,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
Locale.ROOT,
|
||||
"players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s",
|
||||
this.players.size(),
|
||||
@@ -27404,7 +27404,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
this.blockEntityTickers.size(),
|
||||
getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType),
|
||||
this.getBlockTicks().count(),
|
||||
@@ -2125,15 +2418,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2127,15 +2420,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
|
||||
@@ -27433,7 +27433,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
public void startTickingChunk(LevelChunk chunk) {
|
||||
@@ -2151,32 +2454,45 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2153,32 +2456,45 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
@@ -27486,7 +27486,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2230,7 +2546,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2232,7 +2548,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@Override
|
||||
public CrashReportCategory fillReportDetails(CrashReport report) {
|
||||
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
|
||||
@@ -27496,7 +27496,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 097ec55166b9e9269142be58992c29687122fe28..aeabb79512aabd7a9e8af1be72e1745f0e7eefe4 100644
|
||||
index 0bb610f12e3ddda649ecb5ad62ffdc7bfd243223..19428343b37c9b739b3d28984d52e257f85f253f 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team;
|
||||
@@ -27508,7 +27508,7 @@ index 097ec55166b9e9269142be58992c29687122fe28..aeabb79512aabd7a9e8af1be72e1745f
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||
@@ -388,6 +388,36 @@ public class ServerPlayer extends Player {
|
||||
@@ -395,6 +395,36 @@ public class ServerPlayer extends Player {
|
||||
public @Nullable String clientBrandName = null; // Paper - Brand support
|
||||
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
|
||||
|
||||
@@ -27976,10 +27976,10 @@ index 4eb040006f5d41b47e5ac9df5d9f19c4315d6343..7fa41dea184b01891f45d8e404bc1cba
|
||||
this.generatingStep = generatingStep;
|
||||
this.cache = cache;
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index ff0315cffdb282fdc0a1ffd15e2954caa76835c9..5e94dd9e26aa4fd6545dbaae2ae0cb51cb6f13e0 100644
|
||||
index 7eebb494e38b57e81b4f92f0a96d3a4c610d86df..065f4c810439dde464529b54ae300ecfcb1c2c31 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1312,7 +1312,7 @@ public abstract class PlayerList {
|
||||
@@ -1317,7 +1317,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setViewDistance(int viewDistance) {
|
||||
this.viewDistance = viewDistance;
|
||||
@@ -27988,7 +27988,7 @@ index ff0315cffdb282fdc0a1ffd15e2954caa76835c9..5e94dd9e26aa4fd6545dbaae2ae0cb51
|
||||
|
||||
for (ServerLevel serverLevel : this.server.getAllLevels()) {
|
||||
if (serverLevel != null) {
|
||||
@@ -1323,7 +1323,7 @@ public abstract class PlayerList {
|
||||
@@ -1328,7 +1328,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setSimulationDistance(int simulationDistance) {
|
||||
this.simulationDistance = simulationDistance;
|
||||
@@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
|
||||
+ // Paper end - block counting
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640c88fc282 100644
|
||||
index 9b3b770f6986dd132da78fdc3626d334166ec52a..b2b61203438bb1fad1ee807729781718d2467155 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
|
||||
@@ -28466,7 +28466,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
}
|
||||
// Paper end - Share random for entities to make them more random
|
||||
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
||||
@@ -419,6 +375,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -416,6 +372,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
return this.dimensions.makeBoundingBox(x, y, z);
|
||||
}
|
||||
// Paper end
|
||||
@@ -28623,7 +28623,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
|
||||
public Entity(EntityType<?> entityType, Level level) {
|
||||
this.type = entityType;
|
||||
@@ -1327,35 +1433,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -1324,35 +1430,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
return distance;
|
||||
}
|
||||
|
||||
@@ -28725,7 +28725,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
}
|
||||
|
||||
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
|
||||
@@ -2662,23 +2810,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -2659,23 +2807,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public boolean isInWall() {
|
||||
@@ -28849,7 +28849,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
}
|
||||
|
||||
public InteractionResult interact(Player player, InteractionHand hand) {
|
||||
@@ -4102,15 +4337,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4099,15 +4334,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public Iterable<Entity> getIndirectPassengers() {
|
||||
@@ -28875,7 +28875,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
}
|
||||
|
||||
public int countPlayerPassengers() {
|
||||
@@ -4248,77 +4485,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4245,77 +4482,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
return Mth.lerp(partialTick, this.yRotO, this.yRot);
|
||||
}
|
||||
|
||||
@@ -29066,7 +29066,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
|
||||
public boolean touchingUnloadedChunk() {
|
||||
AABB aabb = this.getBoundingBox().inflate(1.0);
|
||||
@@ -4471,6 +4767,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4468,6 +4764,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.setPosRaw(x, y, z, false);
|
||||
}
|
||||
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
|
||||
@@ -29082,7 +29082,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
if (!checkPosition(this, x, y, z)) {
|
||||
return;
|
||||
}
|
||||
@@ -4601,6 +4906,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4598,6 +4903,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
|
||||
@Override
|
||||
public final void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) {
|
||||
@@ -29095,7 +29095,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause);
|
||||
// CraftBukkit end
|
||||
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
|
||||
@@ -4612,7 +4923,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4609,7 +4920,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.stopRiding();
|
||||
}
|
||||
|
||||
@@ -29104,7 +29104,7 @@ index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640
|
||||
this.levelCallback.onRemove(removalReason);
|
||||
this.onRemoval(removalReason);
|
||||
// Paper start - Folia schedulers
|
||||
@@ -4646,7 +4957,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -4643,7 +4954,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
public boolean shouldBeSaved() {
|
||||
return (this.removalReason == null || this.removalReason.shouldSave())
|
||||
&& !this.isPassenger()
|
||||
@@ -29379,7 +29379,7 @@ index 9f34fc4278860dd7bcfa1fd79b15e588b0cc3973..a7ebd624652cb6f0edc735bf6b9760e7
|
||||
|
||||
public ClipContext(Vec3 from, Vec3 to, ClipContext.Block block, ClipContext.Fluid fluid, Entity entity) {
|
||||
diff --git a/net/minecraft/world/level/EntityGetter.java b/net/minecraft/world/level/EntityGetter.java
|
||||
index 300f3ed58109219d97846082941b860585f66fed..e81195df621159da67136f020fa7a6d39d1ee5ed 100644
|
||||
index 300f3ed58109219d97846082941b860585f66fed..892a7c1eb1b321ca6d5ca709142e7feae1220815 100644
|
||||
--- a/net/minecraft/world/level/EntityGetter.java
|
||||
+++ b/net/minecraft/world/level/EntityGetter.java
|
||||
@@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.BooleanOp;
|
||||
@@ -29397,14 +29397,6 @@ index 300f3ed58109219d97846082941b860585f66fed..e81195df621159da67136f020fa7a6d3
|
||||
|
||||
- default boolean isUnobstructed(@Nullable Entity entity, VoxelShape shape) {
|
||||
- if (shape.isEmpty()) {
|
||||
- return true;
|
||||
- } else {
|
||||
- for (Entity entity1 : this.getEntities(entity, shape.bounds())) {
|
||||
- if (!entity1.isRemoved()
|
||||
- && entity1.blocksBuilding
|
||||
- && (entity == null || !entity1.isPassengerOfSameVehicle(entity))
|
||||
- && Shapes.joinIsNotEmpty(shape, Shapes.create(entity1.getBoundingBox()), BooleanOp.AND)) {
|
||||
- return false;
|
||||
+ // Paper start - rewrite chunk system
|
||||
+ @Override
|
||||
+ default List<Entity> moonrise$getHardCollidingEntities(final Entity entity, final AABB box, final Predicate<? super Entity> predicate) {
|
||||
@@ -29415,7 +29407,14 @@ index 300f3ed58109219d97846082941b860585f66fed..e81195df621159da67136f020fa7a6d3
|
||||
+ // Paper start - optimise collisions
|
||||
+ default boolean isUnobstructed(@Nullable Entity entity, VoxelShape voxel) {
|
||||
+ if (voxel.isEmpty()) {
|
||||
+ return false;
|
||||
return true;
|
||||
- } else {
|
||||
- for (Entity entity1 : this.getEntities(entity, shape.bounds())) {
|
||||
- if (!entity1.isRemoved()
|
||||
- && entity1.blocksBuilding
|
||||
- && (entity == null || !entity1.isPassengerOfSameVehicle(entity))
|
||||
- && Shapes.joinIsNotEmpty(shape, Shapes.create(entity1.getBoundingBox()), BooleanOp.AND)) {
|
||||
- return false;
|
||||
+ }
|
||||
+
|
||||
+ final AABB singleAABB = ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation();
|
||||
@@ -29503,7 +29502,7 @@ index 300f3ed58109219d97846082941b860585f66fed..e81195df621159da67136f020fa7a6d3
|
||||
|
||||
// Paper start - Affects Spawning API
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 771d6ed6a7c889c09efd4ff6e20298c851eaa79f..8331b49185500ab3b4307e9ae05126b4f83a318a 100644
|
||||
index 771d6ed6a7c889c09efd4ff6e20298c851eaa79f..a768f041fd16d253ec4ab5eb75288b1771d5cb00 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -79,6 +79,7 @@ import net.minecraft.world.level.storage.LevelData;
|
||||
@@ -29673,7 +29672,7 @@ index 771d6ed6a7c889c09efd4ff6e20298c851eaa79f..8331b49185500ab3b4307e9ae05126b4
|
||||
+ public boolean isUnobstructed(final Entity entity) {
|
||||
+ final AABB boundingBox = entity.getBoundingBox();
|
||||
+ if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isEmpty(boundingBox)) {
|
||||
+ return false;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ final List<Entity> entities = this.getEntities(
|
||||
@@ -30419,7 +30418,7 @@ index 2709803b9266ff4a2034d83321cd0ba4e30fc0aa..26c8c1e5598daf3550aef05b12218c47
|
||||
ChunkAccess getChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk);
|
||||
|
||||
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
|
||||
index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc7ae35984 100644
|
||||
index 155bf7ccff5c1332fceda2598342bb03624608ff..c4485f28def66264846a436cfba7bddccb66b82e 100644
|
||||
--- a/net/minecraft/world/level/ServerExplosion.java
|
||||
+++ b/net/minecraft/world/level/ServerExplosion.java
|
||||
@@ -63,6 +63,249 @@ public class ServerExplosion implements Explosion {
|
||||
@@ -30867,7 +30866,7 @@ index 3619509d51ebd2e5e36fe4b67e76c94a8d272d1b..7b132c55caf9d3c3df3b0a123f4b5bfc
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/biome/Biome.java b/net/minecraft/world/level/biome/Biome.java
|
||||
index ea521e1d636b8ffdeb22882dfc8875b2ddbd8da1..7b666bbeefe296e7fdbadcc72dbf9e602f73e925 100644
|
||||
index 21b9021df95d3611ad17c9fd5f429f97e824ed2f..f44461f92a10cbfdb8fcdbc3a2442e526b9d3d33 100644
|
||||
--- a/net/minecraft/world/level/biome/Biome.java
|
||||
+++ b/net/minecraft/world/level/biome/Biome.java
|
||||
@@ -117,20 +117,7 @@ public final class Biome {
|
||||
@@ -33699,6 +33698,25 @@ index 342c83309b19c64d86e0dd97c1756c96be52772b..423779a2b690f387a4f0bd07b97b50e0
|
||||
+ // Paper end - rewrite chunk system
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/gameevent/DynamicGameEventListener.java b/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
|
||||
index 2b98932e69271571e6e9350c55c82edc858d76f6..c8980c50713e1526c526ed181fb2ad9486bab353 100644
|
||||
--- a/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
|
||||
+++ b/net/minecraft/world/level/gameevent/DynamicGameEventListener.java
|
||||
@@ -27,6 +27,14 @@ public class DynamicGameEventListener<T extends GameEventListener> {
|
||||
|
||||
public void remove(ServerLevel level) {
|
||||
ifChunkExists(level, this.lastSection, listenerRegistry -> listenerRegistry.unregister(this.listener));
|
||||
+ // Paper start - rewrite chunk system
|
||||
+ // We need to unset the last section when removed, otherwise if the same instance is re-added at the same position it
|
||||
+ // will assume there was no change and fail to re-register.
|
||||
+ // In vanilla, chunks rarely unload and re-load quickly enough to trigger this issue. However, our chunk system has a
|
||||
+ // quirk where fast chunk reload cycles will often occur on player login (see PR #22).
|
||||
+ // So we fix this vanilla oversight as our changes cause it to manifest in bugs much more often (see issue #87).
|
||||
+ this.lastSection = null;
|
||||
+ // Paper end - rewrite chunk system
|
||||
}
|
||||
|
||||
public void move(ServerLevel level) {
|
||||
diff --git a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
index 6d61739574155f89511b9adcaf1174841bdc7da7..65728ef17e63d71833677fdcbd5bb90794b4822b 100644
|
||||
--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
@@ -22,7 +22,7 @@ Alternate Current's wire handler.
|
||||
|
||||
diff --git a/alternate/current/wire/LevelHelper.java b/alternate/current/wire/LevelHelper.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..eda108e2df9bf7d1ddd89287b8d2c2d7f1637c96
|
||||
index 0000000000000000000000000000000000000000..ff663d3089627e75221aa128aff4bf5cc459addb
|
||||
--- /dev/null
|
||||
+++ b/alternate/current/wire/LevelHelper.java
|
||||
@@ -0,0 +1,66 @@
|
||||
@@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..eda108e2df9bf7d1ddd89287b8d2c2d7
|
||||
+ static boolean setWireState(ServerLevel level, BlockPos pos, BlockState state, boolean updateNeighborShapes) {
|
||||
+ int y = pos.getY();
|
||||
+
|
||||
+ if (y < level.getMinY() || y >= level.getMaxY()) {
|
||||
+ if (y < level.getMinY() || y > level.getMaxY()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
@@ -2326,7 +2326,7 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 95a4e37a3c93f9b3c56c7a7376ed521cd46fbb6f..46dfaed12c998c219a20c711a06531aed2c68012 100644
|
||||
index a293d1481b5f4a1d18addc3e518486c639223f09..5bf38ab129451e867b638cfbd2d7be59cbf7f38d 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
|
||||
@@ -2337,7 +2337,7 @@ index 95a4e37a3c93f9b3c56c7a7376ed521cd46fbb6f..46dfaed12c998c219a20c711a06531ae
|
||||
|
||||
public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
@@ -2555,6 +2556,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2557,6 +2558,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
return this.chunkSource.getGenerator().getSeaLevel();
|
||||
}
|
||||
|
||||
@@ -2352,7 +2352,7 @@ index 95a4e37a3c93f9b3c56c7a7376ed521cd46fbb6f..46dfaed12c998c219a20c711a06531ae
|
||||
@Override
|
||||
public void onCreated(Entity entity) {
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 8331b49185500ab3b4307e9ae05126b4f83a318a..2bbebb4335d927f240abcac67a5b423e38dc33d7 100644
|
||||
index a768f041fd16d253ec4ab5eb75288b1771d5cb00..1dbe7c7c1051c3972105534a07ce50d4cf98fc85 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
|
||||
@@ -8,7 +8,7 @@ This ensures at least a valid version of the chunk exists
|
||||
on disk, even if outdated
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 7da388ffab162c282cad0f297bb7304f3c2abbaf..ff4fc280409f680f3879a495e37cf1925b1a38f1 100644
|
||||
index 984db72272d552c7210bd6f437ea88694ddd2828..dea2823a9d1d69dcb0a4759d8ea9b3015ede20dc 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
|
||||
@@ -42,7 +42,7 @@ index 64a718c98f799c62a5bb28e1e8e5f66cc96c915d..666f2e967c99f78422c83fb20e1a3bf3
|
||||
this.used.set(sectorOffset, sectorOffset + sectorCount);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index ff4fc280409f680f3879a495e37cf1925b1a38f1..a4621c96fd456c5cdd1b6847931806e677b26b30 100644
|
||||
index dea2823a9d1d69dcb0a4759d8ea9b3015ede20dc..0c41177462cca5c4bbab6490e323b9535fd6300f 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -46,6 +46,355 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
@@ -699,7 +699,7 @@ 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 70a9972252576e039ac126f6057a6ed66b80cdfc..d783c3580ea274a0a9cb07449eb8037bc5a04d76 100644
|
||||
index 879d411775a2fece1d8a970300cb3a550baa6305..6b6aaeca14178b5b709e20ae13552d42217f15c0 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(
|
||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Incremental chunk and player saving
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index d967d605c2e4227ae980c30f1c8b86edbc680d6d..6dbae12bbfd47cd4e75bc3089561e8e226e9e604 100644
|
||||
index 409c1134327bfcc338c3ac5e658a83cc396645d1..cc2d442682496197d29ace79b22e6cf6fb7edf5e 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -960,7 +960,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -50,10 +50,10 @@ index d967d605c2e4227ae980c30f1c8b86edbc680d6d..6dbae12bbfd47cd4e75bc3089561e8e2
|
||||
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 46dfaed12c998c219a20c711a06531aed2c68012..ebeeb63c3dca505a3ce8b88feaa5d2ca20ec24a2 100644
|
||||
index 42995dac38248032b6abecc27124adfe12ec4cab..28a67294c3e678e01d5dfd68b950234213d8e55c 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1316,6 +1316,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1318,6 +1318,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ index 46dfaed12c998c219a20c711a06531aed2c68012..ebeeb63c3dca505a3ce8b88feaa5d2ca
|
||||
// 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 e61fe83479f095e8addbd3e8f1d5179c998ae1eb..0a7e5106a1d39150326e7c323030df5d32ecef1e 100644
|
||||
index f44600604a7bf68c990cd74a1ac2d7900ff6e88e..69b8074e18775c846d5991f40bc2e0a5186500ac 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -180,6 +180,7 @@ import org.slf4j.Logger;
|
||||
@@ -95,7 +95,7 @@ index e61fe83479f095e8addbd3e8f1d5179c998ae1eb..0a7e5106a1d39150326e7c323030df5d
|
||||
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 5e94dd9e26aa4fd6545dbaae2ae0cb51cb6f13e0..03feaf0adb8ee87e33744a4615dc2507a02f92d7 100644
|
||||
index 7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4..5a4960fdbd97d830ac79845697eea9372c48a13b 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -482,6 +482,7 @@ public abstract class PlayerList {
|
||||
@@ -78,10 +78,10 @@ index 87d4291a3944f706a694536da6de0f28c548ab8d..5576bf1d1d70ab7a010653d3207909b5
|
||||
profiler.popPush("spawnAndTick");
|
||||
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 0a7e5106a1d39150326e7c323030df5d32ecef1e..a63702dd7e86fc8b9f78c2ae23e23b65b6b2ee24 100644
|
||||
index 02fb30a3adf92de0795aee213caf94a228b01ca0..67f6e40216e0be063a3cfb61427f095f7c74d785 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -368,6 +368,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -375,6 +375,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public boolean queueHealthUpdatePacket;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
// Paper end - cancellable death event
|
||||
@@ -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 a63702dd7e86fc8b9f78c2ae23e23b65b6b2ee24..6d75a641431c7deb7e8ddbf02cdc919015a3a7dc 100644
|
||||
index 67f6e40216e0be063a3cfb61427f095f7c74d785..3de65c4025be91d938a350c884975cb6edc234d3 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -372,6 +372,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -379,6 +379,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
|
||||
@@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 6dbae12bbfd47cd4e75bc3089561e8e226e9e604..9c859025302ddb2c20cf6457fa4e4eaf7fbafdd7 100644
|
||||
index cc2d442682496197d29ace79b22e6cf6fb7edf5e..ae220a732c78ab076261f20b5a54c71d7fceb407 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1707,6 +1707,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1708,6 +1708,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 6dbae12bbfd47cd4e75bc3089561e8e226e9e604..9c859025302ddb2c20cf6457fa4e4eaf
|
||||
/* 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 c255e11cb0981bd7e0456d4fd401beb5257be597..d6361863d6a1e364de262d6199373cbd68d1c699 100644
|
||||
index b393be76bead3c66ab0bd8a0e6fd9b9ef81d8e28..76f50437396f8f856381d0fbef52953ef7c263f6 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -808,10 +808,16 @@ public final class ItemStack implements DataComponentHolder {
|
||||
@@ -827,10 +827,16 @@ public final class ItemStack implements DataComponentHolder {
|
||||
}
|
||||
|
||||
public ItemStack copy() {
|
||||
@@ -6,10 +6,10 @@ 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 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca078bad0b 100644
|
||||
index 12c83cb084563a4e3f7f357d8b600941544ef2b0..90e582ca30851857add5e2d830e9876667fd1807 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -561,7 +561,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -563,7 +563,7 @@ public class ServerGamePacketListenerImpl
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
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
|
||||
@@ -571,6 +571,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -573,6 +573,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
|
||||
@@ -26,7 +26,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
double verticalDelta = d4; // Paper - Decompile fix, was named d11 previously, is now gone in the source
|
||||
d3 = d - rootVehicle.getX();
|
||||
d4 = d1 - rootVehicle.getY();
|
||||
@@ -582,14 +583,22 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -584,14 +585,22 @@ public class ServerGamePacketListenerImpl
|
||||
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
boolean flag2 = false;
|
||||
if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
@@ -52,7 +52,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
rootVehicle.absMoveTo(x, y, z, f, f1);
|
||||
this.player.absMoveTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
||||
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
|
||||
@@ -667,9 +676,32 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -669,9 +678,32 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
private boolean noBlocksAround(Entity entity) {
|
||||
@@ -88,7 +88,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1361,7 +1393,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1371,7 +1403,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
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
|
||||
@@ -1400,6 +1432,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -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
|
||||
@@ -105,7 +105,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
// Paper start - prevent position desync
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
||||
@@ -1432,7 +1465,17 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1442,7 +1475,17 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
// Paper start - Add fail move event
|
||||
@@ -124,7 +124,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
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);
|
||||
@@ -1568,7 +1611,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1578,7 +1621,7 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
private boolean updateAwaitingTeleport() {
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
@@ -133,7 +133,7 @@ index 650126e6445c0458c6a6649c235908bfeea428cd..d248671b2e1c6256fc4d74320bdb29ca
|
||||
this.awaitingTeleportTime = this.tickCount;
|
||||
this.teleport(
|
||||
this.awaitingPositionFromClient.x,
|
||||
@@ -1587,6 +1630,33 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1597,6 +1640,33 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 20 Jan 2025 13:30:34 -0800
|
||||
Subject: [PATCH] Flush regionfiles on save configuration option
|
||||
|
||||
The windows file system does not write metadata unless
|
||||
the FileChannel is explicitly flushed with metaData=true.
|
||||
|
||||
Note: Setting SYNC (not DSYNC) on the FileChannel does not appear
|
||||
to write the metadata.
|
||||
|
||||
Specifically, we are interested in writing the last modified
|
||||
timestamp so that fs watchers can detect when RegionFiles are
|
||||
modified.
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
index 1acea58838f057ab87efd103cbecb6f5aeaef393..98fbc5c8044bd945d64569f13412a6e7e49a4e7f 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
@@ -1258,6 +1258,14 @@ public final class MoonriseRegionFileIO {
|
||||
|
||||
try {
|
||||
this.regionDataController.finishWrite(this.chunkX, this.chunkZ, writeData);
|
||||
+ // Paper start - flush regionfiles on save
|
||||
+ if (this.world.paperConfig().chunks.flushRegionsOnSave) {
|
||||
+ final RegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ);
|
||||
+ if (regionFile != null) {
|
||||
+ regionFile.flush();
|
||||
+ } // else: evicted from cache, which should have called flush
|
||||
+ }
|
||||
+ // Paper end - flush regionfiles on save
|
||||
} catch (final Throwable thr) {
|
||||
failedWrite = thr instanceof IOException;
|
||||
LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr);
|
||||
@@ -0,0 +1,34 @@
|
||||
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();
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/com/mojang/brigadier/suggestion/IntegerSuggestion.java
|
||||
+++ b/com/mojang/brigadier/suggestion/IntegerSuggestion.java
|
||||
@@ -53,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public int compareTo(final Suggestion o) {
|
||||
- if (o instanceof IntegerSuggestion) {
|
||||
+ if (false && o instanceof IntegerSuggestion) { // Paper - fix unstable Suggestion comparison
|
||||
return Integer.compare(value, ((IntegerSuggestion) o).value);
|
||||
}
|
||||
return super.compareTo(o);
|
||||
@@ -61,6 +_,6 @@
|
||||
|
||||
@Override
|
||||
public int compareToIgnoreCase(final Suggestion b) {
|
||||
- return compareTo(b);
|
||||
+ return super.compareToIgnoreCase(b); // Paper - fix unstable Suggestion comparison
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
--- a/com/mojang/brigadier/suggestion/Suggestion.java
|
||||
+++ b/com/mojang/brigadier/suggestion/Suggestion.java
|
||||
@@ -76,13 +_,27 @@
|
||||
'}';
|
||||
}
|
||||
|
||||
+ // Paper start - fix unstable Suggestion comparison
|
||||
+ private static int compare0(final Suggestion lhs, final Suggestion rhs, final java.util.Comparator<String> textComparator) {
|
||||
+ if (lhs instanceof final IntegerSuggestion lis && rhs instanceof final IntegerSuggestion ris) {
|
||||
+ return Integer.compare(lis.getValue(), ris.getValue());
|
||||
+ } else if (lhs instanceof IntegerSuggestion) {
|
||||
+ return -1;
|
||||
+ } else if (rhs instanceof IntegerSuggestion) {
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ return textComparator.compare(lhs.text, rhs.text);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - fix unstable Suggestion comparison
|
||||
+
|
||||
@Override
|
||||
public int compareTo(final Suggestion o) {
|
||||
- return text.compareTo(o.text);
|
||||
+ return compare0(this, o, java.util.Comparator.naturalOrder()); // Paper - fix unstable Suggestion comparison
|
||||
}
|
||||
|
||||
public int compareToIgnoreCase(final Suggestion b) {
|
||||
- return text.compareToIgnoreCase(b.text);
|
||||
+ return compare0(this, b, String.CASE_INSENSITIVE_ORDER); // Paper - fix unstable Suggestion comparison
|
||||
}
|
||||
|
||||
public Suggestion expand(final String command, final StringRange range) {
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/com/mojang/brigadier/tree/CommandNode.java
|
||||
+++ b/com/mojang/brigadier/tree/CommandNode.java
|
||||
@@ -27,11 +_,21 @@
|
||||
@@ -27,11 +_,22 @@
|
||||
private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
|
||||
private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
|
||||
private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
|
||||
@@ -13,6 +13,7 @@
|
||||
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
|
||||
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
|
||||
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API
|
||||
+ public io.papermc.paper.command.brigadier.PluginCommandMeta pluginCommandMeta; // Paper - Brigadier Command API
|
||||
+ // CraftBukkit start
|
||||
+ public void removeCommand(String name) {
|
||||
+ this.children.remove(name);
|
||||
|
||||
@@ -18,6 +18,37 @@
|
||||
|
||||
public CommandSourceStack(
|
||||
CommandSource source,
|
||||
@@ -187,6 +_,30 @@
|
||||
this.chatMessageChainer
|
||||
);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Expose 'with' functions from the CommandSourceStack
|
||||
+ @Override
|
||||
+ public CommandSourceStack withLocation(org.bukkit.Location location) {
|
||||
+ return this.getLocation().equals(location)
|
||||
+ ? this
|
||||
+ : new CommandSourceStack(
|
||||
+ this.source,
|
||||
+ new Vec3(location.x(), location.y(), location.z()),
|
||||
+ new Vec2(location.getPitch(), location.getYaw()),
|
||||
+ ((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle(),
|
||||
+ this.permissionLevel,
|
||||
+ this.textName,
|
||||
+ this.displayName,
|
||||
+ this.server,
|
||||
+ this.entity,
|
||||
+ this.silent,
|
||||
+ this.resultCallback,
|
||||
+ this.anchor,
|
||||
+ this.signingContext,
|
||||
+ this.chatMessageChainer
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Expose 'with' functions from the CommandSourceStack
|
||||
|
||||
public CommandSourceStack withRotation(Vec2 rotation) {
|
||||
return this.rotation.equals(rotation)
|
||||
@@ -391,9 +_,44 @@
|
||||
|
||||
@Override
|
||||
@@ -92,6 +123,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public Collection<String> getOnlinePlayerNames() {
|
||||
- return Lists.newArrayList(this.server.getPlayerNames());
|
||||
+ return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -598,4 +_,16 @@
|
||||
public boolean isSilent() {
|
||||
return this.silent;
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -251,6 +_,30 @@
|
||||
@@ -150,6 +_,11 @@
|
||||
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
|
||||
|
||||
public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
|
||||
+ // Paper start - Brigadier API - modern minecraft overloads that do not use redirects but are copies instead
|
||||
+ this(selection, context, false);
|
||||
+ }
|
||||
+ public Commands(Commands.CommandSelection selection, CommandBuildContext context, final boolean modern) {
|
||||
+ // Paper end - Brigadier API - modern minecraft overloads that do not use redirects but are copies instead
|
||||
AdvancementCommands.register(this.dispatcher);
|
||||
AttributeCommand.register(this.dispatcher, context);
|
||||
ExecuteCommand.register(this.dispatcher, context);
|
||||
@@ -251,6 +_,40 @@
|
||||
PublishCommand.register(this.dispatcher);
|
||||
}
|
||||
|
||||
@@ -14,9 +26,20 @@
|
||||
+ // Paper start - Brigadier Command API
|
||||
+ // Create legacy minecraft namespace commands
|
||||
+ for (final CommandNode<CommandSourceStack> node : new java.util.ArrayList<>(this.dispatcher.getRoot().getChildren())) {
|
||||
+ // The brigadier dispatcher is not able to resolve nested redirects.
|
||||
+ // E.g. registering the alias minecraft:tp cannot redirect to tp, as tp itself redirects to teleport.
|
||||
+ // Instead, target the first none redirecting node.
|
||||
+ if (modern) {
|
||||
+ // Modern behaviour that simply creates a full copy of the commands node.
|
||||
+ // Avoids plenty of issues around registering redirects *to* these nodes from the API
|
||||
+ this.dispatcher.getRoot().addChild(
|
||||
+ io.papermc.paper.command.brigadier.PaperBrigadier.copyLiteral(
|
||||
+ "minecraft:" + node.getName(),
|
||||
+ (com.mojang.brigadier.tree.LiteralCommandNode<CommandSourceStack>) node
|
||||
+ )
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // Legacy behaviour of creating a flattened redirecting node.
|
||||
+ // Used by CommandArgumentUpgrader
|
||||
+ CommandNode<CommandSourceStack> flattenedAliasTarget = node;
|
||||
+ while (flattenedAliasTarget.getRedirect() != null) flattenedAliasTarget = flattenedAliasTarget.getRedirect();
|
||||
+
|
||||
@@ -24,8 +47,7 @@
|
||||
+ com.mojang.brigadier.builder.LiteralArgumentBuilder.<CommandSourceStack>literal("minecraft:" + node.getName())
|
||||
+ .executes(flattenedAliasTarget.getCommand())
|
||||
+ .requires(flattenedAliasTarget.getRequirement())
|
||||
+ .redirect(flattenedAliasTarget)
|
||||
+ );
|
||||
+ .redirect(flattenedAliasTarget));
|
||||
+ }
|
||||
+ // Paper end - Brigadier Command API
|
||||
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
|
||||
@@ -150,11 +172,10 @@
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -360,25 +_,130 @@
|
||||
@@ -360,26 +_,120 @@
|
||||
}
|
||||
|
||||
public void sendCommands(ServerPlayer player) {
|
||||
- Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newHashMap();
|
||||
+ // Paper start - Send empty commands if tab completion is disabled
|
||||
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
|
||||
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>()));
|
||||
@@ -182,7 +203,7 @@
|
||||
+
|
||||
+ private void sendAsync(ServerPlayer player, java.util.Collection<CommandNode<CommandSourceStack>> dispatcherRootChildren) {
|
||||
+ // Paper end - Perf: Async command map building
|
||||
+ Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues
|
||||
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newHashMap();
|
||||
RootCommandNode<SharedSuggestionProvider> rootCommandNode = new RootCommandNode<>();
|
||||
map.put(this.dispatcher.getRoot(), rootCommandNode);
|
||||
- this.fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
|
||||
@@ -224,7 +245,6 @@
|
||||
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode
|
||||
) {
|
||||
- for (CommandNode<CommandSourceStack> commandNode : rootCommandSource.getChildren()) {
|
||||
+ commandNodeToSuggestionNode.keySet().removeIf((node) -> !org.spigotmc.SpigotConfig.sendNamespaced && node.getName().contains(":")); // Paper - Remove namedspaced from result nodes to prevent redirect trimming ~ see comment below
|
||||
+ for (CommandNode<CommandSourceStack> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
|
||||
+ // Paper start - Brigadier API
|
||||
+ if (commandNode.clientNode != null) {
|
||||
@@ -249,12 +269,11 @@
|
||||
+ - Don't allow command nodes to be deleted
|
||||
+ - Do this :)
|
||||
+ */
|
||||
+
|
||||
+ // Is there an invalid command redirect?
|
||||
+ if (argumentBuilder.getRedirect() != null && commandNodeToSuggestionNode.get(argumentBuilder.getRedirect()) == null) {
|
||||
+ // Create the argument builder with the same values as the specified node, but with a different literal and populated children
|
||||
+
|
||||
+ CommandNode<SharedSuggestionProvider> redirect = argumentBuilder.getRedirect();
|
||||
+ final CommandNode<SharedSuggestionProvider> redirect = argumentBuilder.getRedirect();
|
||||
+ // Diff copied from LiteralCommand#createBuilder
|
||||
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<SharedSuggestionProvider> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
|
||||
+ builder.requires(redirect.getRequirement());
|
||||
@@ -263,7 +282,7 @@
|
||||
+ builder.executes(redirect.getCommand());
|
||||
+ }
|
||||
+ // Diff copied from LiteralCommand#createBuilder
|
||||
+ for (CommandNode<SharedSuggestionProvider> child : redirect.getChildren()) {
|
||||
+ for (final CommandNode<SharedSuggestionProvider> child : redirect.getChildren()) {
|
||||
+ builder.then(child);
|
||||
+ }
|
||||
+
|
||||
@@ -271,21 +290,15 @@
|
||||
+ }
|
||||
+ // Paper end
|
||||
argumentBuilder.requires(suggestions -> true);
|
||||
if (argumentBuilder.getCommand() != null) {
|
||||
- if (argumentBuilder.getCommand() != null) {
|
||||
- argumentBuilder.executes(commandContext -> 0);
|
||||
+ // Paper start - fix suggestions due to falsely equal nodes
|
||||
+ // Always create a new instance
|
||||
+ //noinspection Convert2Lambda
|
||||
+ argumentBuilder.executes(new com.mojang.brigadier.Command<>() {
|
||||
+ @Override
|
||||
+ public int run(com.mojang.brigadier.context.CommandContext<SharedSuggestionProvider> commandContext) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - fix suggestions due to falsely equal nodes
|
||||
}
|
||||
- }
|
||||
+ // Paper - don't replace Command instance on suggestion node
|
||||
+ // 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 @@
|
||||
commandNodeToSuggestionNode.put(commandNode, commandNode1);
|
||||
rootSuggestion.addChild(commandNode1);
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
--- 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;
|
||||
|
||||
@@ -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 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
);
|
||||
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.DataSanitizationUtil.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
|
||||
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.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.DataSanitizationUtil.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
|
||||
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.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()
|
||||
@@ -18,7 +18,7 @@
|
||||
);
|
||||
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.DataSanitizationUtil.CONTAINER).cacheEncoding() // Paper - sanitize container contents
|
||||
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.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()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/FriendlyByteBuf.java
|
||||
+++ b/net/minecraft/network/FriendlyByteBuf.java
|
||||
@@ -70,6 +_,7 @@
|
||||
@@ -70,14 +_,20 @@
|
||||
public class FriendlyByteBuf extends ByteBuf {
|
||||
public static final int DEFAULT_NBT_QUOTA = 2097152;
|
||||
private final ByteBuf source;
|
||||
@@ -8,8 +8,13 @@
|
||||
public static final short MAX_STRING_LENGTH = 32767;
|
||||
public static final int MAX_COMPONENT_STRING_LENGTH = 262144;
|
||||
private static final int PUBLIC_KEY_SIZE = 256;
|
||||
@@ -78,6 +_,7 @@
|
||||
private static final int MAX_PUBLIC_KEY_HEADER_SIZE = 256;
|
||||
private static final int MAX_PUBLIC_KEY_LENGTH = 512;
|
||||
private static final Gson GSON = new Gson();
|
||||
+ // Paper start - Track codec depth
|
||||
+ public boolean trackCodecDepth;
|
||||
+ public byte codecDepth;
|
||||
+ // Paper end - Track codec depth
|
||||
|
||||
public FriendlyByteBuf(ByteBuf source) {
|
||||
+ this.adventure$locale = PacketEncoder.ADVENTURE_LOCALE.get(); // Paper - track player's locale for server-side translations
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
--- a/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
@@ -378,6 +_,48 @@
|
||||
};
|
||||
}
|
||||
|
||||
+ // Paper start - Track codec depth
|
||||
+ static <B extends FriendlyByteBuf, V> StreamCodec<B, V> trackDepth(final StreamCodec<B, V> codec) {
|
||||
+ return new StreamCodec<>() {
|
||||
+ @Override
|
||||
+ public V decode(B buffer) {
|
||||
+ buffer.trackCodecDepth = true;
|
||||
+ try {
|
||||
+ return codec.decode(buffer);
|
||||
+ } finally {
|
||||
+ buffer.trackCodecDepth = false;
|
||||
+ buffer.codecDepth = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void encode(B buffer, V value) {
|
||||
+ codec.encode(buffer, value);
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ static <B extends FriendlyByteBuf, V> StreamCodec<B, V> increaseDepth(final StreamCodec<B, V> codec) {
|
||||
+ return new StreamCodec<>() {
|
||||
+ @Override
|
||||
+ public V decode(B buffer) {
|
||||
+ if (!buffer.trackCodecDepth) {
|
||||
+ return codec.decode(buffer);
|
||||
+ }
|
||||
+ if (++buffer.codecDepth > 64) {
|
||||
+ throw new DecoderException("Too deep");
|
||||
+ }
|
||||
+ return codec.decode(buffer);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void encode(B buffer, V value) {
|
||||
+ codec.encode(buffer, value);
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ // Paper end - Track codec depth
|
||||
+
|
||||
static <B extends ByteBuf, V> StreamCodec<B, Optional<V>> optional(final StreamCodec<B, V> codec) {
|
||||
return new StreamCodec<B, Optional<V>>() {
|
||||
@Override
|
||||
@@ -1,21 +1,26 @@
|
||||
--- a/net/minecraft/network/protocol/common/custom/DiscardedPayload.java
|
||||
+++ b/net/minecraft/network/protocol/common/custom/DiscardedPayload.java
|
||||
@@ -4,13 +_,14 @@
|
||||
@@ -4,13 +_,19 @@
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
-public record DiscardedPayload(ResourceLocation id) implements CustomPacketPayload {
|
||||
+public record DiscardedPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { // CraftBukkit - store data
|
||||
+public record DiscardedPayload(ResourceLocation id, byte[] data) implements CustomPacketPayload { // Paper - store data
|
||||
public static <T extends FriendlyByteBuf> StreamCodec<T, DiscardedPayload> codec(ResourceLocation id, int maxSize) {
|
||||
- return CustomPacketPayload.codec((value, output) -> {}, buffer -> {
|
||||
+ return CustomPacketPayload.codec((value, output) -> {
|
||||
+ output.writeBytes(value.data); // CraftBukkit - serialize
|
||||
+ // Paper start
|
||||
+ // Always write data
|
||||
+ output.writeBytes(value.data);
|
||||
+ }, buffer -> {
|
||||
int i = buffer.readableBytes();
|
||||
if (i >= 0 && i <= maxSize) {
|
||||
- buffer.skipBytes(i);
|
||||
- return new DiscardedPayload(id);
|
||||
+ return new DiscardedPayload(id, buffer.readBytes(i)); // CraftBukkit
|
||||
+ final byte[] data = new byte[i];
|
||||
+ buffer.readBytes(data);
|
||||
+ return new DiscardedPayload(id, data);
|
||||
+ // Paper end
|
||||
} else {
|
||||
throw new IllegalArgumentException("Payload may not be larger than " + maxSize + " bytes");
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
private static void pack(List<SynchedEntityData.DataValue<?>> dataValues, RegistryFriendlyByteBuf buffer) {
|
||||
+ try (io.papermc.paper.util.DataSanitizationUtil.DataSanitizer ignored = io.papermc.paper.util.DataSanitizationUtil.start(true)) { // Paper - data sanitization
|
||||
+ 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
|
||||
for (SynchedEntityData.DataValue<?> dataValue : dataValues) {
|
||||
dataValue.write(buffer);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
buffer.writeVarInt(this.entity);
|
||||
int size = this.slots.size();
|
||||
|
||||
+ try (io.papermc.paper.util.DataSanitizationUtil.DataSanitizer ignored = io.papermc.paper.util.DataSanitizationUtil.start(this.sanitize)) { // Paper - data sanitization
|
||||
+ 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
|
||||
for (int i = 0; i < size; i++) {
|
||||
Pair<EquipmentSlot, ItemStack> pair = this.slots.get(i);
|
||||
EquipmentSlot equipmentSlot = pair.getFirst();
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--- 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) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundSetCreativeModeSlotPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundSetCreativeModeSlotPacket.java
|
||||
@@ -11,7 +_,7 @@
|
||||
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
|
||||
ServerboundSetCreativeModeSlotPacket::itemStack,
|
||||
ServerboundSetCreativeModeSlotPacket::new
|
||||
);
|
||||
@@ -23,7 +23,7 @@
|
||||
public boolean isDirty() {
|
||||
return this.isDirty;
|
||||
}
|
||||
@@ -169,6 +_,20 @@
|
||||
@@ -169,6 +_,19 @@
|
||||
return new SynchedEntityData(this.entity, this.itemsById);
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,8 @@
|
||||
+ // Paper start
|
||||
+ // We need to pack all as we cannot rely on "non default values" or "dirty" ones.
|
||||
+ // Because these values can possibly be desynced on the client.
|
||||
+ @Nullable
|
||||
+ public List<SynchedEntityData.DataValue<?>> packAll() {
|
||||
+ final List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
|
||||
+ final List<SynchedEntityData.DataValue<?>> list = new ArrayList<>(this.itemsById.length);
|
||||
+ for (final DataItem<?> dataItem : this.itemsById) {
|
||||
+ list.add(dataItem.value());
|
||||
+ }
|
||||
|
||||
@@ -984,7 +984,7 @@
|
||||
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
|
||||
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
|
||||
|
||||
@@ -1046,17 +_,65 @@
|
||||
@@ -1046,17 +_,66 @@
|
||||
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
||||
@@ -1027,8 +1027,9 @@
|
||||
+ }
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) entityhuman;
|
||||
+ long playerTime = entityplayer.getPlayerTime();
|
||||
+ ClientboundSetTimePacket packet = (playerTime == dayTime) ? worldPacket :
|
||||
+ new ClientboundSetTimePacket(worldTime, playerTime, doDaylight);
|
||||
+ boolean relativeTime = entityplayer.relativeTime;
|
||||
+ ClientboundSetTimePacket packet = ((relativeTime || !doDaylight) && playerTime == dayTime) ? worldPacket :
|
||||
+ new ClientboundSetTimePacket(worldTime, playerTime, relativeTime && doDaylight);
|
||||
+ entityplayer.connection.send(packet); // Add support for per player time
|
||||
+ // Paper end - Perf: Optimize time updates
|
||||
+ }
|
||||
@@ -1262,11 +1263,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1652,10 +_,11 @@
|
||||
@@ -1651,11 +_,12 @@
|
||||
public void kickUnlistedPlayers(CommandSourceStack commandSource) {
|
||||
if (this.isEnforceWhitelist()) {
|
||||
PlayerList playerList = commandSource.getServer().getPlayerList();
|
||||
+ if (!playerList.isUsingWhitelist()) return; // Paper - whitelist not enabled
|
||||
UserWhiteList whiteList = playerList.getWhiteList();
|
||||
+ if (!((net.minecraft.server.dedicated.DedicatedServer) this).getProperties().whiteList.get()) return; // Paper - whitelist not enabled
|
||||
|
||||
for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) {
|
||||
- if (!whiteList.isWhiteListed(serverPlayer.getGameProfile())) {
|
||||
|
||||
@@ -67,3 +67,12 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -247,7 +_,7 @@
|
||||
public void flushDirty(ServerPlayer serverPlayer) {
|
||||
if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
|
||||
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();
|
||||
- Set<AdvancementHolder> set = new HashSet<>();
|
||||
+ Set<AdvancementHolder> set = new java.util.TreeSet<>(java.util.Comparator.comparing(adv -> adv.id().toString())); // Paper - Changed from HashSet to TreeSet ordered alphabetically.
|
||||
Set<ResourceLocation> set1 = new HashSet<>();
|
||||
|
||||
for (AdvancementNode advancementNode : this.rootsToUpdate) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
--- a/net/minecraft/server/ReloadableServerResources.java
|
||||
+++ b/net/minecraft/server/ReloadableServerResources.java
|
||||
@@ -39,6 +_,7 @@
|
||||
@@ -38,7 +_,8 @@
|
||||
this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess());
|
||||
this.postponedTags = postponedTags;
|
||||
this.recipes = new RecipeManager(registries);
|
||||
this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures));
|
||||
- this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures));
|
||||
+ this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration
|
||||
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API
|
||||
this.advancements = new ServerAdvancementManager(registries);
|
||||
this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher());
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -14,6 +_,7 @@
|
||||
private long scheduledCurrentSprintTicks = 0L;
|
||||
private boolean previousIsFrozen = false;
|
||||
private final MinecraftServer server;
|
||||
+ private boolean silent; // Paper - silence feedback when API requests sprint
|
||||
|
||||
public ServerTickRateManager(MinecraftServer server) {
|
||||
this.server = server;
|
||||
@@ -67,6 +_,13 @@
|
||||
}
|
||||
|
||||
public boolean requestGameToSprint(int sprintTime) {
|
||||
+ // Paper start - silence feedback when API requests sprint
|
||||
+ return requestGameToSprint(sprintTime, false);
|
||||
+ }
|
||||
+
|
||||
+ public boolean requestGameToSprint(int sprintTime, boolean silent) {
|
||||
+ if (!isSprinting()) this.silent = silent;
|
||||
+ // Paper end - silence feedback when API requests sprint
|
||||
boolean flag = this.remainingSprintTicks > 0L;
|
||||
this.sprintTimeSpend = 0L;
|
||||
this.scheduledCurrentSprintTicks = sprintTime;
|
||||
@@ -83,7 +_,10 @@
|
||||
String string = String.format("%.2f", l == 0L ? this.millisecondsPerTick() : d / l);
|
||||
this.scheduledCurrentSprintTicks = 0L;
|
||||
this.sprintTimeSpend = 0L;
|
||||
- this.server.createCommandSourceStack().sendSuccess(() -> Component.translatable("commands.tick.sprint.report", i, string), true);
|
||||
+ // Paper start - silence feedback when API requests sprint
|
||||
+ if (!this.silent) this.server.createCommandSourceStack().sendSuccess(() -> Component.translatable("commands.tick.sprint.report", i, string), true);
|
||||
+ this.silent = false;
|
||||
+ // Paper end - silence feedback when API requests sprint
|
||||
this.remainingSprintTicks = 0L;
|
||||
this.setFrozen(this.previousIsFrozen);
|
||||
this.server.onTickRateChanged();
|
||||
@@ -5,7 +5,7 @@
|
||||
private int value;
|
||||
private int max = 100;
|
||||
+ // CraftBukkit start
|
||||
+ private org.bukkit.boss.KeyedBossBar bossBar;
|
||||
+ private @javax.annotation.Nullable org.bukkit.boss.KeyedBossBar bossBar;
|
||||
+
|
||||
+ public org.bukkit.boss.KeyedBossBar getBukkitEntity() {
|
||||
+ if (this.bossBar == null) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/commands/LocateCommand.java
|
||||
+++ b/net/minecraft/server/commands/LocateCommand.java
|
||||
@@ -202,6 +_,6 @@
|
||||
private static float dist(int x1, int z1, int x2, int z2) {
|
||||
int i = x2 - x1;
|
||||
int i1 = z2 - z1;
|
||||
- return Mth.sqrt(i * i + i1 * i1);
|
||||
+ return (float) Math.hypot(i, i1); // Paper - Fix MC-177381
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/server/commands/RideCommand.java
|
||||
+++ b/net/minecraft/server/commands/RideCommand.java
|
||||
@@ -58,7 +_,7 @@
|
||||
Entity vehicle1 = target.getVehicle();
|
||||
if (vehicle1 != null) {
|
||||
throw ERROR_ALREADY_RIDING.create(target.getDisplayName(), vehicle1.getDisplayName());
|
||||
- } else if (vehicle.getType() == EntityType.PLAYER) {
|
||||
+ } else if (vehicle.getType() == EntityType.PLAYER && !io.papermc.paper.configuration.GlobalConfiguration.get().commands.rideCommandAllowPlayerAsVehicle) { // Paper - allow player as vehicle
|
||||
throw ERROR_MOUNTING_PLAYER.create();
|
||||
} else if (target.getSelfAndPassengers().anyMatch(passenger -> passenger == vehicle)) {
|
||||
throw ERROR_MOUNTING_LOOP.create();
|
||||
@@ -361,7 +361,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -515,14 +_,52 @@
|
||||
@@ -515,14 +_,54 @@
|
||||
|
||||
@Override
|
||||
public String getPluginNames() {
|
||||
@@ -402,6 +402,8 @@
|
||||
+ }
|
||||
+
|
||||
+ public String runCommand(RconConsoleSource rconConsoleSource, String s) {
|
||||
+ if (s.isBlank()) return ""; // Paper - Do not process empty rcon commands
|
||||
+
|
||||
+ rconConsoleSource.prepareForCommand();
|
||||
+ this.executeBlocking(() -> {
|
||||
+ CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack();
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
Properties map = Settings.this.cloneProperties();
|
||||
map.put(this.key, this.serializer.apply(newValue));
|
||||
- return Settings.this.reload(registryAccess, map);
|
||||
+ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit
|
||||
+ return Settings.this.reload(registryAccess, map, Settings.this.options); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,15 +204,19 @@
|
||||
chunkGenerator,
|
||||
this.chunkSource.randomState(),
|
||||
this,
|
||||
@@ -281,7 +_,7 @@
|
||||
@@ -280,9 +_,9 @@
|
||||
seed,
|
||||
fixerUpper
|
||||
);
|
||||
this.structureManager = new StructureManager(this, server.getWorldData().worldGenOptions(), this.structureCheck);
|
||||
- this.structureManager = new StructureManager(this, server.getWorldData().worldGenOptions(), this.structureCheck);
|
||||
- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) {
|
||||
- this.dragonFight = new EndDragonFight(this, seed, server.getWorldData().endDragonFightData());
|
||||
+ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), this.structureCheck); // CraftBukkit
|
||||
+ if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END
|
||||
this.dragonFight = new EndDragonFight(this, seed, server.getWorldData().endDragonFightData());
|
||||
+ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit
|
||||
} else {
|
||||
this.dragonFight = null;
|
||||
}
|
||||
@@ -292,7 +_,15 @@
|
||||
this.randomSequences = Objects.requireNonNullElseGet(
|
||||
randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(seed), "random_sequences")
|
||||
@@ -456,7 +460,7 @@
|
||||
}
|
||||
|
||||
public void resetEmptyTime() {
|
||||
@@ -746,18 +_,45 @@
|
||||
@@ -746,18 +_,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,6 +487,7 @@
|
||||
entity.setOldPosAndRot();
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
entity.tickCount++;
|
||||
+ entity.totalEntityAge++; // Paper - age-like counter for all entities
|
||||
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString());
|
||||
profilerFiller.incrementCounter("tickNonPassenger");
|
||||
entity.tick();
|
||||
@@ -502,7 +507,12 @@
|
||||
}
|
||||
|
||||
private void tickPassenger(Entity ridingEntity, Entity passengerEntity) {
|
||||
@@ -770,6 +_,7 @@
|
||||
@@ -766,10 +_,12 @@
|
||||
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
|
||||
passengerEntity.setOldPosAndRot();
|
||||
passengerEntity.tickCount++;
|
||||
+ passengerEntity.totalEntityAge++; // Paper - age-like counter for all entities
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString());
|
||||
profilerFiller.incrementCounter("tickPassenger");
|
||||
passengerEntity.rideTick();
|
||||
@@ -860,11 +870,11 @@
|
||||
double zOffset,
|
||||
double speed
|
||||
) {
|
||||
+ // CraftBukkit start - visibility api support
|
||||
+ // Paper start - visibility api support
|
||||
+ return this.sendParticlesSource(null, type, overrideLimiter, alwaysShow, posX, posY, posZ, particleCount, xOffset, yOffset, zOffset, speed);
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ @javax.annotation.Nullable ServerPlayer sender,
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -881,7 +891,7 @@
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ List<ServerPlayer> receivers,
|
||||
+ @javax.annotation.Nullable ServerPlayer sender,
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -894,7 +904,7 @@
|
||||
+ double zOffset,
|
||||
+ double speed
|
||||
+ ) {
|
||||
+ // CraftBukkit end - visibility api support
|
||||
+ // Paper end - visibility api support
|
||||
ClientboundLevelParticlesPacket clientboundLevelParticlesPacket = new ClientboundLevelParticlesPacket(
|
||||
type, overrideLimiter, alwaysShow, posX, posY, posZ, (float)xOffset, (float)yOffset, (float)zOffset, (float)speed, particleCount
|
||||
);
|
||||
@@ -1062,6 +1072,14 @@
|
||||
@Override
|
||||
public CrashReportCategory fillReportDetails(CrashReport report) {
|
||||
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
|
||||
@@ -1714,6 +_,7 @@
|
||||
final class EntityCallbacks implements LevelCallback<Entity> {
|
||||
@Override
|
||||
public void onCreated(Entity entity) {
|
||||
+ entity.setOldPosAndRot(); // Paper - update old pos / rot for new entities as it will default to Vec3.ZERO
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1723,24 +_,32 @@
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
@Nullable
|
||||
private Vec3 startingToFallPosition;
|
||||
@Nullable
|
||||
@@ -258,6 +_,13 @@
|
||||
@@ -258,6 +_,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
|
||||
+ }
|
||||
+ // Paper end - Sync offhand slot in menus
|
||||
+
|
||||
+ // Paper start - add flag to simplify remote matching logic
|
||||
+ @Override
|
||||
+ public ServerPlayer player() {
|
||||
+ return ServerPlayer.this;
|
||||
+ }
|
||||
+ // Paper end - add flag to simplify remote matching logic
|
||||
+
|
||||
@Override
|
||||
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
|
||||
@@ -1213,7 +1220,7 @@
|
||||
+ if (this.getMainArm() != clientInformation.mainHand()) {
|
||||
+ org.bukkit.event.player.PlayerChangedMainHandEvent event = new org.bukkit.event.player.PlayerChangedMainHandEvent(
|
||||
+ this.getBukkitEntity(),
|
||||
+ this.getMainArm() == HumanoidArm.LEFT ? org.bukkit.inventory.MainHand.LEFT : org.bukkit.inventory.MainHand.RIGHT
|
||||
+ clientInformation.mainHand() == HumanoidArm.LEFT ? org.bukkit.inventory.MainHand.LEFT : org.bukkit.inventory.MainHand.RIGHT
|
||||
+ );
|
||||
+ this.server.server.getPluginManager().callEvent(event);
|
||||
+ }
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,30 +_,119 @@
|
||||
@@ -88,30 +_,123 @@
|
||||
public void handlePong(ServerboundPongPacket packet) {
|
||||
}
|
||||
|
||||
@@ -105,64 +105,68 @@
|
||||
@Override
|
||||
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
|
||||
- }
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - Brand support
|
||||
+ // Paper start
|
||||
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.BrandPayload(String brand)) {
|
||||
+ this.player.clientBrandName = brand;
|
||||
+ }
|
||||
+ // Paper end - Brand support
|
||||
+
|
||||
+ if (!(packet.payload() instanceof final net.minecraft.network.protocol.common.custom.DiscardedPayload discardedPayload)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
+ net.minecraft.resources.ResourceLocation identifier = packet.payload().type().id();
|
||||
+ io.netty.buffer.ByteBuf payload = discardedPayload.data();
|
||||
+
|
||||
+ if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_REGISTER)) {
|
||||
+ try {
|
||||
+ String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
+ for (String channel : channels.split("\0")) {
|
||||
+ this.getCraftPlayer().addChannel(channel);
|
||||
+ }
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn't register custom payload", ex);
|
||||
+ this.disconnect(Component.literal("Invalid payload REGISTER!"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
||||
+ }
|
||||
+ } else if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER)) {
|
||||
+ try {
|
||||
+ String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
+ for (String channel : channels.split("\0")) {
|
||||
+ this.getCraftPlayer().removeChannel(channel);
|
||||
+ }
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn't unregister custom payload", ex);
|
||||
+ this.disconnect(Component.literal("Invalid payload UNREGISTER!"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
||||
+ }
|
||||
+ } else {
|
||||
+ try {
|
||||
+ byte[] data = new byte[payload.readableBytes()];
|
||||
+ payload.readBytes(data);
|
||||
+ // Paper start - Brand support; Retain this incase upstream decides to 'break' the new mechanism in favour of backwards compat...
|
||||
+ if (identifier.equals(MINECRAFT_BRAND)) {
|
||||
+ try {
|
||||
+ this.player.clientBrandName = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.copiedBuffer(data)).readUtf(256);
|
||||
+ } catch (StringIndexOutOfBoundsException ex) {
|
||||
+ this.player.clientBrandName = "illegal";
|
||||
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
+
|
||||
+ final net.minecraft.resources.ResourceLocation identifier = packet.payload().type().id();
|
||||
+ final byte[] data = discardedPayload.data();
|
||||
+ try {
|
||||
+ final boolean registerChannel = ServerCommonPacketListenerImpl.CUSTOM_REGISTER.equals(identifier);
|
||||
+ if (registerChannel || ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER.equals(identifier)) {
|
||||
+ // Strings separated by zeros instead of length prefixes
|
||||
+ int startIndex = 0;
|
||||
+ for (int i = 0; i < data.length; i++) {
|
||||
+ final byte b = data[i];
|
||||
+ if (b != 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ readChannelIdentifier(data, startIndex, i, registerChannel);
|
||||
+ startIndex = i + 1;
|
||||
+ }
|
||||
+ // Paper end - Brand support
|
||||
+ this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), identifier.toString(), data);
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn't dispatch custom payload", ex);
|
||||
+ this.disconnect(Component.literal("Invalid custom payload!"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
||||
+
|
||||
+ // Read the last one
|
||||
+ readChannelIdentifier(data, startIndex, data.length, registerChannel);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (identifier.equals(MINECRAFT_BRAND)) {
|
||||
+ this.player.clientBrandName = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.wrappedBuffer(data)).readUtf(256);
|
||||
+ }
|
||||
+
|
||||
+ this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), identifier.toString(), data);
|
||||
+ } catch (final Exception e) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn't handle custom payload on channel {}", identifier, e);
|
||||
+ this.disconnect(Component.literal("Invalid custom payload payload!"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void readChannelIdentifier(final byte[] data, final int from, final int to, final boolean register) {
|
||||
+ final int length = to - from;
|
||||
+ if (length == 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final String channel = new String(data, from, length, java.nio.charset.StandardCharsets.US_ASCII);
|
||||
+ if (register) {
|
||||
+ this.getCraftPlayer().addChannel(channel);
|
||||
+ } else {
|
||||
+ this.getCraftPlayer().removeChannel(channel);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public final boolean isDisconnected() {
|
||||
+ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper - Fix duplication bugs
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void handleResourcePackResponse(ServerboundResourcePackPacket packet) {
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
private double firstGoodX;
|
||||
private double firstGoodY;
|
||||
private double firstGoodZ;
|
||||
@@ -236,22 +_,39 @@
|
||||
@@ -236,22 +_,41 @@
|
||||
private int receivedMovePacketCount;
|
||||
private int knownMovePacketCount;
|
||||
private boolean receivedMovementThisTick;
|
||||
@@ -98,6 +98,7 @@
|
||||
private final FutureChain chatMessageChain;
|
||||
private boolean waitingForSwitchToConfig;
|
||||
+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); // Paper - Limit client sign length
|
||||
+ private final io.papermc.paper.event.packet.ClientTickEndEvent tickEndEvent; // Paper - add client tick end event
|
||||
|
||||
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
|
||||
- super(server, connection, cookie);
|
||||
@@ -109,6 +110,7 @@
|
||||
this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile);
|
||||
- this.chatMessageChain = new FutureChain(server);
|
||||
+ this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat
|
||||
+ this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -373,7 +375,7 @@
|
||||
this.awaitingPositionFromClient.x,
|
||||
this.awaitingPositionFromClient.y,
|
||||
this.awaitingPositionFromClient.z,
|
||||
@@ -495,6 +_,7 @@
|
||||
@@ -495,12 +_,20 @@
|
||||
this.lastGoodZ = this.awaitingPositionFromClient.z;
|
||||
this.player.hasChangedDimension();
|
||||
this.awaitingPositionFromClient = null;
|
||||
@@ -381,6 +383,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAcceptPlayerLoad(ServerboundPlayerLoadedPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
+ // Paper start - PlayerLoadedWorldEvent
|
||||
+ if (this.player.hasClientLoaded()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ final io.papermc.paper.event.player.PlayerClientLoadedWorldEvent event = new io.papermc.paper.event.player.PlayerClientLoadedWorldEvent(this.player.getBukkitEntity(), false);
|
||||
+ event.callEvent();
|
||||
+ // Paper end - PlayerLoadedWorldEvent
|
||||
this.player.setClientLoaded(true);
|
||||
}
|
||||
|
||||
@@ -521,6 +_,7 @@
|
||||
@Override
|
||||
public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) {
|
||||
@@ -532,7 +547,7 @@
|
||||
addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack);
|
||||
}
|
||||
|
||||
@@ -685,14 +_,24 @@
|
||||
@@ -685,18 +_,29 @@
|
||||
if (stack.isItemEnabled(this.player.level().enabledFeatures())) {
|
||||
Inventory inventory = this.player.getInventory();
|
||||
int i = inventory.findSlotMatchingItem(stack);
|
||||
@@ -561,6 +576,11 @@
|
||||
}
|
||||
|
||||
this.player.connection.send(new ClientboundSetHeldSlotPacket(inventory.selected));
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,6 +_,13 @@
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
int item = packet.getItem();
|
||||
@@ -1057,7 +1077,7 @@
|
||||
if (this.player.hasClientLoaded()) {
|
||||
BlockPos pos = packet.getPos();
|
||||
this.player.resetLastActionTime();
|
||||
@@ -1101,14 +_,46 @@
|
||||
@@ -1101,32 +_,95 @@
|
||||
case SWAP_ITEM_WITH_OFFHAND:
|
||||
if (!this.player.isSpectator()) {
|
||||
ItemStack itemInHand = this.player.getItemInHand(InteractionHand.OFF_HAND);
|
||||
@@ -1083,6 +1103,7 @@
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.player.stopUsingItem();
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1104,14 +1125,27 @@
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.player.drop(false);
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
@@ -1125,8 +_,34 @@
|
||||
return;
|
||||
case DROP_ALL_ITEMS:
|
||||
if (!this.player.isSpectator()) {
|
||||
this.player.drop(true);
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
return;
|
||||
case RELEASE_USE_ITEM:
|
||||
- this.player.releaseUsingItem();
|
||||
+ if (this.player.getUseItem() == this.player.getItemInHand(this.player.getUsedItemHand())) this.player.releaseUsingItem(); // Paper - validate use item before processing release
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
return;
|
||||
case START_DESTROY_BLOCK:
|
||||
case ABORT_DESTROY_BLOCK:
|
||||
case STOP_DESTROY_BLOCK:
|
||||
+ // Paper start - Don't allow digging into unloaded chunks
|
||||
+ if (this.player.level().getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4) == null) {
|
||||
+ if (this.player.level().getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4) == null || !this.player.canInteractWithBlock(pos, 1.0)) {
|
||||
+ this.player.connection.ackBlockChangesUpTo(packet.getSequence());
|
||||
+ return;
|
||||
+ }
|
||||
@@ -1138,6 +1172,7 @@
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Send block entities after destroy prediction
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
return;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid player action");
|
||||
@@ -1208,6 +1243,14 @@
|
||||
} else {
|
||||
Component component1 = Component.translatable("build.tooHigh", maxY).withStyle(ChatFormatting.RED);
|
||||
this.player.sendSystemMessage(component1, true);
|
||||
@@ -1187,6 +_,7 @@
|
||||
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos));
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction)));
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
} else {
|
||||
LOGGER.warn(
|
||||
"Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.",
|
||||
@@ -1203,6 +_,8 @@
|
||||
@Override
|
||||
public void handleUseItem(ServerboundUseItemPacket packet) {
|
||||
@@ -1333,7 +1376,7 @@
|
||||
throw new IllegalArgumentException("Expected packet sequence nr >= 0");
|
||||
} else {
|
||||
this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo);
|
||||
@@ -1275,7 +_,17 @@
|
||||
@@ -1275,20 +_,38 @@
|
||||
@Override
|
||||
public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
@@ -1351,8 +1394,10 @@
|
||||
if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) {
|
||||
this.player.stopUsingItem();
|
||||
}
|
||||
@@ -1284,11 +_,18 @@
|
||||
|
||||
this.player.getInventory().selected = packet.getSlot();
|
||||
this.player.resetLastActionTime();
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
} else {
|
||||
LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
|
||||
+ this.disconnect(Component.literal("Invalid hotbar selection (Hacking?)"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause
|
||||
@@ -1516,7 +1561,7 @@
|
||||
}
|
||||
|
||||
return optional;
|
||||
@@ -1451,22 +_,155 @@
|
||||
@@ -1451,22 +_,157 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1662,9 +1707,11 @@
|
||||
+ // Spigot start - spam exclusions
|
||||
+ private void detectRateSpam(String message) {
|
||||
+ // CraftBukkit start - replaced with thread safe throttle
|
||||
+ for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
+ if (exclude != null && message.startsWith(exclude)) {
|
||||
+ return;
|
||||
+ if (org.spigotmc.SpigotConfig.enableSpamExclusions) {
|
||||
+ for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
+ if (exclude != null && message.startsWith(exclude)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
@@ -1935,7 +1982,7 @@
|
||||
ServerGamePacketListenerImpl.LOGGER
|
||||
.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString());
|
||||
}
|
||||
@@ -1656,6 +_,26 @@
|
||||
@@ -1656,6 +_,27 @@
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1959,6 +2006,7 @@
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end - PlayerUseUnknownEntityEvent
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2017,7 +2065,7 @@
|
||||
this.player.containerMenu.sendAllDataToRemote();
|
||||
} else if (!this.player.containerMenu.stillValid(this.player)) {
|
||||
LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu);
|
||||
@@ -1713,7 +_,313 @@
|
||||
@@ -1713,7 +_,341 @@
|
||||
} else {
|
||||
boolean flag = packet.getStateId() != this.player.containerMenu.getStateId();
|
||||
this.player.containerMenu.suppressRemoteUpdates();
|
||||
@@ -2056,11 +2104,19 @@
|
||||
+ ItemStack cursor = this.player.containerMenu.getCarried();
|
||||
+ if (clickedItem.isEmpty()) {
|
||||
+ if (!cursor.isEmpty()) {
|
||||
+ action = packet.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE;
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && cursor.has(DataComponents.BUNDLE_CONTENTS) && packet.getButtonNum() != 0) {
|
||||
+ action = cursor.get(DataComponents.BUNDLE_CONTENTS).isEmpty() ? InventoryAction.NOTHING : InventoryAction.PLACE_FROM_BUNDLE;
|
||||
+ } else {
|
||||
+ action = packet.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE;
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (slot.mayPickup(this.player)) {
|
||||
+ if (cursor.isEmpty()) {
|
||||
+ action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF;
|
||||
+ if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && slot.getItem().has(DataComponents.BUNDLE_CONTENTS) && packet.getButtonNum() != 0) {
|
||||
+ action = slot.getItem().get(DataComponents.BUNDLE_CONTENTS).isEmpty() ? InventoryAction.NOTHING : InventoryAction.PICKUP_FROM_BUNDLE;
|
||||
+ } else {
|
||||
+ action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF;
|
||||
+ }
|
||||
+ } else if (slot.mayPlace(cursor)) {
|
||||
+ if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
|
||||
+ int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1;
|
||||
@@ -2076,7 +2132,27 @@
|
||||
+ action = InventoryAction.PLACE_SOME;
|
||||
+ }
|
||||
+ } else if (cursor.getCount() <= slot.getMaxStackSize()) {
|
||||
+ action = InventoryAction.SWAP_WITH_CURSOR;
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && cursor.has(DataComponents.BUNDLE_CONTENTS) && packet.getButtonNum() == 0) {
|
||||
+ int toPickup = cursor.get(DataComponents.BUNDLE_CONTENTS).getMaxAmountToAdd(slot.getItem());
|
||||
+ if (toPickup >= slot.getItem().getCount()) {
|
||||
+ action = InventoryAction.PICKUP_ALL_INTO_BUNDLE;
|
||||
+ } else if (toPickup == 0) {
|
||||
+ action = InventoryAction.NOTHING;
|
||||
+ } else {
|
||||
+ action = InventoryAction.PICKUP_SOME_INTO_BUNDLE;
|
||||
+ }
|
||||
+ } else if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && slot.getItem().has(DataComponents.BUNDLE_CONTENTS) && packet.getButtonNum() == 0) {
|
||||
+ int toPickup = slot.getItem().get(DataComponents.BUNDLE_CONTENTS).getMaxAmountToAdd(cursor);
|
||||
+ if (toPickup >= cursor.getCount()) {
|
||||
+ action = InventoryAction.PLACE_ALL_INTO_BUNDLE;
|
||||
+ } else if (toPickup == 0) {
|
||||
+ action = InventoryAction.NOTHING;
|
||||
+ } else {
|
||||
+ action = InventoryAction.PLACE_SOME_INTO_BUNDLE;
|
||||
+ }
|
||||
+ } else {
|
||||
+ action = InventoryAction.SWAP_WITH_CURSOR;
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
|
||||
+ if (clickedItem.getCount() >= 0) {
|
||||
@@ -2332,6 +2408,14 @@
|
||||
|
||||
for (Entry<ItemStack> entry : Int2ObjectMaps.fastIterable(packet.getChangedSlots())) {
|
||||
this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), entry.getValue());
|
||||
@@ -1726,6 +_,7 @@
|
||||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
}
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1733,6 +_,14 @@
|
||||
|
||||
@Override
|
||||
@@ -2401,7 +2485,15 @@
|
||||
this.player.resetLastActionTime();
|
||||
if (this.player.containerMenu.containerId == packet.containerId() && !this.player.isSpectator()) {
|
||||
if (!this.player.containerMenu.stillValid(this.player)) {
|
||||
@@ -1792,6 +_,43 @@
|
||||
@@ -1776,6 +_,7 @@
|
||||
if (flag) {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
}
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1792,10 +_,48 @@
|
||||
|
||||
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
|
||||
boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
|
||||
@@ -2445,6 +2537,11 @@
|
||||
if (flag1 && flag2) {
|
||||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes.
|
||||
} else if (flag && flag2) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
this.dropSpamThrottler.increment();
|
||||
@@ -1809,11 +_,24 @@
|
||||
|
||||
@Override
|
||||
@@ -2551,7 +2648,7 @@
|
||||
this.signedMessageDecoder = chatSession.createMessageDecoder(this.player.getUUID());
|
||||
this.chatMessageChain
|
||||
.append(
|
||||
@@ -1919,15 +_,17 @@
|
||||
@@ -1919,19 +_,22 @@
|
||||
this.server
|
||||
.getPlayerList()
|
||||
.broadcastAll(
|
||||
@@ -2573,6 +2670,11 @@
|
||||
|
||||
@Override
|
||||
public void handleClientTickEnd(ServerboundClientTickEndPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
+ this.tickEndEvent.callEvent(); // Paper - add client tick end event
|
||||
if (!this.receivedMovementThisTick) {
|
||||
this.player.setKnownMovement(Vec3.ZERO);
|
||||
}
|
||||
@@ -1957,4 +_,17 @@
|
||||
interface EntityInteraction {
|
||||
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
|
||||
|
||||
@@ -931,14 +931,19 @@
|
||||
}
|
||||
|
||||
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
|
||||
@@ -671,8 +_,16 @@
|
||||
@@ -671,8 +_,21 @@
|
||||
|
||||
public void sendAllPlayerInfo(ServerPlayer player) {
|
||||
player.inventoryMenu.sendAllDataToRemote();
|
||||
- player.resetSentInfo();
|
||||
+ // entityplayer.resetSentInfo();
|
||||
+ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
|
||||
+ player.refreshEntityData(player); // CraftBukkkit - SPIGOT-7218: sync metadata
|
||||
+ // Paper start - send all attributes
|
||||
+ // needs to be done because the ServerPlayer instance is being reused on respawn instead of getting replaced like on vanilla
|
||||
+ java.util.Collection<net.minecraft.world.entity.ai.attributes.AttributeInstance> syncableAttributes = player.getAttributes().getSyncableAttributes();
|
||||
+ player.getBukkitEntity().injectScaledMaxHealth(syncableAttributes, true);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket(player.getId(), syncableAttributes));
|
||||
+ // Paper end - send all attributes
|
||||
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
|
||||
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
|
||||
+ // CraftBukkit start - from GameRules
|
||||
+ int i = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
this.setLootTable(lootTable);
|
||||
this.setLootTableSeed(seed);
|
||||
}
|
||||
@@ -50,14 +_,15 @@
|
||||
@@ -50,15 +_,17 @@
|
||||
|
||||
default boolean tryLoadLootTable(CompoundTag tag) {
|
||||
if (tag.contains("LootTable", 8)) {
|
||||
@@ -25,8 +25,10 @@
|
||||
- return true;
|
||||
+ return this.lootableData() == null; // Paper - only track the loot table if there is chance for replenish
|
||||
} else {
|
||||
+ setLootTable(null); // Paper - Fix removing loottable from nbt not updating block entity, MC-279196
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -69,26 +_,42 @@
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -1,127 +1,95 @@
|
||||
--- a/net/minecraft/world/damagesource/DamageSource.java
|
||||
+++ b/net/minecraft/world/damagesource/DamageSource.java
|
||||
@@ -20,6 +_,105 @@
|
||||
@@ -20,6 +_,92 @@
|
||||
private final Entity directEntity;
|
||||
@Nullable
|
||||
private final Vec3 damageSourcePosition;
|
||||
+ // CraftBukkit start
|
||||
+ @Nullable
|
||||
+ private org.bukkit.block.Block directBlock; // The block that caused the damage. damageSourcePosition is not used for all block damages
|
||||
+ private org.bukkit.event.entity.EntityDamageEvent.DamageCause knownCause; // When the damage event cause is known by the context of the call rather than the damage source data
|
||||
+ @Nullable
|
||||
+ private org.bukkit.block.BlockState directBlockState; // The block state of the block relevant to this damage source
|
||||
+ private boolean sweep = false;
|
||||
+ private boolean melting = false;
|
||||
+ private boolean poison = false;
|
||||
+ private Entity eventEntityDamager = null; // Relevant entity set when the game doesn't normally set a causingEntity/directEntity
|
||||
+ @Nullable
|
||||
+ private Entity customEventDamager = null; // This field is a helper for when causing entity damage is not set by vanilla // Paper - fix DamageSource API
|
||||
+
|
||||
+ public DamageSource sweep() {
|
||||
+ this.sweep = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isSweep() {
|
||||
+ return this.sweep;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource melting() {
|
||||
+ this.melting = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isMelting() {
|
||||
+ return this.melting;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource poison() {
|
||||
+ this.poison = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isPoison() {
|
||||
+ return this.poison;
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - fix DamageSource API
|
||||
+ private org.bukkit.block.Block eventBlockDamager; // Relevant block set. damageSourcePosition is only used for bad respawn point explosion or custom damage
|
||||
+ @Nullable
|
||||
+ public Entity getCustomEventDamager() {
|
||||
+ return (this.customEventDamager != null) ? this.customEventDamager : this.directEntity;
|
||||
+ private org.bukkit.block.BlockState fromBlockSnapshot; // Captured block snapshot when the eventBlockDamager is not relevant (e.g. for bad respawn point explosions the block is already removed)
|
||||
+ private boolean critical; // Supports arrows and sweeping damage
|
||||
+
|
||||
+ public DamageSource knownCause(final org.bukkit.event.entity.EntityDamageEvent.DamageCause cause) {
|
||||
+ final DamageSource damageSource = this.copy();
|
||||
+ damageSource.knownCause = cause;
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource customEventDamager(Entity entity) {
|
||||
+ @Nullable
|
||||
+ public org.bukkit.event.entity.EntityDamageEvent.DamageCause knownCause() {
|
||||
+ return this.knownCause;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public Entity eventEntityDamager() {
|
||||
+ return this.eventEntityDamager;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource eventEntityDamager(final Entity entity) {
|
||||
+ if (this.directEntity != null) {
|
||||
+ throw new IllegalStateException("Cannot set custom event damager when direct entity is already set (report a bug to Paper)");
|
||||
+ throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (report a bug to Paper)");
|
||||
+ }
|
||||
+ DamageSource damageSource = this.cloneInstance();
|
||||
+ damageSource.customEventDamager = entity;
|
||||
+ // Paper end - fix DamageSource API
|
||||
+ final DamageSource damageSource = this.copy();
|
||||
+ damageSource.eventEntityDamager = entity;
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.block.Block getDirectBlock() {
|
||||
+ return this.directBlock;
|
||||
+ @Nullable
|
||||
+ public org.bukkit.block.Block eventBlockDamager() {
|
||||
+ return this.eventBlockDamager;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource directBlock(net.minecraft.world.level.Level world, net.minecraft.core.BlockPos blockPosition) {
|
||||
+ if (blockPosition == null || world == null) {
|
||||
+ public DamageSource eventBlockDamager(final @Nullable net.minecraft.world.level.LevelAccessor level, final @Nullable net.minecraft.core.BlockPos pos) {
|
||||
+ if (pos == null) {
|
||||
+ return this;
|
||||
+ }
|
||||
+ return this.directBlock(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockPosition));
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource directBlock(org.bukkit.block.Block block) {
|
||||
+ if (block == null) {
|
||||
+ return this;
|
||||
+ }
|
||||
+ // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources
|
||||
+ DamageSource damageSource = this.cloneInstance();
|
||||
+ damageSource.directBlock = block;
|
||||
+ final DamageSource damageSource = this.copy();
|
||||
+ damageSource.eventBlockDamager = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.block.BlockState getDirectBlockState() {
|
||||
+ return this.directBlockState;
|
||||
+ @Nullable
|
||||
+ public org.bukkit.block.BlockState causingBlockSnapshot() {
|
||||
+ return this.fromBlockSnapshot;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource directBlockState(org.bukkit.block.BlockState blockState) {
|
||||
+ if (blockState == null) {
|
||||
+ return this;
|
||||
+ public DamageSource causingBlockSnapshot(final @Nullable org.bukkit.block.BlockState blockState) {
|
||||
+ if (this.eventBlockDamager != null) {
|
||||
+ throw new IllegalStateException("Cannot set a block snapshot when an event block damager is already set (report a bug to Paper)");
|
||||
+ }
|
||||
+ // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources
|
||||
+ DamageSource damageSource = this.cloneInstance();
|
||||
+ damageSource.directBlockState = blockState;
|
||||
+ final DamageSource damageSource = this.copy();
|
||||
+ damageSource.fromBlockSnapshot = blockState;
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+
|
||||
+ private DamageSource cloneInstance() {
|
||||
+ DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition);
|
||||
+ damageSource.directBlock = this.getDirectBlock();
|
||||
+ damageSource.directBlockState = this.getDirectBlockState();
|
||||
+ damageSource.sweep = this.isSweep();
|
||||
+ damageSource.poison = this.isPoison();
|
||||
+ damageSource.melting = this.isMelting();
|
||||
+ public boolean isCritical() {
|
||||
+ return this.critical;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource critical() {
|
||||
+ final DamageSource damageSource = this.copy();
|
||||
+ damageSource.critical = true;
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+
|
||||
+ // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources
|
||||
+ private DamageSource copy() {
|
||||
+ final DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition);
|
||||
+ damageSource.knownCause = this.knownCause;
|
||||
+ damageSource.eventEntityDamager = this.eventEntityDamager;
|
||||
+ damageSource.eventBlockDamager = this.eventBlockDamager;
|
||||
+ damageSource.fromBlockSnapshot = this.fromBlockSnapshot;
|
||||
+ damageSource.critical = this.critical;
|
||||
+ return damageSource;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -134,4 +_,18 @@
|
||||
public Holder<DamageType> typeHolder() {
|
||||
return this.type;
|
||||
}
|
||||
+
|
||||
+ // Paper start - add critical damage API
|
||||
+ private boolean critical;
|
||||
+ public boolean isCritical() {
|
||||
+ return this.critical;
|
||||
+ }
|
||||
+ public DamageSource critical() {
|
||||
+ return this.critical(true);
|
||||
+ }
|
||||
+ public DamageSource critical(boolean critical) {
|
||||
+ this.critical = critical;
|
||||
+ return this;
|
||||
+ }
|
||||
+ // Paper end - add critical damage API
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
--- a/net/minecraft/world/damagesource/DamageSources.java
|
||||
+++ b/net/minecraft/world/damagesource/DamageSources.java
|
||||
@@ -42,9 +_,15 @@
|
||||
private final DamageSource stalagmite;
|
||||
private final DamageSource outsideBorder;
|
||||
private final DamageSource genericKill;
|
||||
+ // CraftBukkit start
|
||||
+ private final DamageSource melting;
|
||||
+ private final DamageSource poison;
|
||||
|
||||
public DamageSources(RegistryAccess registry) {
|
||||
this.damageTypes = registry.lookupOrThrow(Registries.DAMAGE_TYPE);
|
||||
+ this.melting = this.source(DamageTypes.ON_FIRE).melting();
|
||||
+ this.poison = this.source(DamageTypes.MAGIC).poison();
|
||||
+ // CraftBukkit end
|
||||
this.inFire = this.source(DamageTypes.IN_FIRE);
|
||||
this.campfire = this.source(DamageTypes.CAMPFIRE);
|
||||
this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT);
|
||||
@@ -84,6 +_,16 @@
|
||||
return new DamageSource(this.damageTypes.getOrThrow(damageTypeKey), causingEntity, directEntity);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public DamageSource melting() {
|
||||
+ return this.melting;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource poison() {
|
||||
+ return this.poison;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public DamageSource inFire() {
|
||||
return this.inFire;
|
||||
}
|
||||
@@ -261,7 +_,13 @@
|
||||
}
|
||||
|
||||
public DamageSource badRespawnPointExplosion(Vec3 position) {
|
||||
- return new DamageSource(this.damageTypes.getOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
|
||||
+ // CraftBukkit start
|
||||
+ return this.badRespawnPointExplosion(position, null);
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource badRespawnPointExplosion(Vec3 position, org.bukkit.block.BlockState blockState) {
|
||||
+ return new DamageSource(this.damageTypes.getOrThrow(DamageTypes.BAD_RESPAWN_POINT), position).directBlockState(blockState);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public DamageSource outOfBorder() {
|
||||
@@ -9,8 +9,11 @@
|
||||
} else {
|
||||
entity.hurtServer(level, entity.damageSources().magic(), 6 << amplifier);
|
||||
}
|
||||
@@ -30,7 +_,7 @@
|
||||
@@ -28,9 +_,10 @@
|
||||
public void applyInstantenousEffect(
|
||||
ServerLevel level, @Nullable Entity source, @Nullable Entity indirectSource, LivingEntity entity, int amplifier, double health
|
||||
) {
|
||||
+ if (!new io.papermc.paper.event.entity.EntityEffectTickEvent(entity.getBukkitLivingEntity(), org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftToBukkit(this), amplifier).callEvent()) { return; } // Paper - Add EntityEffectTickEvent
|
||||
if (this.isHarm == entity.isInvertedHealAndHarm()) {
|
||||
int i = (int)(health * (4 << amplifier) + 0.5);
|
||||
- entity.heal(i);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/effect/MobEffect.java
|
||||
+++ b/net/minecraft/world/effect/MobEffect.java
|
||||
@@ -76,6 +_,7 @@
|
||||
public void applyInstantenousEffect(
|
||||
ServerLevel level, @Nullable Entity source, @Nullable Entity indirectSource, LivingEntity entity, int amplifier, double health
|
||||
) {
|
||||
+ if (!new io.papermc.paper.event.entity.EntityEffectTickEvent(entity.getBukkitLivingEntity(), org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftToBukkit(this), amplifier).callEvent()) { return; } // Paper - Add EntityEffectTickEvent
|
||||
this.applyEffectTick(level, entity, amplifier);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
--- a/net/minecraft/world/effect/MobEffectInstance.java
|
||||
+++ b/net/minecraft/world/effect/MobEffectInstance.java
|
||||
@@ -216,6 +_,7 @@
|
||||
int i = this.isInfiniteDuration() ? entity.tickCount : this.duration;
|
||||
if (entity.level() instanceof ServerLevel serverLevel
|
||||
&& this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier)
|
||||
+ && new io.papermc.paper.event.entity.EntityEffectTickEvent(entity.getBukkitLivingEntity(), org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftHolderToBukkit(this.effect), this.amplifier).callEvent() // Paper - Add EntityEffectTickEvent
|
||||
&& !this.effect.value().applyEffectTick(serverLevel, entity, this.amplifier)) {
|
||||
entity.removeEffect(this.effect);
|
||||
}
|
||||
@@ -408,7 +_,7 @@
|
||||
.apply(instance, MobEffectInstance.Details::create)
|
||||
)
|
||||
);
|
||||
- public static final StreamCodec<ByteBuf, MobEffectInstance.Details> STREAM_CODEC = StreamCodec.recursive(
|
||||
+ public static final StreamCodec<net.minecraft.network.FriendlyByteBuf, MobEffectInstance.Details> STREAM_CODEC = StreamCodec.recursive( // Paper - Track codec depth
|
||||
codec -> StreamCodec.composite(
|
||||
ByteBufCodecs.VAR_INT,
|
||||
MobEffectInstance.Details::amplifier,
|
||||
@@ -420,7 +_,7 @@
|
||||
MobEffectInstance.Details::showParticles,
|
||||
ByteBufCodecs.BOOL,
|
||||
MobEffectInstance.Details::showIcon,
|
||||
- codec.apply(ByteBufCodecs::optional),
|
||||
+ codec.apply(ByteBufCodecs::increaseDepth).apply(ByteBufCodecs::optional), // Paper - Track codec depth
|
||||
MobEffectInstance.Details::hiddenEffect,
|
||||
MobEffectInstance.Details::new
|
||||
)
|
||||
@@ -5,7 +5,7 @@
|
||||
public boolean applyEffectTick(ServerLevel level, LivingEntity entity, int amplifier) {
|
||||
if (entity.getHealth() > 1.0F) {
|
||||
- entity.hurtServer(level, entity.damageSources().magic(), 1.0F);
|
||||
+ entity.hurtServer(level, entity.damageSources().poison(), 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON
|
||||
+ entity.hurtServer(level, entity.damageSources().magic().knownCause(org.bukkit.event.entity.EntityDamageEvent.DamageCause.POISON), 1.0F); // CraftBukkit
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
+ // Paper end - Share random for entities to make them more random
|
||||
+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
||||
+
|
||||
+ private org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
|
||||
+ private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
|
||||
+
|
||||
+ public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
|
||||
+ if (this.bukkitEntity == null) {
|
||||
@@ -101,7 +101,7 @@
|
||||
+ return this.bukkitEntity;
|
||||
+ }
|
||||
+ // Paper start
|
||||
+ public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntityRaw() {
|
||||
+ public @Nullable org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntityRaw() {
|
||||
+ return this.bukkitEntity;
|
||||
+ }
|
||||
+ // Paper end
|
||||
@@ -127,7 +127,7 @@
|
||||
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
|
||||
private long pistonDeltasGameTime;
|
||||
private EntityDimensions dimensions;
|
||||
@@ -250,6 +_,63 @@
|
||||
@@ -250,6 +_,60 @@
|
||||
private final List<Entity.Movement> movementThisTick = new ArrayList<>();
|
||||
private final Set<BlockState> blocksInside = new ReferenceArraySet<>();
|
||||
private final LongSet visitedBlocks = new LongOpenHashSet();
|
||||
@@ -158,6 +158,7 @@
|
||||
+ public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
|
||||
+ public boolean fixedPose = false; // Paper - Expand Pose API
|
||||
+ 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
|
||||
+
|
||||
+ public void setOrigin(@javax.annotation.Nonnull org.bukkit.Location location) {
|
||||
@@ -178,10 +179,6 @@
|
||||
+ public float getBukkitYaw() {
|
||||
+ return this.yRot;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isChunkLoaded() {
|
||||
+ return this.level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start
|
||||
+ public final AABB getBoundingBoxAt(double x, double y, double z) {
|
||||
@@ -195,7 +192,7 @@
|
||||
this.entityData = builder.build();
|
||||
this.setPos(0.0, 0.0, 0.0);
|
||||
this.eyeHeight = this.dimensions.eyeHeight();
|
||||
+ this.despawnTime = type == EntityType.PLAYER ? -1 : level.paperConfig().entities.spawning.despawnTime.getOrDefault(type, io.papermc.paper.configuration.type.number.IntOr.Disabled.DISABLED).or(-1); // Paper - entity despawn time limit
|
||||
+ this.despawnTime = level == null || type == EntityType.PLAYER ? -1 : level.paperConfig().entities.spawning.despawnTime.getOrDefault(type, io.papermc.paper.configuration.type.number.IntOr.Disabled.DISABLED).or(-1); // Paper - entity despawn time limit
|
||||
}
|
||||
|
||||
public boolean isColliding(BlockPos pos, BlockState state) {
|
||||
@@ -373,7 +370,7 @@
|
||||
|
||||
public void tick() {
|
||||
+ // Paper start - entity despawn time limit
|
||||
+ if (this.despawnTime >= 0 && this.tickCount >= this.despawnTime) {
|
||||
+ if (this.despawnTime >= 0 && this.totalEntityAge >= this.despawnTime) {
|
||||
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN);
|
||||
+ return;
|
||||
+ }
|
||||
@@ -463,7 +460,7 @@
|
||||
+ // CraftBukkit end
|
||||
if (this.level() instanceof ServerLevel serverLevel
|
||||
- && this.hurtServer(serverLevel, this.damageSources().lava(), 4.0F)
|
||||
+ && this.hurtServer(serverLevel, this.damageSources().lava().directBlock(this.level, this.lastLavaContact), 4.0F) // CraftBukkit - we also don't throw an event unless the object in lava is living, to save on some event calls
|
||||
+ && this.hurtServer(serverLevel, this.damageSources().lava().eventBlockDamager(this.level, this.lastLavaContact), 4.0F) // CraftBukkit - we also don't throw an event unless the object in lava is living, to save on some event calls
|
||||
&& this.shouldPlayLavaHurtSound()
|
||||
&& !this.isSilent()) {
|
||||
serverLevel.playSound(
|
||||
@@ -802,7 +799,7 @@
|
||||
+ if (this.maxAirTicks != this.getDefaultMaxAirSupply()) {
|
||||
+ compound.putInt("Bukkit.MaxAirSupply", this.getMaxAirSupply());
|
||||
+ }
|
||||
+ compound.putInt("Spigot.ticksLived", this.tickCount);
|
||||
+ compound.putInt("Spigot.ticksLived", this.totalEntityAge); // Paper
|
||||
+ // CraftBukkit end
|
||||
Component customName = this.getCustomName();
|
||||
if (customName != null) {
|
||||
@@ -864,7 +861,7 @@
|
||||
+ // CraftBukkit start
|
||||
+ // Spigot start
|
||||
+ if (this instanceof net.minecraft.world.entity.LivingEntity) {
|
||||
+ this.tickCount = compound.getInt("Spigot.ticksLived");
|
||||
+ this.totalEntityAge = compound.getInt("Spigot.ticksLived"); // Paper
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist");
|
||||
@@ -1304,7 +1301,7 @@
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!this.hurtServer(level, this.damageSources().lightningBolt().customEventDamager(lightning), 5.0F)) { // Paper - fix DamageSource API
|
||||
+ if (!this.hurtServer(level, this.damageSources().lightningBolt().eventEntityDamager(lightning), 5.0F)) { // Paper - fix DamageSource API
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
public boolean skipAttackInteraction(Entity entity) {
|
||||
if (entity instanceof Player player) {
|
||||
+ // CraftBukkit start
|
||||
+ DamageSource source = player.damageSources().playerAttack(player);
|
||||
+ DamageSource source = player.damageSources().generic().eventEntityDamager(entity);
|
||||
+ org.bukkit.event.entity.EntityDamageEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return true;
|
||||
@@ -14,7 +14,7 @@
|
||||
this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime());
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, player.damageSources().generic(), 1.0F, 1.0F, false);
|
||||
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, player.damageSources().generic(), 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit // Paper - use correct source and fix taken/dealt param order
|
||||
+ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, source, 1.0F, (float) event.getFinalDamage(), false); // CraftBukkit // Paper - use correct source and fix taken/dealt param order
|
||||
}
|
||||
|
||||
return !this.getResponse();
|
||||
|
||||
@@ -678,7 +678,7 @@
|
||||
+ event.setCancelled(itemStack == null);
|
||||
+ this.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Set death protection to null as the event was cancelled. Prevent any attempt at ressurection.
|
||||
+ // Set death protection to null as the event was cancelled. Prevent any attempt at resurrection.
|
||||
+ deathProtection = null;
|
||||
+ } else {
|
||||
+ if (!itemInHand.isEmpty() && itemStack != null) { // Paper - only reduce item if actual totem was found
|
||||
@@ -691,7 +691,7 @@
|
||||
- if (this instanceof ServerPlayer serverPlayer) {
|
||||
+ }
|
||||
+ // Paper start - fix NPE when pre-cancelled EntityResurrectEvent is uncancelled
|
||||
+ // restore the previous behavior in that case by defaulting to vanillas totem of undying efect
|
||||
+ // restore the previous behavior in that case by defaulting to vanillas totem of undying effect
|
||||
+ if (deathProtection == null) {
|
||||
+ deathProtection = DeathProtection.TOTEM_OF_UNDYING;
|
||||
+ }
|
||||
@@ -971,7 +971,7 @@
|
||||
int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5;
|
||||
int i1 = 25 - i;
|
||||
float f = damageAmount * i1;
|
||||
@@ -1768,24 +_,212 @@
|
||||
@@ -1768,24 +_,219 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,7 +984,11 @@
|
||||
+ if (invulnerabilityRelatedLastDamage == 0) return 0D; // no last damage, no reduction
|
||||
+ // last damage existed, this means the reduction *technically* is (new damage - last damage).
|
||||
+ // If the event damage was changed to something less than invul damage, hard lock it at 0.
|
||||
+ if (d < invulnerabilityRelatedLastDamage) return 0D;
|
||||
+ //
|
||||
+ // Cast the passed in double down to a float as double -> float -> double is lossy.
|
||||
+ // If last damage is a (float) 3.2D (since the events use doubles), we cannot compare
|
||||
+ // the new damage value of this damage instance by upcasting it again to a double as 3.2D != (double) (float) 3.2D.
|
||||
+ if (d.floatValue() < invulnerabilityRelatedLastDamage) return 0D;
|
||||
+ return (double) -invulnerabilityRelatedLastDamage;
|
||||
+ };
|
||||
+ final float originalInvulnerabilityReduction = invulnerabilityReductionEquation.apply((double) amount).floatValue();
|
||||
@@ -1118,7 +1122,10 @@
|
||||
+
|
||||
+ // Apply damage to armor
|
||||
+ if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) {
|
||||
+ float armorDamage = (float) (event.getDamage() + event.getDamage(DamageModifier.BLOCKING) + event.getDamage(DamageModifier.HARD_HAT));
|
||||
+ float armorDamage = (float) event.getDamage();
|
||||
+ armorDamage += (float) event.getDamage(DamageModifier.INVULNERABILITY_REDUCTION);
|
||||
+ armorDamage += (float) event.getDamage(DamageModifier.BLOCKING);
|
||||
+ armorDamage += (float) event.getDamage(DamageModifier.HARD_HAT);
|
||||
+ this.hurtArmor(damageSource, armorDamage);
|
||||
+ }
|
||||
+
|
||||
@@ -1336,20 +1343,57 @@
|
||||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
|
||||
if (map != null) {
|
||||
this.handleHandSwap(map);
|
||||
@@ -2595,6 +_,13 @@
|
||||
@@ -2586,6 +_,20 @@
|
||||
@Nullable
|
||||
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
|
||||
Map<EquipmentSlot, ItemStack> map = null;
|
||||
+ // Paper start - EntityEquipmentChangedEvent
|
||||
+ record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange {
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.ItemStack oldItem() {
|
||||
+ return this.oldItem.clone();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.ItemStack newItem() {
|
||||
+ return this.newItem.clone();
|
||||
+ }
|
||||
+ }
|
||||
+ Map<org.bukkit.inventory.EquipmentSlot, io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange> equipmentChanges = null;
|
||||
+ // Paper end - EntityEquipmentChangedEvent
|
||||
|
||||
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
|
||||
ItemStack itemStack = switch (equipmentSlot.getType()) {
|
||||
@@ -2595,11 +_,20 @@
|
||||
};
|
||||
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
|
||||
if (this.equipmentHasChanged(itemStack, itemBySlot)) {
|
||||
+ // Paper start - PlayerArmorChangeEvent
|
||||
+ // Paper start - EntityEquipmentChangedEvent, PlayerArmorChangeEvent
|
||||
+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemStack);
|
||||
+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemBySlot);
|
||||
+ if (this instanceof ServerPlayer && equipmentSlot.getType() == EquipmentSlot.Type.HUMANOID_ARMOR) {
|
||||
+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemStack);
|
||||
+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemBySlot);
|
||||
+ new com.destroystokyo.paper.event.player.PlayerArmorChangeEvent((org.bukkit.entity.Player) this.getBukkitEntity(), com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.valueOf(equipmentSlot.name()), oldItem, newItem).callEvent();
|
||||
+ }
|
||||
+ // Paper end - PlayerArmorChangeEvent
|
||||
+ // Paper end - EntityEquipmentChangedEvent, PlayerArmorChangeEvent
|
||||
if (map == null) {
|
||||
map = Maps.newEnumMap(EquipmentSlot.class);
|
||||
+ equipmentChanges = Maps.newEnumMap(org.bukkit.inventory.EquipmentSlot.class); // Paper - EntityEquipmentChangedEvent
|
||||
}
|
||||
|
||||
map.put(equipmentSlot, itemBySlot);
|
||||
+ equipmentChanges.put(org.bukkit.craftbukkit.CraftEquipmentSlot.getSlot(equipmentSlot), new EquipmentChangeImpl(oldItem, newItem)); // Paper - EntityEquipmentChangedEvent
|
||||
AttributeMap attributes = this.getAttributes();
|
||||
if (!itemStack.isEmpty()) {
|
||||
this.stopLocationBasedEffects(itemStack, equipmentSlot, attributes);
|
||||
@@ -2624,6 +_,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ new io.papermc.paper.event.entity.EntityEquipmentChangedEvent(this.getBukkitLivingEntity(), equipmentChanges).callEvent(); // Paper - EntityEquipmentChangedEvent
|
||||
}
|
||||
|
||||
return map;
|
||||
@@ -2664,7 +_,7 @@
|
||||
this.lastBodyItemStack = itemStack;
|
||||
}
|
||||
|
||||
@@ -326,6 +326,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -981,7 +_,9 @@
|
||||
double d = this.getEquipmentDropChance(equipmentSlot);
|
||||
if (d > 1.0) {
|
||||
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
|
||||
+ this.forceDrops = true; // Paper - Add missing forceDrop toggles
|
||||
this.spawnAtLocation(level, itemBySlot);
|
||||
+ this.forceDrops = false; // Paper - Add missing forceDrop toggles
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1269,6 +_,22 @@
|
||||
public <T extends Mob> T convertTo(
|
||||
EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java
|
||||
@@ -22,13 +_,32 @@
|
||||
level.getPoiManager()
|
||||
.getType(globalPos.pos())
|
||||
.ifPresent(
|
||||
- poi -> instance.<List<LivingEntity>>get(nearestLivingEntities)
|
||||
- .stream()
|
||||
- .filter(entity -> entity instanceof Villager && entity != villager)
|
||||
- .map(entity -> (Villager)entity)
|
||||
- .filter(LivingEntity::isAlive)
|
||||
- .filter(v -> competesForSameJobsite(globalPos, poi, v))
|
||||
- .reduce(villager, PoiCompetitorScan::selectWinner)
|
||||
+ // Paper start - Improve performance of PoiCompetitorScan by unrolling stream
|
||||
+ // The previous logic used Stream#reduce to simulate a form of single-iteration bubble sort
|
||||
+ // in which the "winning" villager would maintain MemoryModuleType.JOB_SITE while all others
|
||||
+ // would lose said memory module type by passing each "current winner" and incoming next
|
||||
+ // villager to #selectWinner.
|
||||
+ poi -> {
|
||||
+ final List<LivingEntity> livingEntities = instance.get(nearestLivingEntities);
|
||||
+
|
||||
+ Villager winner = villager;
|
||||
+ for (final LivingEntity other : livingEntities) {
|
||||
+ if (other == villager) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!(other instanceof final net.minecraft.world.entity.npc.Villager otherVillager)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!other.isAlive()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!competesForSameJobsite(globalPos, poi, otherVillager)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ winner = selectWinner(winner, otherVillager);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Improve performance of PoiCompetitorScan by unrolling stream
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
+ parent.setAge(6000);
|
||||
+ partner.setAge(6000);
|
||||
+ level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
|
||||
+ // CraftBukkit end
|
||||
+ // CraftBukkit end - call EntityBreedEvent
|
||||
level.broadcastEntityEvent(breedOffspring, (byte)12);
|
||||
return Optional.of(breedOffspring);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/world/entity/animal/AgeableWaterCreature.java
|
||||
+++ b/net/minecraft/world/entity/animal/AgeableWaterCreature.java
|
||||
@@ -68,6 +_,10 @@
|
||||
) {
|
||||
int seaLevel = level.getSeaLevel();
|
||||
int i = seaLevel - 13;
|
||||
+ // Paper start - Make water animal spawn height configurable
|
||||
+ seaLevel = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(seaLevel);
|
||||
+ i = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(i);
|
||||
+ // Paper end - Make water animal spawn height configurable
|
||||
return pos.getY() >= i
|
||||
&& pos.getY() <= seaLevel
|
||||
&& level.getFluidState(pos.below()).is(FluidTags.WATER)
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
this.level().broadcastEntityEvent(this, (byte)18);
|
||||
}
|
||||
@@ -220,23 +_,45 @@
|
||||
@@ -220,23 +_,44 @@
|
||||
if (breedOffspring != null) {
|
||||
breedOffspring.setBaby(true);
|
||||
breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
|
||||
@@ -74,43 +74,43 @@
|
||||
+ int experience = this.getRandom().nextInt(7) + 1;
|
||||
+ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, this, mate, breeder, this.breedItem, experience);
|
||||
+ if (entityBreedEvent.isCancelled()) {
|
||||
+ this.resetLove();
|
||||
+ mate.resetLove();
|
||||
+ return;
|
||||
+ }
|
||||
+ experience = entityBreedEvent.getExperience();
|
||||
+ this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring, experience);
|
||||
+ level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
|
||||
+ // CraftBukkit end
|
||||
+ // CraftBukkit end - call EntityBreedEvent
|
||||
}
|
||||
}
|
||||
|
||||
public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) {
|
||||
- Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(animal.getLoveCause())).ifPresent(player -> {
|
||||
+ // CraftBukkit start
|
||||
+ // CraftBukkit start - call EntityBreedEvent
|
||||
+ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1);
|
||||
+ }
|
||||
+
|
||||
+ public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby, int experience) {
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start
|
||||
+ // CraftBukkit end - call EntityBreedEvent
|
||||
+ // Paper start - call EntityBreedEvent
|
||||
+ ServerPlayer player = this.getLoveCause();
|
||||
+ if (player == null) player = animal.getLoveCause();
|
||||
+ if (player != null) {
|
||||
+ // Paper end
|
||||
+ // Paper end - call EntityBreedEvent
|
||||
player.awardStat(Stats.ANIMALS_BRED);
|
||||
CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby);
|
||||
- });
|
||||
+ } // Paper
|
||||
+ } // Paper - call EntityBreedEvent
|
||||
this.setAge(6000);
|
||||
animal.setAge(6000);
|
||||
this.resetLove();
|
||||
animal.resetLove();
|
||||
level.broadcastEntityEvent(this, (byte)18);
|
||||
if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
|
||||
+ // CraftBukkit start - use event experience
|
||||
+ if (experience > 0) {
|
||||
+ level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, player, baby)); // Paper
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (experience > 0 && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - call EntityBreedEvent
|
||||
+ level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, player, baby)); // Paper - call EntityBreedEvent, add spawn context
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
}
|
||||
|
||||
public static boolean isPathClear(Fox fox, LivingEntity livingEntity) {
|
||||
@@ -853,6 +_,14 @@
|
||||
@@ -853,6 +_,18 @@
|
||||
if (loveCause1 != null && loveCause != loveCause1) {
|
||||
fox.addTrustedUUID(loveCause1.getUUID());
|
||||
}
|
||||
@@ -102,13 +102,17 @@
|
||||
+ fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F);
|
||||
+ int experience = this.animal.getRandom().nextInt(7) + 1;
|
||||
+ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(fox, this.animal, this.partner, loveCause, this.animal.breedItem, experience);
|
||||
+ if (entityBreedEvent.isCancelled()) return;
|
||||
+ if (entityBreedEvent.isCancelled()) {
|
||||
+ this.animal.resetLove();
|
||||
+ this.partner.resetLove();
|
||||
+ return;
|
||||
+ }
|
||||
+ experience = entityBreedEvent.getExperience();
|
||||
+ // CraftBukkit end
|
||||
+ // CraftBukkit end - call EntityBreedEvent
|
||||
|
||||
if (serverPlayer != null) {
|
||||
serverPlayer.awardStat(Stats.ANIMALS_BRED);
|
||||
@@ -863,15 +_,17 @@
|
||||
@@ -863,14 +_,12 @@
|
||||
this.partner.setAge(6000);
|
||||
this.animal.resetLove();
|
||||
this.partner.resetLove();
|
||||
@@ -117,22 +121,15 @@
|
||||
- serverLevel.addFreshEntityWithPassengers(fox);
|
||||
+ serverLevel.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
|
||||
this.level.broadcastEntityEvent(this.animal, (byte)18);
|
||||
if (serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- this.level
|
||||
- .addFreshEntity(
|
||||
- if (serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
+ if (experience > 0 && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - call EntityBreedEvent
|
||||
this.level
|
||||
.addFreshEntity(
|
||||
- new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1)
|
||||
- );
|
||||
+ // CraftBukkit start - use event experience
|
||||
+ if (experience > 0) {
|
||||
+ this.level
|
||||
+ .addFreshEntity(
|
||||
+ new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, loveCause, fox) // Paper
|
||||
+ );
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, loveCause, fox) // Paper - call EntityBreedEvent, add spawn context
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -934,6 +_,7 @@
|
||||
private void pickSweetBerries(BlockState state) {
|
||||
int ageValue = state.getValue(SweetBerryBushBlock.AGE);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) {
|
||||
- this.hurtServer(serverLevel, this.damageSources().onFire(), 1.0F);
|
||||
+ this.hurtServer(serverLevel, this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING
|
||||
+ this.hurtServer(serverLevel, this.damageSources().onFire().knownCause(org.bukkit.event.entity.EntityDamageEvent.DamageCause.MELTING), 1.0F); // CraftBukkit
|
||||
}
|
||||
|
||||
if (!serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
@Override
|
||||
public void thunderHit(ServerLevel level, LightningBolt lightning) {
|
||||
- this.hurtServer(level, this.damageSources().lightningBolt(), Float.MAX_VALUE);
|
||||
+ this.hurtServer(level, this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
|
||||
+ this.hurtServer(level, this.damageSources().lightningBolt().eventEntityDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
+ public boolean actuallyHurt(ServerLevel level, DamageSource damageSource, float amount, org.bukkit.event.entity.EntityDamageEvent event) { // CraftBukkit - void -> boolean
|
||||
if (!this.canArmorAbsorb(damageSource)) {
|
||||
- super.actuallyHurt(level, damageSource, amount);
|
||||
+ super.actuallyHurt(level, damageSource, amount, event); // CraftBukkit
|
||||
+ return super.actuallyHurt(level, damageSource, amount, event); // CraftBukkit
|
||||
} else {
|
||||
+ if (event.isCancelled()) return false; // CraftBukkit - SPIGOT-7815: if the damage was cancelled, no need to run the wolf armor behaviour
|
||||
ItemStack bodyArmorItem = this.getBodyArmorItem();
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
this.playEatingSound();
|
||||
}
|
||||
|
||||
@@ -350,7 +_,7 @@
|
||||
@@ -349,8 +_,7 @@
|
||||
double d1 = Mth.randomBetween(this.random, 0.3F, 0.7F);
|
||||
double d2 = Mth.randomBetween(this.random, -0.2F, 0.2F);
|
||||
ItemEntity itemEntity = new ItemEntity(this.level(), vec3.x(), vec3.y(), vec3.z(), itemStack, d, d1, d2);
|
||||
this.level().addFreshEntity(itemEntity);
|
||||
- this.level().addFreshEntity(itemEntity);
|
||||
- return true;
|
||||
+ return this.spawnAtLocation((net.minecraft.server.level.ServerLevel) this.level(), itemEntity) != null; // Paper - Call EntityDropItemEvent
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -423,12 +_,18 @@
|
||||
@@ -423,13 +_,19 @@
|
||||
if (compound.contains("DrownedConversionTime", 99) && compound.getInt("DrownedConversionTime") > -1) {
|
||||
this.startUnderWaterConversion(compound.getInt("DrownedConversionTime"));
|
||||
}
|
||||
@@ -206,11 +206,13 @@
|
||||
public boolean killedEntity(ServerLevel level, LivingEntity entity) {
|
||||
boolean flag = super.killedEntity(level, entity);
|
||||
- if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager villager) {
|
||||
+ final double fallbackChance = level.getDifficulty() == Difficulty.HARD ? 100 : level.getDifficulty() == Difficulty.NORMAL ? 50 : 0; // Paper - Configurable chance of villager zombie infection
|
||||
- if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
|
||||
+ final double fallbackChance = level.getDifficulty() == Difficulty.HARD ? 100 : level.getDifficulty() == Difficulty.NORMAL ? 50 : 0; // Paper - Configurable chance of villager zombie infection - moved up from belows if
|
||||
+ if (this.random.nextDouble() * 100 < level.paperConfig().entities.behavior.zombieVillagerInfectionChance.or(fallbackChance) && entity instanceof Villager villager) { // Paper - Configurable chance of villager zombie infection
|
||||
if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
|
||||
+ if (false && level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { // Paper - Configurable chance of villager zombie infection - moved to "fallbackChance"
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -465,7 +_,7 @@
|
||||
spawnGroupData = super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||
float specialMultiplier = difficulty.getSpecialMultiplier();
|
||||
|
||||
@@ -57,14 +57,6 @@
|
||||
EntityType.VILLAGER,
|
||||
ConversionParams.single(this, false, false),
|
||||
villager -> {
|
||||
@@ -223,6 +_,7 @@
|
||||
SlotAccess slot = villager.getSlot(equipmentSlot.getIndex() + 300);
|
||||
slot.set(this.getItemBySlot(equipmentSlot));
|
||||
}
|
||||
+ this.forceDrops = false; // CraftBukkit
|
||||
|
||||
villager.setVillagerData(this.getVillagerData());
|
||||
if (this.gossips != null) {
|
||||
@@ -237,19 +_,24 @@
|
||||
villager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(villager.blockPosition()), EntitySpawnReason.CONVERSION, null);
|
||||
villager.refreshBrain(serverLevel);
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
&& !this.isSprinting();
|
||||
+ flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
|
||||
if (flag2) {
|
||||
+ damageSource = damageSource.critical(true); // Paper start - critical damage API
|
||||
+ damageSource = damageSource.critical(); // Paper - critical damage API
|
||||
f *= 1.5F;
|
||||
}
|
||||
|
||||
@@ -342,12 +342,14 @@
|
||||
}
|
||||
|
||||
if (flag3) {
|
||||
@@ -1212,43 +_,62 @@
|
||||
@@ -1212,43 +_,64 @@
|
||||
&& (!(livingEntity2 instanceof ArmorStand) || !((ArmorStand)livingEntity2).isMarker())
|
||||
&& this.distanceToSqr(livingEntity2) < 9.0) {
|
||||
float f6 = this.getEnchantedDamage(livingEntity2, f5, damageSource) * attackStrengthScale;
|
||||
+ // CraftBukkit start - Only apply knockback if the damage hits
|
||||
+ if (!livingEntity2.hurtServer((ServerLevel) this.level(), this.damageSources().playerAttack(this).sweep().critical(flag2), f6)) { // Paper - add critical damage API
|
||||
+ // CraftBukkit start - Only apply knockback if the event is not cancelled
|
||||
+ livingEntity2.lastDamageCancelled = false;
|
||||
+ livingEntity2.hurtServer((ServerLevel) this.level(), damageSource.knownCause(org.bukkit.event.entity.EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK), f6);
|
||||
+ if (livingEntity2.lastDamageCancelled) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -643,18 +645,21 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1988,17 +_,28 @@
|
||||
@@ -1988,17 +_,32 @@
|
||||
return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING);
|
||||
}
|
||||
|
||||
+ // Paper start - PlayerReadyArrowEvent
|
||||
+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) {
|
||||
+ return !(this instanceof ServerPlayer) ||
|
||||
+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent(
|
||||
+ ((ServerPlayer) this).getBukkitEntity(),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)
|
||||
+ ).callEvent();
|
||||
+ // We pass a result mutable boolean in to allow the caller of this method to know if the event was cancelled.
|
||||
+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack, final org.apache.commons.lang3.mutable.MutableBoolean cancelled) {
|
||||
+ if (!(this instanceof final ServerPlayer serverPlayer)) return true;
|
||||
+ final boolean notCancelled = new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent(
|
||||
+ serverPlayer.getBukkitEntity(),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)
|
||||
+ ).callEvent();
|
||||
+ if (!notCancelled) cancelled.setValue(true);
|
||||
+ return notCancelled;
|
||||
+ }
|
||||
+ // Paper end - PlayerReadyArrowEvent
|
||||
+
|
||||
@@ -664,13 +669,44 @@
|
||||
return ItemStack.EMPTY;
|
||||
} else {
|
||||
- Predicate<ItemStack> supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles();
|
||||
+ Predicate<ItemStack> supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles().and(item -> this.tryReadyArrow(shootable, item)); // Paper - PlayerReadyArrowEvent
|
||||
+ final org.apache.commons.lang3.mutable.MutableBoolean anyEventCancelled = new org.apache.commons.lang3.mutable.MutableBoolean(); // Paper - PlayerReadyArrowEvent
|
||||
+ Predicate<ItemStack> supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles().and(item -> this.tryReadyArrow(shootable, item, anyEventCancelled)); // Paper - PlayerReadyArrowEvent
|
||||
ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles);
|
||||
if (!heldProjectile.isEmpty()) {
|
||||
return heldProjectile;
|
||||
} else {
|
||||
- supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getAllSupportedProjectiles();
|
||||
+ supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getAllSupportedProjectiles().and(item -> this.tryReadyArrow(shootable, item)); // Paper - PlayerReadyArrowEvent
|
||||
+ supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getAllSupportedProjectiles().and(item -> this.tryReadyArrow(shootable, item, anyEventCancelled)); // Paper - PlayerReadyArrowEvent
|
||||
|
||||
for (int i = 0; i < this.inventory.getContainerSize(); i++) {
|
||||
ItemStack item = this.inventory.getItem(i);
|
||||
@@ -2007,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (anyEventCancelled.booleanValue() && !this.abilities.instabuild && this instanceof final ServerPlayer player) this.resyncUsingItem(player); // Paper - resync if no item matched the Predicate
|
||||
return this.abilities.instabuild ? new ItemStack(Items.ARROW) : ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -2089,12 +_,20 @@
|
||||
}
|
||||
|
||||
public boolean hasClientLoaded() {
|
||||
- return this.clientLoaded || this.clientLoadedTimeoutTimer <= 0;
|
||||
+ return this.clientLoaded; // Paper - Add PlayerLoadedWorldEvent
|
||||
}
|
||||
|
||||
public void tickClientLoadTimeout() {
|
||||
if (!this.clientLoaded) {
|
||||
this.clientLoadedTimeoutTimer--;
|
||||
+ // Paper start - Add PlayerLoadedWorldEvent
|
||||
+ if (this.clientLoadedTimeoutTimer <= 0) {
|
||||
+ this.clientLoaded = true;
|
||||
+
|
||||
+ final io.papermc.paper.event.player.PlayerClientLoadedWorldEvent event = new io.papermc.paper.event.player.PlayerClientLoadedWorldEvent((org.bukkit.craftbukkit.entity.CraftPlayer) getBukkitEntity(), true);
|
||||
+ event.callEvent();
|
||||
+ }
|
||||
+ // Paper end - Add PlayerLoadedWorldEvent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
this.hasImpulse = true;
|
||||
if (this.getPierceLevel() > 0 && projectileDeflection == ProjectileDeflection.NONE) {
|
||||
continue;
|
||||
@@ -313,6 +_,19 @@
|
||||
@@ -313,13 +_,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,14 @@
|
||||
@Override
|
||||
protected double getDefaultGravity() {
|
||||
return 0.05;
|
||||
}
|
||||
|
||||
private boolean shouldFall() {
|
||||
- return this.isInGround() && this.level().noCollision(new AABB(this.position(), this.position()).inflate(0.06));
|
||||
+ return this.isInGround() && this.level().noCollision(new AABB(this.position(), this.position()).inflate(0.06)); // Paper - getAttachedBlocks api; diff on change
|
||||
}
|
||||
|
||||
private void startFalling() {
|
||||
@@ -329,7 +_,7 @@
|
||||
this.life = 0;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
if (target.isAlive() && !target.isInvulnerable() && target != owner) {
|
||||
if (owner == null) {
|
||||
- target.hurt(this.damageSources().magic(), 6.0F);
|
||||
+ target.hurt(this.damageSources().magic().customEventDamager(this), 6.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
+ target.hurt(this.damageSources().magic().eventEntityDamager(this), 6.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
} else {
|
||||
if (owner.isAlliedTo(target)) {
|
||||
return;
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
|
||||
if (this.life > this.lifetime && this.level() instanceof ServerLevel serverLevel) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@
|
||||
super.onHitEntity(result);
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
this.level().getBlockState(blockPos).entityInside(this.level(), blockPos, this);
|
||||
if (this.level() instanceof ServerLevel serverLevel && this.hasExplosion()) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
|
||||
super.onHitBlock(result);
|
||||
|
||||
@@ -54,11 +54,14 @@
|
||||
}
|
||||
|
||||
this.leftOwner = compound.getBoolean("LeftOwner");
|
||||
@@ -175,13 +_,22 @@
|
||||
@@ -175,13 +_,25 @@
|
||||
float f2 = Mth.cos(y * (float) (Math.PI / 180.0)) * Mth.cos(x * (float) (Math.PI / 180.0));
|
||||
this.shoot(f, f1, f2, velocity, inaccuracy);
|
||||
Vec3 knownMovement = shooter.getKnownMovement();
|
||||
+ // Paper start - allow disabling relative velocity
|
||||
+ if (Double.isNaN(knownMovement.x) || Double.isNaN(knownMovement.y) || Double.isNaN(knownMovement.z)) {
|
||||
+ knownMovement = new Vec3(0, 0, 0);
|
||||
+ }
|
||||
+ if (!shooter.level().paperConfig().misc.disableRelativeProjectileVelocity) {
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(knownMovement.x, shooter.onGround() ? 0.0 : knownMovement.y, knownMovement.z));
|
||||
+ }
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
serverPlayer1.resetFallDistance();
|
||||
serverPlayer1.resetCurrentImpulseContext();
|
||||
- serverPlayer1.hurtServer(serverPlayer.serverLevel(), this.damageSources().enderPearl(), 5.0F);
|
||||
+ serverPlayer1.hurtServer(serverPlayer.serverLevel(), this.damageSources().enderPearl().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
+ serverPlayer1.hurtServer(serverPlayer.serverLevel(), this.damageSources().enderPearl().eventEntityDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
this.playSound(serverLevel, vec3);
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
+++ b/net/minecraft/world/entity/projectile/ThrownPotion.java
|
||||
@@ -9,6 +_,7 @@
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
@@ -82,51 +_,87 @@
|
||||
@@ -82,51 +_,86 @@
|
||||
@Override
|
||||
protected void onHit(HitResult result) {
|
||||
super.onHit(result);
|
||||
@@ -28,12 +20,12 @@
|
||||
+ } else if (true || potionContents.hasEffects()) { // CraftBukkit - Call event even if no effects to apply
|
||||
if (this.isLingering()) {
|
||||
- this.makeAreaOfEffectCloud(potionContents);
|
||||
+ showParticles = this.makeAreaOfEffectCloud(potionContents, result); // CraftBukkit - Pass MovingObjectPosition // Paper
|
||||
+ showParticles = this.makeAreaOfEffectCloud(potionContents, result); // CraftBukkit - Pass HitResult // Paper
|
||||
} else {
|
||||
- this.applySplash(
|
||||
- serverLevel, potionContents.getAllEffects(), result.getType() == HitResult.Type.ENTITY ? ((EntityHitResult)result).getEntity() : null
|
||||
+ showParticles = this.applySplash(
|
||||
+ serverLevel, potionContents.getAllEffects(), result != null && result.getType() == HitResult.Type.ENTITY ? ((EntityHitResult)result).getEntity() : null, result // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||
+ showParticles = this.applySplash( // Paper - Fix potions splash events
|
||||
+ serverLevel, potionContents.getAllEffects(), result != null && result.getType() == HitResult.Type.ENTITY ? ((EntityHitResult)result).getEntity() : null, result // CraftBukkit - Pass HitResult // Paper - More projectile API
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +40,7 @@
|
||||
}
|
||||
|
||||
- private void applyWater(ServerLevel level) {
|
||||
+ private static final Predicate<net.minecraft.world.entity.LivingEntity> APPLY_WATER_GET_ENTITIES_PREDICATE = ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE.or(Axolotl.class::isInstance); // Paper - Fix potions splash events
|
||||
+ private static final Predicate<LivingEntity> APPLY_WATER_GET_ENTITIES_PREDICATE = ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE.or(Axolotl.class::isInstance); // Paper - Fix potions splash events
|
||||
+
|
||||
+ private boolean applyWater(ServerLevel level, @Nullable HitResult result) { // Paper - Fix potions splash events
|
||||
AABB aabb = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
|
||||
@@ -67,20 +59,19 @@
|
||||
if (d < 16.0) {
|
||||
if (livingEntity.isSensitiveToWater()) {
|
||||
- livingEntity.hurtServer(level, this.damageSources().indirectMagic(this, this.getOwner()), 1.0F);
|
||||
+ affected.put(livingEntity.getBukkitLivingEntity(), 1.0);
|
||||
+ // livingEntity.hurtServer(level, this.damageSources().indirectMagic(this, this.getOwner()), 1.0F);
|
||||
+ affected.put(livingEntity.getBukkitLivingEntity(), 1.0); // Paper - Fix potions splash events
|
||||
}
|
||||
|
||||
if (livingEntity.isOnFire() && livingEntity.isAlive()) {
|
||||
- livingEntity.extinguishFire();
|
||||
+ extinguish.add(livingEntity.getBukkitLivingEntity());
|
||||
+ // livingEntity.extinguishFire();
|
||||
+ extinguish.add(livingEntity.getBukkitLivingEntity()); // Paper - Fix potions splash events
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- for (Axolotl axolotl : this.level().getEntitiesOfClass(Axolotl.class, aabb)) {
|
||||
- axolotl.rehydrate();
|
||||
+ // Paper start - Fix potions splash events
|
||||
+ io.papermc.paper.event.entity.WaterBottleSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callWaterBottleSplashEvent(
|
||||
+ this, result, affected, rehydrate, extinguish
|
||||
+ );
|
||||
@@ -102,14 +93,14 @@
|
||||
}
|
||||
|
||||
- private void applySplash(ServerLevel level, Iterable<MobEffectInstance> effects, @Nullable Entity entity) {
|
||||
+ private boolean applySplash(ServerLevel level, Iterable<MobEffectInstance> effects, @Nullable Entity entity, @Nullable HitResult result) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events & More projectile API
|
||||
+ private boolean applySplash(ServerLevel level, Iterable<MobEffectInstance> effects, @Nullable Entity entity, @Nullable HitResult result) { // CraftBukkit - Pass HitResult // Paper - Fix potions splash events & More projectile API
|
||||
AABB aabb = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
|
||||
List<LivingEntity> entitiesOfClass = level.getEntitiesOfClass(LivingEntity.class, aabb);
|
||||
+ java.util.Map<org.bukkit.entity.LivingEntity, Double> affected = new java.util.HashMap<>(); // CraftBukkit
|
||||
if (!entitiesOfClass.isEmpty()) {
|
||||
Entity effectSource = this.getEffectSource();
|
||||
|
||||
@@ -135,33 +_,57 @@
|
||||
@@ -135,12 +_,31 @@
|
||||
double d = this.distanceToSqr(livingEntity);
|
||||
if (d < 16.0) {
|
||||
double d1;
|
||||
@@ -120,69 +111,45 @@
|
||||
d1 = 1.0 - Math.sqrt(d) / 4.0;
|
||||
}
|
||||
|
||||
- for (MobEffectInstance mobEffectInstance : effects) {
|
||||
- Holder<MobEffect> effect = mobEffectInstance.getEffect();
|
||||
- if (effect.value().isInstantenous()) {
|
||||
- effect.value().applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), d1);
|
||||
- } else {
|
||||
- int i = mobEffectInstance.mapDuration(i1 -> (int)(d1 * i1 + 0.5));
|
||||
- MobEffectInstance mobEffectInstance1 = new MobEffectInstance(
|
||||
- effect, i, mobEffectInstance.getAmplifier(), mobEffectInstance.isAmbient(), mobEffectInstance.isVisible()
|
||||
- );
|
||||
- if (!mobEffectInstance1.endsWithin(20)) {
|
||||
- livingEntity.addEffect(mobEffectInstance1, effectSource);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ affected.put(livingEntity.getBukkitLivingEntity(), d1);
|
||||
+ // CraftBukkit start
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, result, affected);
|
||||
+ if (!event.isCancelled() && entitiesOfClass != null && !entitiesOfClass.isEmpty()) { // do not process effects if there are no effects to process
|
||||
+ if (!event.isCancelled() && !entitiesOfClass.isEmpty()) { // do not process effects if there are no effects to process
|
||||
+ Entity effectSource = this.getEffectSource();
|
||||
+ for (org.bukkit.entity.LivingEntity victim : event.getAffectedEntities()) {
|
||||
+ if (!(victim instanceof org.bukkit.craftbukkit.entity.CraftLivingEntity craftLivingEntity)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle();
|
||||
+ LivingEntity livingEntity = craftLivingEntity.getHandle();
|
||||
+ double d1 = event.getIntensity(victim);
|
||||
+ // CraftBukkit end
|
||||
+ for (MobEffectInstance mobEffectInstance : effects) {
|
||||
+ Holder<MobEffect> effect = mobEffectInstance.getEffect();
|
||||
+ // CraftBukkit start - Abide by PVP settings - for players only!
|
||||
+ if (!this.level().pvpMode && this.getOwner() instanceof ServerPlayer && livingEntity instanceof ServerPlayer && livingEntity != this.getOwner()) {
|
||||
+ MobEffect mobEffect = effect.value();
|
||||
+ if (mobEffect == net.minecraft.world.effect.MobEffects.MOVEMENT_SLOWDOWN || mobEffect == net.minecraft.world.effect.MobEffects.DIG_SLOWDOWN || mobEffect == net.minecraft.world.effect.MobEffects.HARM || mobEffect == net.minecraft.world.effect.MobEffects.BLINDNESS
|
||||
+ || mobEffect == net.minecraft.world.effect.MobEffects.HUNGER || mobEffect == net.minecraft.world.effect.MobEffects.WEAKNESS || mobEffect == net.minecraft.world.effect.MobEffects.POISON) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ {
|
||||
+ {
|
||||
+ // CraftBukkit end
|
||||
+ if (effect.value().isInstantenous()) {
|
||||
+ effect.value().applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), d1);
|
||||
+ } else {
|
||||
+ int i = mobEffectInstance.mapDuration(i1 -> (int)(d1 * i1 + 0.5));
|
||||
+ MobEffectInstance mobEffectInstance1 = new MobEffectInstance(
|
||||
+ effect, i, mobEffectInstance.getAmplifier(), mobEffectInstance.isAmbient(), mobEffectInstance.isVisible()
|
||||
+ );
|
||||
+ if (!mobEffectInstance1.endsWithin(20)) {
|
||||
+ livingEntity.addEffect(mobEffectInstance1, effectSource, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
for (MobEffectInstance mobEffectInstance : effects) {
|
||||
Holder<MobEffect> effect = mobEffectInstance.getEffect();
|
||||
if (effect.value().isInstantenous()) {
|
||||
@@ -151,7 +_,7 @@
|
||||
effect, i, mobEffectInstance.getAmplifier(), mobEffectInstance.isAmbient(), mobEffectInstance.isVisible()
|
||||
);
|
||||
if (!mobEffectInstance1.endsWithin(20)) {
|
||||
- livingEntity.addEffect(mobEffectInstance1, effectSource);
|
||||
+ livingEntity.addEffect(mobEffectInstance1, effectSource, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,9 +_,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+ return !event.isCancelled(); // Paper - Fix potions splash events
|
||||
}
|
||||
|
||||
- private void makeAreaOfEffectCloud(PotionContents potionContents) {
|
||||
+ private boolean makeAreaOfEffectCloud(PotionContents potionContents, @Nullable HitResult result) { // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||
+ private boolean makeAreaOfEffectCloud(PotionContents potionContents, @Nullable HitResult result) { // CraftBukkit - Pass HitResult // Paper - More projectile API
|
||||
AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
||||
if (this.getOwner() instanceof LivingEntity livingEntity) {
|
||||
areaEffectCloud.setOwner(livingEntity);
|
||||
@@ -197,41 +164,30 @@
|
||||
+ if (!(event.isCancelled() || areaEffectCloud.isRemoved() || (!event.allowsEmptyCreation() && (noEffects && !areaEffectCloud.potionContents.hasEffects())))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
|
||||
+ this.level().addFreshEntity(areaEffectCloud);
|
||||
+ } else {
|
||||
+ areaEffectCloud.discard(null); // CraftBukkit - add Bukkit remove cause
|
||||
+ areaEffectCloud.discard(null); // add Bukkit remove cause
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ return !event.isCancelled(); // Paper - Fix potions splash events
|
||||
}
|
||||
|
||||
public boolean isLingering() {
|
||||
@@ -182,13 +_,25 @@
|
||||
@@ -182,13 +_,19 @@
|
||||
private void dowseFire(BlockPos pos) {
|
||||
BlockState blockState = this.level().getBlockState(pos);
|
||||
if (blockState.is(BlockTags.FIRE)) {
|
||||
- this.level().destroyBlock(pos, false, this);
|
||||
+ // CraftBukkit start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
|
||||
+ this.level().destroyBlock(pos, false, this);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.level().destroyBlock(pos, false, this);
|
||||
+ } // CraftBukkit
|
||||
} else if (AbstractCandleBlock.isLit(blockState)) {
|
||||
- AbstractCandleBlock.extinguish(null, blockState, this.level(), pos);
|
||||
+ // CraftBukkit start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(AbstractCandleBlock.LIT, false))) {
|
||||
+ AbstractCandleBlock.extinguish(null, blockState, this.level(), pos);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(AbstractCandleBlock.LIT, Boolean.valueOf(false)))) { // CraftBukkit
|
||||
AbstractCandleBlock.extinguish(null, blockState, this.level(), pos);
|
||||
+ } // CraftBukkit
|
||||
} else if (CampfireBlock.isLitCampfire(blockState)) {
|
||||
- this.level().levelEvent(null, 1009, pos, 0);
|
||||
- CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState);
|
||||
- this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false)));
|
||||
+ // CraftBukkit start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(CampfireBlock.LIT, false))) {
|
||||
+ this.level().levelEvent(null, 1009, pos, 0);
|
||||
+ CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState);
|
||||
+ this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, false));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false)))) { // CraftBukkit
|
||||
this.level().levelEvent(null, 1009, pos, 0);
|
||||
CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState);
|
||||
this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false)));
|
||||
+ } // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
}
|
||||
} else {
|
||||
- flag = var8.hurtServer(serverLevel, this.damageSources().magic(), 5.0F);
|
||||
+ flag = var8.hurtServer(serverLevel, this.damageSources().magic().customEventDamager(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls // Paper - fix DamageSource API
|
||||
+ flag = var8.hurtServer(serverLevel, this.damageSources().magic().eventEntityDamager(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls // Paper - fix DamageSource API
|
||||
}
|
||||
|
||||
if (flag && var8 instanceof LivingEntity livingEntityx) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
--- a/net/minecraft/world/entity/projectile/windcharge/BreezeWindCharge.java
|
||||
+++ b/net/minecraft/world/entity/projectile/windcharge/BreezeWindCharge.java
|
||||
@@ -20,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public void explode(Vec3 pos) {
|
||||
+ // Paper start - Fire event for WindCharge explosions
|
||||
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, RADIUS, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Fire event for WindCharge explosions
|
||||
this.level()
|
||||
.explode(
|
||||
this,
|
||||
@@ -28,8 +_,8 @@
|
||||
pos.x(),
|
||||
pos.y(),
|
||||
pos.z(),
|
||||
- 3.0F,
|
||||
- false,
|
||||
+ event.getRadius(), // Paper - Fire event for WindCharge explosions
|
||||
+ event.getFire(), // Paper - Fire event for WindCharge explosions
|
||||
Level.ExplosionInteraction.TRIGGER,
|
||||
ParticleTypes.GUST_EMITTER_SMALL,
|
||||
ParticleTypes.GUST_EMITTER_LARGE,
|
||||
@@ -0,0 +1,26 @@
|
||||
--- a/net/minecraft/world/entity/projectile/windcharge/WindCharge.java
|
||||
+++ b/net/minecraft/world/entity/projectile/windcharge/WindCharge.java
|
||||
@@ -52,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public void explode(Vec3 pos) {
|
||||
+ // Paper start - Fire event for WindCharge explosions
|
||||
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, RADIUS, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Fire event for WindCharge explosions
|
||||
this.level()
|
||||
.explode(
|
||||
this,
|
||||
@@ -60,8 +_,8 @@
|
||||
pos.x(),
|
||||
pos.y(),
|
||||
pos.z(),
|
||||
- 1.2F,
|
||||
- false,
|
||||
+ event.getRadius(), // Paper - Fire event for WindCharge explosions
|
||||
+ event.getFire(), // Paper - Fire event for WindCharge explosions
|
||||
Level.ExplosionInteraction.TRIGGER,
|
||||
ParticleTypes.GUST_EMITTER_SMALL,
|
||||
ParticleTypes.GUST_EMITTER_LARGE,
|
||||
@@ -99,42 +99,20 @@
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
@@ -491,6 +_,10 @@
|
||||
@@ -486,7 +_,7 @@
|
||||
|
||||
private void spawnGroup(BlockPos pos) {
|
||||
boolean flag = false;
|
||||
- int i = this.groupsSpawned + 1;
|
||||
+ int i = this.groupsSpawned + 1; final int wave = i; // Paper - OBFHELPER
|
||||
this.totalHealth = 0.0F;
|
||||
DifficultyInstance currentDifficultyAt = this.level.getCurrentDifficultyAt(pos);
|
||||
boolean shouldSpawnBonusGroup = this.shouldSpawnBonusGroup();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ Raider leader = null;
|
||||
+ List<Raider> raiders = new java.util.ArrayList<>();
|
||||
+ // CraftBukkit end
|
||||
for (Raid.RaiderType raiderType : Raid.RaiderType.VALUES) {
|
||||
int i1 = this.getDefaultNumSpawns(raiderType, i, shouldSpawnBonusGroup)
|
||||
+ this.getPotentialBonusSpawns(raiderType, this.random, i, currentDifficultyAt, shouldSpawnBonusGroup);
|
||||
@@ -506,9 +_,11 @@
|
||||
raider.setPatrolLeader(true);
|
||||
this.setLeader(i, raider);
|
||||
flag = true;
|
||||
+ leader = raider; // CraftBukkit
|
||||
}
|
||||
|
||||
this.joinRaid(i, raider, pos, false);
|
||||
+ raiders.add(raider); // CraftBukkit
|
||||
if (raiderType.entityType == EntityType.RAVAGER) {
|
||||
Raider raider1 = null;
|
||||
if (i == this.getNumGroups(Difficulty.NORMAL)) {
|
||||
@@ -526,6 +_,7 @@
|
||||
this.joinRaid(i, raider1, pos, false);
|
||||
raider1.moveTo(pos, 0.0F, 0.0F);
|
||||
raider1.startRiding(raider);
|
||||
+ raiders.add(raider); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -535,6 +_,7 @@
|
||||
this.groupsSpawned++;
|
||||
this.updateBossbar();
|
||||
this.setDirty();
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, java.util.Objects.requireNonNull(this.getLeader(wave)), this.groupRaiderMap.get(wave)); // CraftBukkit
|
||||
}
|
||||
|
||||
public void joinRaid(int wave, Raider raider, @Nullable BlockPos pos, boolean isRecruited) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.Container;
|
||||
@@ -63,6 +_,31 @@
|
||||
@@ -63,6 +_,32 @@
|
||||
@Nullable
|
||||
private ContainerSynchronizer synchronizer;
|
||||
private boolean suppressRemoteUpdates;
|
||||
@@ -37,6 +37,7 @@
|
||||
+ com.google.common.base.Preconditions.checkState(this.title == null, "Title already set");
|
||||
+ this.title = title;
|
||||
+ }
|
||||
+ public void startOpen() {}
|
||||
+ // CraftBukkit end
|
||||
|
||||
protected AbstractContainerMenu(@Nullable MenuType<?> menuType, int containerId) {
|
||||
@@ -71,6 +72,41 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +_,7 @@
|
||||
private void synchronizeSlotToRemote(int slotIndex, ItemStack stack, Supplier<ItemStack> supplier) {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
ItemStack itemStack = this.remoteSlots.get(slotIndex);
|
||||
- if (!ItemStack.matches(itemStack, stack)) {
|
||||
+ if (!this.matchesRemote(itemStack, stack)) { // Paper - add flag to simplify remote matching logic
|
||||
ItemStack itemStack1 = supplier.get();
|
||||
this.remoteSlots.set(slotIndex, itemStack1);
|
||||
if (this.synchronizer != null) {
|
||||
@@ -267,7 +_,7 @@
|
||||
|
||||
private void synchronizeCarriedToRemote() {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
- if (!ItemStack.matches(this.getCarried(), this.remoteCarried)) {
|
||||
+ if (!this.matchesRemote(this.getCarried(), this.remoteCarried)) { // Paper - add flag to simplify remote matching logic
|
||||
this.remoteCarried = this.getCarried().copy();
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendCarriedChange(this, this.remoteCarried);
|
||||
@@ -276,6 +_,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - add flag to simplify remote matching logic
|
||||
+ private boolean matchesRemote(final ItemStack stack, final ItemStack other) {
|
||||
+ if (this.synchronizer != null && this.synchronizer.player() != null && this.synchronizer.player().getBukkitEntity().simplifyContainerDesyncCheck()) {
|
||||
+ // Only check the item type and count
|
||||
+ return stack == other || (stack.getCount() == other.getCount() && ItemStack.isSameItem(stack, other));
|
||||
+ }
|
||||
+ return ItemStack.matches(stack, other);
|
||||
+ }
|
||||
+ // Paper end - add flag to simplify remote matching logic
|
||||
+
|
||||
public void setRemoteSlot(int slot, ItemStack stack) {
|
||||
this.remoteSlots.set(slot, stack.copy());
|
||||
}
|
||||
@@ -343,6 +_,7 @@
|
||||
this.resetQuickCraft();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/inventory/ChestMenu.java
|
||||
+++ b/net/minecraft/world/inventory/ChestMenu.java
|
||||
@@ -9,6 +_,29 @@
|
||||
@@ -9,6 +_,34 @@
|
||||
public class ChestMenu extends AbstractContainerMenu {
|
||||
private final Container container;
|
||||
private final int containerRows;
|
||||
@@ -26,14 +26,21 @@
|
||||
+ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this);
|
||||
+ return this.bukkitEntity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void startOpen() {
|
||||
+ this.container.startOpen(this.player.player);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
private ChestMenu(MenuType<?> type, int containerId, Inventory playerInventory, int rows) {
|
||||
this(type, containerId, playerInventory, new SimpleContainer(9 * rows), rows);
|
||||
@@ -52,6 +_,9 @@
|
||||
@@ -51,7 +_,10 @@
|
||||
checkContainerSize(container, rows * 9);
|
||||
this.container = container;
|
||||
this.containerRows = rows;
|
||||
container.startOpen(playerInventory.player);
|
||||
- container.startOpen(playerInventory.player);
|
||||
+ // container.startOpen(playerInventory.player); // Paper - don't startOpen until menu actually opens
|
||||
+ // CraftBukkit start - Save player
|
||||
+ this.player = playerInventory;
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
--- a/net/minecraft/world/inventory/ContainerSynchronizer.java
|
||||
+++ b/net/minecraft/world/inventory/ContainerSynchronizer.java
|
||||
@@ -11,4 +_,6 @@
|
||||
@@ -11,4 +_,12 @@
|
||||
void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack);
|
||||
|
||||
void sendDataChange(AbstractContainerMenu container, int id, int value);
|
||||
+
|
||||
+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus
|
||||
+
|
||||
+ // Paper start - add flag to simplify remote matching logic
|
||||
+ default net.minecraft.server.level.@org.jspecify.annotations.Nullable ServerPlayer player() {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - add flag to simplify remote matching logic
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
+ .bukkitToMinecraftHolder(offer.getEnchantment()));
|
||||
+ this.levelClue[j] = offer.getEnchantmentLevel();
|
||||
+ } else {
|
||||
+ this.costs[j] = 0;
|
||||
+ if (enchantClue[j] != -1) this.costs[j] = 0;
|
||||
+ this.enchantClue[j] = -1;
|
||||
+ this.levelClue[j] = -1;
|
||||
+ }
|
||||
@@ -107,7 +107,7 @@
|
||||
this.broadcastChanges();
|
||||
});
|
||||
} else {
|
||||
@@ -145,19 +_,51 @@
|
||||
@@ -145,19 +_,53 @@
|
||||
return false;
|
||||
} else {
|
||||
this.access.execute((level, blockPos) -> {
|
||||
@@ -124,7 +124,9 @@
|
||||
+ enchants.put(org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(instance.enchantment), instance.level);
|
||||
+ }
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
+ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(registry.byId(this.enchantClue[id]));
|
||||
+ Holder<Enchantment> holder = registry.byId(this.enchantClue[id]);
|
||||
+ if (holder == null) return;
|
||||
+ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(holder);
|
||||
+ int hintedEnchantmentLevel = this.levelClue[id];
|
||||
+ org.bukkit.event.enchantment.EnchantItemEvent event = new org.bukkit.event.enchantment.EnchantItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), this.getBukkitView(), this.access.getLocation().getBlock(), craftItemStack, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/world/inventory/HorseInventoryMenu.java
|
||||
+++ b/net/minecraft/world/inventory/HorseInventoryMenu.java
|
||||
@@ -19,9 +_,23 @@
|
||||
private final AbstractHorse horse;
|
||||
public final AbstractHorse horse;
|
||||
public static final int SLOT_BODY_ARMOR = 1;
|
||||
private static final int SLOT_HORSE_INVENTORY_START = 2;
|
||||
+ // CraftBukkit start
|
||||
|
||||
@@ -27,6 +27,14 @@
|
||||
this.addStandardInventorySlots(playerInventory, 108, 84);
|
||||
}
|
||||
|
||||
@@ -61,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
+ if (!checkReachable) return true; // Paper - checkReachable
|
||||
return this.trader.stillValid(player);
|
||||
}
|
||||
|
||||
@@ -105,12 +_,12 @@
|
||||
ItemStack item = slot.getItem();
|
||||
itemStack = item.copy();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java
|
||||
+++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java
|
||||
@@ -9,6 +_,20 @@
|
||||
@@ -9,6 +_,25 @@
|
||||
public class ShulkerBoxMenu extends AbstractContainerMenu {
|
||||
private static final int CONTAINER_SIZE = 27;
|
||||
private final Container container;
|
||||
@@ -17,18 +17,25 @@
|
||||
+ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventory(this.container), this);
|
||||
+ return this.bukkitEntity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void startOpen() {
|
||||
+ container.startOpen(player.player);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
public ShulkerBoxMenu(int containerId, Inventory playerInventory) {
|
||||
this(containerId, playerInventory, new SimpleContainer(27));
|
||||
@@ -18,6 +_,7 @@
|
||||
@@ -18,7 +_,8 @@
|
||||
super(MenuType.SHULKER_BOX, containerId);
|
||||
checkContainerSize(container, 27);
|
||||
this.container = container;
|
||||
- container.startOpen(playerInventory.player);
|
||||
+ this.player = playerInventory; // CraftBukkit - save player
|
||||
container.startOpen(playerInventory.player);
|
||||
+ // container.startOpen(playerInventory.player); // Paper - don't startOpen until menu actually opens
|
||||
int i = 3;
|
||||
int i1 = 9;
|
||||
|
||||
@@ -33,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/item/EnderpearlItem.java
|
||||
+++ b/net/minecraft/world/item/EnderpearlItem.java
|
||||
@@ -21,22 +_,38 @@
|
||||
@@ -21,22 +_,42 @@
|
||||
@Override
|
||||
public InteractionResult use(Level level, Player player, InteractionHand hand) {
|
||||
ItemStack itemInHand = player.getItemInHand(hand);
|
||||
@@ -39,7 +39,11 @@
|
||||
+ );
|
||||
+ player.awardStat(Stats.ITEM_USED.get(this));
|
||||
+ } else {
|
||||
+ // Paper end - PlayerLaunchProjectileEvent
|
||||
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.deregisterEnderPearl(thrownEnderpearl.projectile());
|
||||
+ serverPlayer.connection.send(new net.minecraft.network.protocol.game.ClientboundCooldownPacket(player.getCooldowns().getCooldownGroup(itemInHand), 0)); // prevent visual desync of cooldown on the slot
|
||||
+ }
|
||||
+ // Paper end - PlayerLaunchProjectileEvent
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/item/HangingEntityItem.java
|
||||
+++ b/net/minecraft/world/item/HangingEntityItem.java
|
||||
@@ -66,6 +_,19 @@
|
||||
@@ -66,6 +_,20 @@
|
||||
|
||||
if (hangingEntity.survives()) {
|
||||
if (!level.isClientSide) {
|
||||
@@ -14,6 +14,7 @@
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ if (player != null) player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Player player = context.getPlayer();
|
||||
ItemStack itemInHand = context.getItemInHand();
|
||||
+ // Paper start - EntityChangeBlockEvent
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, clickedPos, blockState)) {
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, clickedPos, blockState1)) {
|
||||
+ if (!player.isCreative()) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user