Compare commits

...
11 changed files with 422 additions and 13 deletions

No files matched your search

+1
View File
@@ -118,6 +118,7 @@ public net.minecraft.stats.ServerRecipeBook known
public net.minecraft.tags.TagEntry id
public net.minecraft.tags.TagEntry required
public net.minecraft.tags.TagEntry tag
public net.minecraft.util.AbstractListBuilder
public net.minecraft.util.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V
public net.minecraft.util.datafix.fixes.BlockStateData register(ILcom/mojang/serialization/Dynamic;[Lcom/mojang/serialization/Dynamic;)V
public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES
+1 -1
View File
@@ -86,7 +86,7 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.12.2")
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("org.mockito:mockito-core:5.14.1")
testImplementation("org.ow2.asm:asm-tree:9.8")
testImplementation("org.ow2.asm:asm-tree:9.9.1")
mockitoAgent("org.mockito:mockito-core:5.14.1") { isTransitive = false } // configure mockito agent that is needed in newer java versions
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
+2 -2
View File
@@ -150,7 +150,7 @@ dependencies {
}
implementation("io.netty:netty-codec-haproxy:4.2.7.Final") // Add support for proxy protocol
implementation("org.apache.logging.log4j:log4j-iostreams:2.24.1")
implementation("org.ow2.asm:asm-commons:9.8")
implementation("org.ow2.asm:asm-commons:9.9.1")
implementation("org.spongepowered:configurate-yaml:4.2.0")
// Deps that were previously in the API but have now been moved here for backwards compat, eventually to be removed
@@ -169,7 +169,7 @@ dependencies {
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("org.mockito:mockito-core:5.14.1")
mockitoAgent("org.mockito:mockito-core:5.14.1") { isTransitive = false } // Configure mockito agent that is needed in newer java versions
testImplementation("org.ow2.asm:asm-tree:9.8")
testImplementation("org.ow2.asm:asm-tree:9.9.1")
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // CartesianTest
implementation("net.neoforged:srgutils:1.0.9") // Mappings handling
@@ -521,10 +521,10 @@ index 34ef15867759ebc7296256a6d5ec286eb3a5f895..d3d97b0b6ff6312f1deb0bb8b1beef8b
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 5b6020de0848458f5576113e690b5a6435f35d05..6f49b5e5888a6296b929e465a5ef87dc49bd4516 100644
index 56c29f6407256f471156d309fd81bb0256fff756..07b3d08d9c2f9e978379de5a6b846a828029e2fa 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3330,6 +3330,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -3331,6 +3331,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
protected void playAttackSound() {
}
@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 8 Apr 2026 18:25:47 -0400
Subject: [PATCH] Fix Comparator State Issues
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
index 578e7c8dc601f53cf2a068685c6901bfaf47e763..7e87d56cd42f27c115b575b9acf2ce9ac0953af8 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -136,7 +136,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
float f = state.getValue(MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F;
level.playSound(player, pos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, f);
level.setBlock(pos, state, Block.UPDATE_CLIENTS);
- this.refreshOutputState(level, pos, state);
+ if (level.getBlockState(pos).is(this)) { this.refreshOutputState(level, pos, state); } // Paper
return InteractionResult.SUCCESS;
}
}
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
index 02ffb5569e2405d86b3a4a695dd17c9372169ff7..a750e2d7f6c5ac7561c8b06870e022b07875c587 100644
--- a/net/minecraft/world/level/block/DiodeBlock.java
+++ b/net/minecraft/world/level/block/DiodeBlock.java
@@ -92,6 +92,7 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {
+ if (!level.getBlockState(pos).is(this)) return; // Paper
if (state.canSurvive(level, pos)) {
this.checkTickOnNeighbor(level, pos, state);
} else {
@@ -0,0 +1,18 @@
--- a/net/minecraft/nbt/NbtAccounter.java
+++ b/net/minecraft/nbt/NbtAccounter.java
@@ -48,6 +_,15 @@
}
}
+ // Paper start - Track codec depth
+ public void pushDepth(final int depth) {
+ if (this.depth + depth >= this.maxDepth) {
+ throw new NbtAccounterException("Tried to read NBT tag with too high complexity, depth > " + this.maxDepth);
+ } else {
+ this.depth += depth;
+ }
+ }
+ // Paper end - Track codec depth
public void pushDepth() {
if (this.depth >= this.maxDepth) {
throw new NbtAccounterException("Tried to read NBT tag with too high complexity, depth > " + this.maxDepth);
@@ -0,0 +1,17 @@
--- a/net/minecraft/network/RegistryFriendlyByteBuf.java
+++ b/net/minecraft/network/RegistryFriendlyByteBuf.java
@@ -11,6 +_,14 @@
super(source);
this.registryAccess = registryAccess;
}
+ // Paper start - Track codec depth
+ public RegistryFriendlyByteBuf(final ByteBuf source, final RegistryFriendlyByteBuf parent) {
+ super(source);
+ this.registryAccess = parent.registryAccess;
+ this.trackCodecDepth = parent.trackCodecDepth;
+ this.codecDepth = parent.codecDepth;
+ }
+ // Paper end - Track codec depth
public RegistryAccess registryAccess() {
return this.registryAccess;
@@ -1,5 +1,20 @@
--- a/net/minecraft/network/codec/ByteBufCodecs.java
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
@@ -334,7 +_,13 @@
return new StreamCodec<ByteBuf, Tag>() {
@Override
public Tag decode(ByteBuf buffer) {
- Tag nbt = FriendlyByteBuf.readNbt(buffer, accounter.get());
+ // Paper start - Track codec depth
+ final NbtAccounter acc = accounter.get();
+ if (buffer instanceof FriendlyByteBuf friendlyByteBuf && friendlyByteBuf.trackCodecDepth) {
+ acc.pushDepth(friendlyByteBuf.codecDepth * 3);
+ }
+ Tag nbt = FriendlyByteBuf.readNbt(buffer, acc);
+ // Paper end - Track codec depth
if (nbt == null) {
throw new DecoderException("Expected non-null compound tag");
} else {
@@ -418,6 +_,48 @@
};
}
@@ -49,3 +64,12 @@
static <B extends ByteBuf, V> StreamCodec<B, Optional<V>> optional(final StreamCodec<? super B, V> codec) {
return new StreamCodec<B, Optional<V>>() {
@Override
@@ -592,7 +_,7 @@
}
static <V> StreamCodec.CodecOperation<RegistryFriendlyByteBuf, V, V> registryFriendlyLengthPrefixed(int length) {
- return lengthPrefixed(length, (registryFriendlyByteBuf, byteBuf) -> new RegistryFriendlyByteBuf(byteBuf, registryFriendlyByteBuf.registryAccess()));
+ return lengthPrefixed(length, (registryFriendlyByteBuf, byteBuf) -> new RegistryFriendlyByteBuf(byteBuf, registryFriendlyByteBuf)); // Paper - Track codec depth
}
static <T> StreamCodec<ByteBuf, T> idMapper(final IntFunction<T> idLookup, final ToIntFunction<T> idGetter) {
@@ -1051,7 +1051,7 @@
int i = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5;
int i1 = 25 - i;
float f = damageAmount * i1;
@@ -1863,24 +_,201 @@
@@ -1863,24 +_,202 @@
}
}
@@ -1151,16 +1151,17 @@
+ return false;
+ }
+
+ if (damageSource.getEntity() instanceof net.minecraft.world.entity.player.Player) {
+ if (damageSource.getEntity() instanceof net.minecraft.world.entity.player.Player attackingPlayer) {
+ // Paper start - PlayerAttackEntityCooldownResetEvent
+ //((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetOnlyAttackStrengthTicker(); // Moved from Player in order to make the cooldown reset get called after the damage event is fired
+ if (damageSource.getEntity() instanceof ServerPlayer) {
+ ServerPlayer player = (ServerPlayer) damageSource.getEntity();
+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackStrengthScale(0F)).callEvent()) {
+ player.resetOnlyAttackStrengthTicker();
+ if (!attackingPlayer.isUsingItem() || !attackingPlayer.getUseItem().has(DataComponents.KINETIC_WEAPON)) { // Paper - Preserve vanilla spear charge cooldown
+ if (attackingPlayer instanceof ServerPlayer player) {
+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackStrengthScale(0F)).callEvent()) {
+ player.resetOnlyAttackStrengthTicker();
+ }
+ } else {
+ attackingPlayer.resetOnlyAttackStrengthTicker();
+ }
+ } else {
+ ((net.minecraft.world.entity.player.Player) damageSource.getEntity()).resetOnlyAttackStrengthTicker();
+ }
+ // Paper end - PlayerAttackEntityCooldownResetEvent
+ }
@@ -23,6 +23,15 @@
}
}
};
@@ -219,7 +_,7 @@
public ItemStack decode(RegistryFriendlyByteBuf buffer) {
ItemStack itemStack = codec.decode(buffer);
if (!itemStack.isEmpty()) {
- RegistryOps<Unit> registryOps = buffer.registryAccess().createSerializationContext(NullOps.INSTANCE);
+ RegistryOps<io.papermc.paper.util.CountingOps.Value> registryOps = buffer.registryAccess().createSerializationContext(io.papermc.paper.util.CountingOps.INSTANCE); // Paper - Track codec depth
ItemStack.CODEC.encodeStart(registryOps, itemStack).getOrThrow(DecoderException::new);
}
@@ -371,10 +_,166 @@
return InteractionResult.PASS;
} else {
@@ -0,0 +1,308 @@
package io.papermc.paper.util;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.ListBuilder;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.RecordBuilder;
import com.mojang.serialization.RecordBuilder.AbstractUniversalBuilder;
import io.netty.handler.codec.DecoderException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import net.minecraft.nbt.Tag;
import net.minecraft.util.AbstractListBuilder;
public final class CountingOps implements DynamicOps<CountingOps.Value> {
public static final CountingOps INSTANCE = new CountingOps(Tag.MAX_DEPTH);
private final int maxDepth;
public CountingOps(final int maxDepth) {
this.maxDepth = maxDepth;
}
@Override
public <U> U convertTo(final DynamicOps<U> outOps, final Value input) {
throw new UnsupportedOperationException();
}
@Override
public Value empty() {
return Value.EMPTY;
}
@Override
public Value emptyMap() {
return this.container(Value.Kind.MAP, 0);
}
@Override
public Value emptyList() {
return this.container(Value.Kind.LIST, 0);
}
@Override
public Value createNumeric(final Number value) {
return Value.PRIMITIVE;
}
@Override
public Value createString(final String value) {
return Value.PRIMITIVE;
}
@Override
public DataResult<Number> getNumberValue(final Value input) {
throw new UnsupportedOperationException();
}
@Override
public DataResult<String> getStringValue(final Value input) {
throw new UnsupportedOperationException();
}
@Override
public DataResult<Value> mergeToList(final Value input, final Value value) {
final Accumulator accumulator = new Accumulator();
if (input.kind == Value.Kind.LIST) {
accumulator.acceptDepth(input.depth - 1);
} else if (input.kind != Value.Kind.EMPTY) {
accumulator.accept(input);
}
accumulator.accept(value);
return DataResult.success(this.container(Value.Kind.LIST, accumulator));
}
@Override
public DataResult<Value> mergeToList(final Value input, final List<Value> values) {
final Accumulator accumulator = new Accumulator();
if (input.kind == Value.Kind.LIST) {
accumulator.acceptDepth(input.depth - 1);
} else if (input.kind != Value.Kind.EMPTY) {
accumulator.accept(input);
}
values.forEach(accumulator::accept);
return DataResult.success(this.container(Value.Kind.LIST, accumulator));
}
@Override
public DataResult<Value> mergeToMap(final Value input, final Value key, final Value value) {
final Accumulator accumulator = new Accumulator();
if (input.kind == Value.Kind.MAP) {
accumulator.acceptDepth(input.depth - 1);
} else if (input.kind != Value.Kind.EMPTY) {
accumulator.accept(input);
}
accumulator.accept(value);
return DataResult.success(this.container(Value.Kind.MAP, accumulator));
}
@Override
public DataResult<Value> mergeToMap(final Value input, final Map<Value, Value> values) {
final Accumulator accumulator = new Accumulator();
if (input.kind == Value.Kind.MAP) {
accumulator.acceptDepth(input.depth - 1);
} else if (input.kind != Value.Kind.EMPTY) {
accumulator.accept(input);
}
values.forEach((key, value) -> {
accumulator.accept(value);
});
return DataResult.success(this.container(Value.Kind.MAP, accumulator));
}
@Override
public DataResult<Value> mergeToMap(final Value input, final MapLike<Value> values) {
final Accumulator accumulator = new Accumulator();
if (input.kind == Value.Kind.MAP) {
accumulator.acceptDepth(input.depth - 1);
} else if (input.kind != Value.Kind.EMPTY) {
accumulator.accept(input);
}
values.entries().forEach(entry -> {
accumulator.accept(entry.getSecond());
});
return DataResult.success(this.container(Value.Kind.MAP, accumulator));
}
@Override
public DataResult<Stream<Pair<Value, Value>>> getMapValues(final Value input) {
throw new UnsupportedOperationException();
}
@Override
public DataResult<Stream<Value>> getStream(final Value input) {
throw new UnsupportedOperationException();
}
@Override
public Value createMap(final Stream<Pair<Value, Value>> map) {
final Accumulator accumulator = new Accumulator();
map.forEach(entry -> accumulator.accept(entry.getSecond()));
return this.container(Value.Kind.MAP, accumulator);
}
@Override
public Value createMap(final Map<Value, Value> map) {
final Accumulator accumulator = new Accumulator();
map.forEach((key, value) -> {
accumulator.accept(value);
});
return this.container(Value.Kind.MAP, accumulator);
}
@Override
public Value createList(final Stream<Value> input) {
final Accumulator accumulator = new Accumulator();
input.forEach(accumulator::accept);
return this.container(Value.Kind.LIST, accumulator);
}
@Override
public Value createByteList(final ByteBuffer input) {
return Value.PRIMITIVE;
}
@Override
public Value createIntList(final IntStream input) {
return Value.PRIMITIVE;
}
@Override
public Value createLongList(final LongStream input) {
return Value.PRIMITIVE;
}
@Override
public Value remove(final Value input, final String key) {
return input;
}
@Override
public RecordBuilder<Value> mapBuilder() {
return new MapBuilder(this);
}
@Override
public ListBuilder<Value> listBuilder() {
return new CountingListBuilder(this);
}
@Override
public String toString() {
return "Counting";
}
private Value container(final Value.Kind kind, final Accumulator accumulator) {
return this.container(kind, accumulator.maxDepth);
}
private Value container(final Value.Kind kind, final int childDepth) {
final int depth = childDepth + 1;
if (depth > this.maxDepth) {
throw new DecoderException("NBT depth exceeded: " + depth + " > " + this.maxDepth);
}
return new Value(kind, depth);
}
private static final class Accumulator {
private int maxDepth;
private void accept(final Value value) {
this.acceptDepth(value.depth);
}
private void acceptDepth(final int depth) {
this.maxDepth = Math.max(this.maxDepth, depth);
}
}
public static final class Value {
private static final Value EMPTY = new Value(Kind.EMPTY, 0);
private static final Value PRIMITIVE = new Value(Kind.PRIMITIVE, 0);
private final Kind kind;
private final int depth;
private Value(final Kind kind, final int depth) {
this.kind = kind;
this.depth = depth;
}
public int depth() {
return this.depth;
}
private enum Kind {
EMPTY,
PRIMITIVE,
LIST,
MAP
}
}
private static final class CountingListBuilder extends AbstractListBuilder<Value, Accumulator> {
private final CountingOps ops;
private CountingListBuilder(final CountingOps ops) {
super(ops);
this.ops = ops;
}
@Override
protected Accumulator initBuilder() {
return new Accumulator();
}
@Override
protected Accumulator append(final Accumulator builder, final Value value) {
builder.accept(value);
return builder;
}
@Override
protected DataResult<Value> build(final Accumulator builder, final Value prefix) {
if (prefix.kind == Value.Kind.LIST) {
builder.acceptDepth(prefix.depth - 1);
} else if (prefix.kind != Value.Kind.EMPTY) {
builder.accept(prefix);
}
return DataResult.success(this.ops.container(Value.Kind.LIST, builder));
}
}
private static final class MapBuilder extends AbstractUniversalBuilder<Value, Accumulator> {
private final CountingOps ops;
private MapBuilder(final CountingOps ops) {
super(ops);
this.ops = ops;
}
@Override
protected Accumulator initBuilder() {
return new Accumulator();
}
@Override
protected Accumulator append(final Value key, final Value value, final Accumulator builder) {
builder.accept(value);
return builder;
}
@Override
protected DataResult<Value> build(final Accumulator builder, final Value prefix) {
if (prefix.kind == Value.Kind.MAP) {
builder.acceptDepth(prefix.depth - 1);
} else if (prefix.kind != Value.Kind.EMPTY) {
builder.accept(prefix);
}
return DataResult.success(this.ops.container(Value.Kind.MAP, builder));
}
}
}