1.21.5
Co-authored-by: Bjarne Koll <git@lynxplay.dev> Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com> Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Co-authored-by: MiniDigger | Martin <admin@minidigger.dev> Co-authored-by: Nassim Jahnke <nassim@njahnke.dev> Co-authored-by: Noah van der Aa <ndvdaa@gmail.com> Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Co-authored-by: Shane Freeder <theboyetronic@gmail.com> Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com> Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com> Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/ChatFormatting.java
|
||||
+++ b/net/minecraft/ChatFormatting.java
|
||||
@@ -112,6 +_,19 @@
|
||||
@@ -118,6 +_,19 @@
|
||||
return friendlyName == null ? null : FORMATTING_BY_NAME.get(cleanName(friendlyName));
|
||||
}
|
||||
|
||||
+ // Paper start - add method to get by hex value
|
||||
+ @Nullable
|
||||
+ public static ChatFormatting getByHexValue(int i) {
|
||||
+ public static ChatFormatting getByHexValue(int color) {
|
||||
+ for (ChatFormatting value : values()) {
|
||||
+ if (value.getColor() != null && value.getColor() == i) {
|
||||
+ if (value.getColor() != null && value.getColor() == color) {
|
||||
+ return value;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/Util.java
|
||||
+++ b/net/minecraft/Util.java
|
||||
@@ -92,9 +_,26 @@
|
||||
@@ -93,9 +_,26 @@
|
||||
private static final int DEFAULT_MAX_THREADS = 255;
|
||||
private static final int DEFAULT_SAFE_FILE_OPERATION_RETRIES = 10;
|
||||
private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
|
||||
@@ -28,7 +28,7 @@
|
||||
private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
|
||||
public static final int LINEAR_LOOKUP_THRESHOLD = 8;
|
||||
private static final Set<String> ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https");
|
||||
@@ -113,6 +_,7 @@
|
||||
@@ -114,6 +_,7 @@
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
|
||||
private static Consumer<String> thePauser = string -> {};
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
|
||||
return Collectors.toMap(Entry::getKey, Entry::getValue);
|
||||
@@ -135,7 +_,7 @@
|
||||
@@ -136,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static long getNanos() {
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
public static long getEpochMillis() {
|
||||
@@ -146,9 +_,10 @@
|
||||
@@ -147,9 +_,10 @@
|
||||
return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
if (i <= 0) {
|
||||
directExecutorService = MoreExecutors.newDirectExecutorService();
|
||||
} else {
|
||||
@@ -173,16 +_,30 @@
|
||||
@@ -174,16 +_,30 @@
|
||||
super.onTermination(throwOnTermination);
|
||||
}
|
||||
};
|
||||
@@ -91,7 +91,7 @@
|
||||
}
|
||||
|
||||
private static int getMaxThreads() {
|
||||
@@ -233,6 +_,21 @@
|
||||
@@ -234,6 +_,21 @@
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
public static void throwAsRuntime(Throwable throwable) {
|
||||
throw throwable instanceof RuntimeException ? (RuntimeException)throwable : new RuntimeException(throwable);
|
||||
}
|
||||
@@ -1075,16 +_,7 @@
|
||||
@@ -1088,16 +_,7 @@
|
||||
}
|
||||
|
||||
public void openUri(URI uri) {
|
||||
|
||||
@@ -18,11 +18,10 @@
|
||||
|
||||
public CommandSourceStack(
|
||||
CommandSource source,
|
||||
@@ -187,6 +_,30 @@
|
||||
this.chatMessageChainer
|
||||
@@ -188,6 +_,30 @@
|
||||
);
|
||||
}
|
||||
+
|
||||
|
||||
+ // Paper start - Expose 'with' functions from the CommandSourceStack
|
||||
+ @Override
|
||||
+ public CommandSourceStack withLocation(org.bukkit.Location location) {
|
||||
@@ -46,9 +45,10 @@
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Expose 'with' functions from the CommandSourceStack
|
||||
|
||||
+
|
||||
public CommandSourceStack withRotation(Vec2 rotation) {
|
||||
return this.rotation.equals(rotation)
|
||||
? this
|
||||
@@ -391,9 +_,44 @@
|
||||
|
||||
@Override
|
||||
@@ -94,7 +94,7 @@
|
||||
public Vec3 getPosition() {
|
||||
return this.worldPosition;
|
||||
}
|
||||
@@ -499,20 +_,25 @@
|
||||
@@ -498,20 +_,25 @@
|
||||
Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC);
|
||||
if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) {
|
||||
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
|
||||
@@ -123,7 +123,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,7 +_,7 @@
|
||||
@@ -522,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public Collection<String> getOnlinePlayerNames() {
|
||||
@@ -132,7 +132,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -598,4 +_,16 @@
|
||||
@@ -597,4 +_,16 @@
|
||||
public boolean isSilent() {
|
||||
return this.silent;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
StackTraceElement[] stackTrace = var12.getStackTrace();
|
||||
|
||||
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
|
||||
@@ -309,18 +_,22 @@
|
||||
@@ -308,18 +_,22 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -148,12 +148,12 @@
|
||||
int min = Math.min(var7.getInput().length(), var7.getCursor());
|
||||
MutableComponent mutableComponent = Component.empty()
|
||||
.withStyle(ChatFormatting.GRAY)
|
||||
- .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + command)));
|
||||
+ .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + label))); // CraftBukkit // Paper
|
||||
- .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + command)));
|
||||
+ .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + label))); // CraftBukkit // Paper
|
||||
if (min > 10) {
|
||||
mutableComponent.append(CommonComponents.ELLIPSIS);
|
||||
}
|
||||
@@ -332,7 +_,17 @@
|
||||
@@ -331,7 +_,17 @@
|
||||
}
|
||||
|
||||
mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
|
||||
@@ -172,7 +172,7 @@
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -360,26 +_,120 @@
|
||||
@@ -359,26 +_,120 @@
|
||||
}
|
||||
|
||||
public void sendCommands(ServerPlayer player) {
|
||||
@@ -297,9 +297,9 @@
|
||||
+ // we want the exact command instance to be used for equality checks
|
||||
+ // when assigning serialization ids to each command node
|
||||
|
||||
if (argumentBuilder instanceof RequiredArgumentBuilder) {
|
||||
RequiredArgumentBuilder<SharedSuggestionProvider, ?> requiredArgumentBuilder = (RequiredArgumentBuilder<SharedSuggestionProvider, ?>)argumentBuilder;
|
||||
@@ -396,7 +_,7 @@
|
||||
if (argumentBuilder instanceof RequiredArgumentBuilder requiredArgumentBuilder
|
||||
&& requiredArgumentBuilder.getSuggestionsProvider() != null) {
|
||||
@@ -393,7 +_,7 @@
|
||||
commandNodeToSuggestionNode.put(commandNode, commandNode1);
|
||||
rootSuggestion.addChild(commandNode1);
|
||||
if (!commandNode.getChildren().isEmpty()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/Direction.java
|
||||
+++ b/net/minecraft/core/Direction.java
|
||||
@@ -57,6 +_,12 @@
|
||||
@@ -62,6 +_,12 @@
|
||||
.sorted(Comparator.comparingInt(direction -> direction.data2d))
|
||||
.toArray(Direction[]::new);
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
private Direction(
|
||||
final int data3d,
|
||||
final int oppositeIndex,
|
||||
@@ -74,6 +_,11 @@
|
||||
this.axisDirection = axisDirection;
|
||||
@@ -80,6 +_,11 @@
|
||||
this.normal = normal;
|
||||
this.normalVec3 = Vec3.atLowerCornerOf(normal);
|
||||
this.normalVec3f = new Vector3f(normal.getX(), normal.getY(), normal.getZ());
|
||||
+ // Paper start - Perf: Inline shift direction fields
|
||||
+ this.adjX = normal.getX();
|
||||
+ this.adjY = normal.getY();
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
|
||||
public static Direction[] orderedByNearest(Entity entity) {
|
||||
@@ -247,15 +_,15 @@
|
||||
@@ -252,15 +_,15 @@
|
||||
}
|
||||
|
||||
public int getStepX() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/MappedRegistry.java
|
||||
+++ b/net/minecraft/core/MappedRegistry.java
|
||||
@@ -33,17 +_,18 @@
|
||||
@@ -32,17 +_,18 @@
|
||||
public class MappedRegistry<T> implements WritableRegistry<T> {
|
||||
private final ResourceKey<? extends Registry<T>> key;
|
||||
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
@Override
|
||||
public Stream<HolderSet.Named<T>> listTags() {
|
||||
@@ -114,6 +_,7 @@
|
||||
@@ -113,6 +_,7 @@
|
||||
this.toId.put(value, size);
|
||||
this.registrationInfos.put(key, registrationInfo);
|
||||
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
|
||||
@@ -32,7 +32,7 @@
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
@@ -275,6 +_,7 @@
|
||||
@@ -274,6 +_,7 @@
|
||||
return this;
|
||||
} else {
|
||||
this.frozen = true;
|
||||
@@ -40,7 +40,7 @@
|
||||
this.byValue.forEach((object, reference) -> reference.bindValue((T)object));
|
||||
List<ResourceLocation> list = this.byKey
|
||||
.entrySet()
|
||||
@@ -509,4 +_,13 @@
|
||||
@@ -508,4 +_,13 @@
|
||||
|
||||
Stream<HolderSet.Named<T>> getTags();
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
--- a/net/minecraft/core/Rotations.java
|
||||
+++ b/net/minecraft/core/Rotations.java
|
||||
@@ -34,6 +_,18 @@
|
||||
this(tag.getFloat(0), tag.getFloat(1), tag.getFloat(2));
|
||||
}
|
||||
|
||||
+ // Paper start - faster alternative constructor
|
||||
+ private Rotations(float x, float y, float z, Void dummy_var) {
|
||||
+ this.x = x;
|
||||
+ this.y = y;
|
||||
+ this.z = z;
|
||||
+ }
|
||||
+
|
||||
@@ -26,11 +_,22 @@
|
||||
buffer.writeFloat(value.z);
|
||||
}
|
||||
};
|
||||
+ // Paper start - add internal method for skipping validation for plugins
|
||||
+ private static boolean SKIP_VALIDATION = false;
|
||||
+ public static Rotations createWithoutValidityChecks(float x, float y, float z) {
|
||||
+ return new Rotations(x, y, z, null);
|
||||
+ SKIP_VALIDATION = true;
|
||||
+ Rotations rotations = new Rotations(x, y, z);
|
||||
+ SKIP_VALIDATION = false;
|
||||
+ return rotations;
|
||||
+ }
|
||||
+ // Paper end - faster alternative constructor
|
||||
+
|
||||
public ListTag save() {
|
||||
ListTag listTag = new ListTag();
|
||||
listTag.add(FloatTag.valueOf(this.x));
|
||||
+ // Paper end - add internal method for skipping validation for plugins
|
||||
|
||||
public Rotations(float x, float y, float z) {
|
||||
+ if (SKIP_VALIDATION) { // Paper - add internal method for skipping validation for plugins
|
||||
x = !Float.isInfinite(x) && !Float.isNaN(x) ? x % 360.0F : 0.0F;
|
||||
y = !Float.isInfinite(y) && !Float.isNaN(y) ? y % 360.0F : 0.0F;
|
||||
z = !Float.isInfinite(z) && !Float.isNaN(z) ? z % 360.0F : 0.0F;
|
||||
+ } // Paper - add internal method for skipping validation for plugins
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
--- a/net/minecraft/core/Vec3i.java
|
||||
+++ b/net/minecraft/core/Vec3i.java
|
||||
@@ -16,9 +_,9 @@
|
||||
vec3i -> IntStream.of(vec3i.getX(), vec3i.getY(), vec3i.getZ())
|
||||
);
|
||||
@@ -22,9 +_,9 @@
|
||||
ByteBufCodecs.VAR_INT, Vec3i::getX, ByteBufCodecs.VAR_INT, Vec3i::getY, ByteBufCodecs.VAR_INT, Vec3i::getZ, Vec3i::new
|
||||
);
|
||||
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
|
||||
- private int x;
|
||||
- private int y;
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
public static Codec<Vec3i> offsetCodec(int maxOffset) {
|
||||
return CODEC.validate(
|
||||
@@ -35,12 +_,12 @@
|
||||
@@ -41,12 +_,12 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -28,7 +28,7 @@
|
||||
return (this.getY() + this.getZ() * 31) * 31 + this.getX();
|
||||
}
|
||||
|
||||
@@ -53,15 +_,15 @@
|
||||
@@ -59,15 +_,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
return this.z;
|
||||
}
|
||||
|
||||
@@ -235,4 +_,10 @@
|
||||
@@ -241,4 +_,10 @@
|
||||
public String toShortString() {
|
||||
return this.getX() + ", " + this.getY() + ", " + this.getZ();
|
||||
}
|
||||
|
||||
@@ -122,13 +122,14 @@
|
||||
)
|
||||
);
|
||||
addDefaultInteractions(map3);
|
||||
@@ -202,15 +_,34 @@
|
||||
@@ -202,15 +_,35 @@
|
||||
Predicate<BlockState> statePredicate,
|
||||
SoundEvent fillSound
|
||||
) {
|
||||
+ // Paper start - add hitDirection
|
||||
+ return fillBucket(state, level, pos, player, hand, emptyStack, filledStack, statePredicate, fillSound, null); // Paper - add hitDirection
|
||||
+ }
|
||||
+
|
||||
+ static InteractionResult fillBucket(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack emptyStack, ItemStack filledStack, Predicate<BlockState> statePredicate, SoundEvent fillSound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
|
||||
+ // Paper end - add hitDirection
|
||||
if (!statePredicate.test(state)) {
|
||||
@@ -137,7 +138,7 @@
|
||||
if (!level.isClientSide) {
|
||||
+ // Paper start - fire PlayerBucketFillEvent
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(level, player, pos, pos, hitDirection, emptyStack, filledStack.getItem(), hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
@@ -158,20 +159,21 @@
|
||||
level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
|
||||
}
|
||||
@@ -222,12 +_,32 @@
|
||||
@@ -222,12 +_,33 @@
|
||||
static InteractionResult emptyBucket(
|
||||
Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound
|
||||
) {
|
||||
+ // Paper start - add hitDirection
|
||||
+ return emptyBucket(level, pos, player, hand, filledStackl, state, emptySound, null);
|
||||
+ }
|
||||
+
|
||||
+ static InteractionResult emptyBucket(Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
|
||||
+ // Paper end - add hitDirection
|
||||
if (!level.isClientSide) {
|
||||
+ // Paper start - fire PlayerBucketEmptyEvent
|
||||
+ ItemStack output = new ItemStack(Items.BUCKET);
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent((net.minecraft.server.level.ServerLevel) level, player, pos, pos, hitDirection, filledStackl, hand);
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent(level, player, pos, pos, hitDirection, filledStackl, hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
@@ -193,7 +195,7 @@
|
||||
level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
|
||||
}
|
||||
@@ -236,7 +_,7 @@
|
||||
@@ -236,23 +_,23 @@
|
||||
}
|
||||
|
||||
private static InteractionResult fillWaterInteraction(
|
||||
@@ -201,13 +203,8 @@
|
||||
+ BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack, final net.minecraft.core.Direction hitDirection // Paper - add hitDirection
|
||||
) {
|
||||
return emptyBucket(
|
||||
level,
|
||||
@@ -245,20 +_,20 @@
|
||||
hand,
|
||||
filledStack,
|
||||
Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
|
||||
- SoundEvents.BUCKET_EMPTY
|
||||
+ SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
|
||||
- level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY
|
||||
+ level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY, hitDirection // Paper - add hitDirection
|
||||
);
|
||||
}
|
||||
|
||||
@@ -227,10 +224,10 @@
|
||||
) {
|
||||
return (InteractionResult)(isUnderWater(level, pos)
|
||||
? InteractionResult.CONSUME
|
||||
@@ -269,53 +_,68 @@
|
||||
@@ -263,53 +_,68 @@
|
||||
hand,
|
||||
filledStack,
|
||||
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)),
|
||||
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3),
|
||||
- SoundEvents.BUCKET_EMPTY_POWDER_SNOW
|
||||
+ SoundEvents.BUCKET_EMPTY_POWDER_SNOW, hitDirection // Paper - add hitDirection
|
||||
));
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
--- a/net/minecraft/core/component/DataComponentPatch.java
|
||||
+++ b/net/minecraft/core/component/DataComponentPatch.java
|
||||
@@ -86,6 +_,11 @@
|
||||
buffer.writeVarInt(0);
|
||||
buffer.writeVarInt(0);
|
||||
} else {
|
||||
+ // Paper start - data sanitization for items
|
||||
+ final io.papermc.paper.util.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
|
||||
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
|
||||
+ : io.papermc.paper.util.ItemObfuscationSession.currentSession();
|
||||
+ // Paper end - data sanitization for items
|
||||
int i = 0;
|
||||
int i1 = 0;
|
||||
@@ -106,6 +_,11 @@
|
||||
buffer.writeVarInt(0);
|
||||
buffer.writeVarInt(0);
|
||||
} else {
|
||||
+ // Paper start - data sanitization for items
|
||||
+ final io.papermc.paper.util.sanitizer.ItemObfuscationSession itemObfuscationSession = value.map.isEmpty()
|
||||
+ ? null // Avoid thread local lookup of current session if it won't be needed anyway.
|
||||
+ : io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession();
|
||||
+ // Paper end - data sanitization for items
|
||||
int i = 0;
|
||||
int i1 = 0;
|
||||
|
||||
@@ -93,7 +_,7 @@
|
||||
value.map
|
||||
)) {
|
||||
if (entry.getValue().isPresent()) {
|
||||
- i++;
|
||||
+ if (!io.papermc.paper.util.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
|
||||
} else {
|
||||
i1++;
|
||||
}
|
||||
@@ -106,6 +_,7 @@
|
||||
value.map
|
||||
)) {
|
||||
Optional<?> optional = entryx.getValue();
|
||||
+ optional = io.papermc.paper.util.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
|
||||
if (optional.isPresent()) {
|
||||
DataComponentType<?> dataComponentType = entryx.getKey();
|
||||
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
|
||||
@@ -125,7 +_,13 @@
|
||||
}
|
||||
@@ -113,7 +_,7 @@
|
||||
value.map
|
||||
)) {
|
||||
if (entry.getValue().isPresent()) {
|
||||
- i++;
|
||||
+ if (!io.papermc.paper.util.sanitizer.ItemComponentSanitizer.shouldDrop(itemObfuscationSession, entry.getKey())) i++; // Paper - data sanitization for items
|
||||
} else {
|
||||
i1++;
|
||||
}
|
||||
@@ -126,6 +_,7 @@
|
||||
value.map
|
||||
)) {
|
||||
Optional<?> optional = entryx.getValue();
|
||||
+ optional = io.papermc.paper.util.sanitizer.ItemComponentSanitizer.override(itemObfuscationSession, entryx.getKey(), entryx.getValue()); // Paper - data sanitization for items
|
||||
if (optional.isPresent()) {
|
||||
DataComponentType<?> dataComponentType = entryx.getKey();
|
||||
DataComponentType.STREAM_CODEC.encode(buffer, dataComponentType);
|
||||
@@ -145,7 +_,13 @@
|
||||
}
|
||||
|
||||
private static <T> void encodeComponent(RegistryFriendlyByteBuf buffer, DataComponentType<T> component, Object value) {
|
||||
- component.streamCodec().encode(buffer, (T)value);
|
||||
+ // Paper start - codec errors of random anonymous classes are useless
|
||||
+ try {
|
||||
+ component.streamCodec().encode(buffer, (T)value);
|
||||
+ } catch (final Exception e) {
|
||||
+ throw new RuntimeException("Error encoding component " + component, e);
|
||||
+ }
|
||||
+ // Paper end - codec errors of random anonymous classes are useless
|
||||
}
|
||||
};
|
||||
private static final String REMOVED_PREFIX = "!";
|
||||
@@ -230,6 +_,42 @@
|
||||
private <T> void encodeComponent(RegistryFriendlyByteBuf buffer, DataComponentType<T> component, Object value) {
|
||||
- codecGetter.apply(component).encode(buffer, (T)value);
|
||||
+ // Paper start - codec errors of random anonymous classes are useless
|
||||
+ try {
|
||||
+ codecGetter.apply(component).encode(buffer, (T)value);
|
||||
+ } catch (final Exception e) {
|
||||
+ throw new RuntimeException("Error encoding component " + component, e);
|
||||
+ }
|
||||
+ // Paper end - codec errors of random anonymous classes are useless
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -249,6 +_,42 @@
|
||||
|
||||
Builder() {
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
--- a/net/minecraft/core/component/DataComponents.java
|
||||
+++ b/net/minecraft/core/component/DataComponents.java
|
||||
@@ -180,10 +_,10 @@
|
||||
@@ -203,10 +_,10 @@
|
||||
"map_post_processing", builder -> builder.networkSynchronized(MapPostProcessing.STREAM_CODEC)
|
||||
);
|
||||
public static final DataComponentType<ChargedProjectiles> CHARGED_PROJECTILES = register(
|
||||
- "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(ChargedProjectiles.STREAM_CODEC).cacheEncoding()
|
||||
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
|
||||
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
|
||||
);
|
||||
public static final DataComponentType<BundleContents> BUNDLE_CONTENTS = register(
|
||||
- "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(BundleContents.STREAM_CODEC).cacheEncoding()
|
||||
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
|
||||
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
|
||||
);
|
||||
public static final DataComponentType<PotionContents> POTION_CONTENTS = register(
|
||||
"potion_contents", builder -> builder.persistent(PotionContents.CODEC).networkSynchronized(PotionContents.STREAM_CODEC).cacheEncoding()
|
||||
@@ -250,7 +_,7 @@
|
||||
@@ -286,7 +_,7 @@
|
||||
"pot_decorations", builder -> builder.persistent(PotDecorations.CODEC).networkSynchronized(PotDecorations.STREAM_CODEC).cacheEncoding()
|
||||
);
|
||||
public static final DataComponentType<ItemContainerContents> CONTAINER = register(
|
||||
- "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(ItemContainerContents.STREAM_CODEC).cacheEncoding()
|
||||
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.OversizedItemComponentSanitizer.CONTAINER).cacheEncoding() // Paper - sanitize container contents
|
||||
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.sanitizer.OversizedItemComponentSanitizer.CONTAINER).cacheEncoding() // Paper - sanitize container contents
|
||||
);
|
||||
public static final DataComponentType<BlockItemStateProperties> BLOCK_STATE = register(
|
||||
"block_state", builder -> builder.persistent(BlockItemStateProperties.CODEC).networkSynchronized(BlockItemStateProperties.STREAM_CODEC).cacheEncoding()
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
@@ -40,13 +_,39 @@
|
||||
@@ -40,13 +_,36 @@
|
||||
d4 = 0.0;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1);
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
@@ -10,23 +_,46 @@
|
||||
@@ -9,24 +_,37 @@
|
||||
|
||||
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
|
||||
private static final int DEFAULT_ACCURACY = 6;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private Direction direction; // Paper - cache facing direction
|
||||
+ private boolean dropper;
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior(boolean dropper) {
|
||||
+ this.dropper = dropper;
|
||||
+ }
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior() {}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
@Override
|
||||
public final ItemStack dispense(BlockSource blockSource, ItemStack item) {
|
||||
+ this.direction = blockSource.state().getValue(DispenserBlock.FACING); // Paper - cache facing direction
|
||||
@@ -32,7 +23,7 @@
|
||||
ItemStack itemStack = item.split(1);
|
||||
- spawnItem(blockSource.level(), itemStack, 6, direction, dispensePosition);
|
||||
+ // CraftBukkit start
|
||||
+ if (!DefaultDispenseItemBehavior.spawnItem(blockSource.level(), itemStack, 6, this.direction, dispensePosition, blockSource, this.dropper)) {
|
||||
+ if (!DefaultDispenseItemBehavior.spawnItem(blockSource.level(), itemStack, 6, this.direction, dispensePosition, blockSource)) {
|
||||
+ item.grow(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -50,37 +41,35 @@
|
||||
double d = position.x();
|
||||
double d1 = position.y();
|
||||
double d2 = position.z();
|
||||
@@ -43,7 +_,45 @@
|
||||
@@ -43,7 +_,43 @@
|
||||
level.random.triangle(0.2, 0.0172275 * speed),
|
||||
level.random.triangle(facing.getStepZ() * d3, 0.0172275 * speed)
|
||||
);
|
||||
+ return itemEntity; // CraftBukkit
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper
|
||||
+ public static boolean spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position dispensePosition, BlockSource blockSource, boolean dropper) {
|
||||
+ // CraftBukkit start - void -> boolean return
|
||||
+ public static boolean spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position position, BlockSource blockSource) {
|
||||
+ if (stack.isEmpty()) return true;
|
||||
+ ItemEntity itemEntity = DefaultDispenseItemBehavior.prepareItem(level, stack, speed, facing, dispensePosition);
|
||||
+ ItemEntity itemEntity = DefaultDispenseItemBehavior.prepareItem(level, stack, speed, facing, position);
|
||||
+
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(itemEntity.getDeltaMovement()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ itemEntity.setItem(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ itemEntity.setDeltaMovement(org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getVelocity()));
|
||||
+ itemEntity.setDeltaMovement(org.bukkit.craftbukkit.util.CraftVector.toVec3(event.getVelocity()));
|
||||
+
|
||||
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ if (blockSource.state().is(net.minecraft.world.level.block.Blocks.DISPENSER) && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior.getClass() != DefaultDispenseItemBehavior.class) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ } else {
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -82,16 +_,48 @@
|
||||
@@ -83,16 +_,45 @@
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
EntityType<?> type = ((SpawnEggItem)item.getItem()).getType(blockSource.level().registryAccess(), item);
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel serverLevel = blockSource.level();
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1);
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
@@ -46,42 +43,40 @@
|
||||
}
|
||||
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
+ if (shrink) item.shrink(1);
|
||||
+ // CraftBukkit end
|
||||
blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos());
|
||||
return item;
|
||||
}
|
||||
@@ -109,12 +_,40 @@
|
||||
@@ -110,12 +_,38 @@
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1);
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ final ItemStack newStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()); // Paper - use event itemstack (unwrap is fine here because the stack won't be modified)
|
||||
Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig(
|
||||
- armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, item, null
|
||||
@@ -90,76 +85,37 @@
|
||||
ArmorStand armorStand = EntityType.ARMOR_STAND.spawn(serverLevel, consumer, blockPos, EntitySpawnReason.DISPENSER, false, false);
|
||||
if (armorStand != null) {
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
+ if (shrink) item.shrink(1); // Paper
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -134,7 +_,36 @@
|
||||
livingEntity -> livingEntity instanceof Saddleable saddleable && !saddleable.isSaddled() && saddleable.isSaddleable()
|
||||
);
|
||||
if (!entitiesOfClass.isEmpty()) {
|
||||
- ((Saddleable)entitiesOfClass.get(0)).equipSaddle(item.split(1), SoundSource.BLOCKS);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ ServerLevel world = blockSource.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ ((Saddleable) entitiesOfClass.get(0)).equipSaddle(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event
|
||||
+ // CraftBukkit end
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
this.setSuccess(true);
|
||||
return item;
|
||||
} else {
|
||||
@@ -156,8 +_,36 @@
|
||||
@@ -135,8 +_,35 @@
|
||||
new AABB(blockPos),
|
||||
abstractChestedHorse1 -> abstractChestedHorse1.isAlive() && !abstractChestedHorse1.hasChest()
|
||||
)) {
|
||||
- if (abstractChestedHorse.isTamed() && abstractChestedHorse.getSlot(499).set(item)) {
|
||||
- item.shrink(1);
|
||||
+ if (abstractChestedHorse.isTamed()/* && abstractChestedHorse.getSlot(499).set(item)*/) {
|
||||
+ ItemStack singleCopy = item.copyWithCount(1); // Paper - shrink below
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack singleCopy = item.copyWithCount(1);
|
||||
+ ServerLevel world = blockSource.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleCopy);
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), abstractChestedHorse.getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below (this was actually missing and should be here, added it commented out to be consistent)
|
||||
+ this.setSuccess(false);
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
@@ -171,30 +127,25 @@
|
||||
this.setSuccess(true);
|
||||
return item;
|
||||
}
|
||||
@@ -195,8 +_,50 @@
|
||||
@@ -174,8 +_,45 @@
|
||||
DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)item.getItem();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
Level level = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ int x = blockPos.getX();
|
||||
+ int y = blockPos.getY();
|
||||
+ int z = blockPos.getZ();
|
||||
+ BlockState iblockdata = level.getBlockState(blockPos);
|
||||
+ BlockState state = level.getBlockState(blockPos);
|
||||
+ ItemStack dispensedItem = item; // Paper - track changed item from the dispense event
|
||||
+ // Paper start - correctly check if the bucket place will succeed
|
||||
+ /* Taken from SolidBucketItem#emptyContents */
|
||||
+ boolean willEmptyContentsSolidBucketItem = dispensibleContainerItem instanceof net.minecraft.world.item.SolidBucketItem && level.isInWorldBounds(blockPos) && iblockdata.isAir();
|
||||
+ boolean willEmptyContentsSolidBucketItem = dispensibleContainerItem instanceof net.minecraft.world.item.SolidBucketItem && level.isInWorldBounds(blockPos) && state.isAir();
|
||||
+ /* Taken from BucketItem#emptyContents */
|
||||
+ boolean willEmptyBucketItem = dispensibleContainerItem instanceof final net.minecraft.world.item.BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (iblockdata.isAir() || iblockdata.canBeReplaced(bucketItem.content) || (iblockdata.getBlock() instanceof net.minecraft.world.level.block.LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, level, blockPos, iblockdata, bucketItem.content)));
|
||||
+ boolean willEmptyBucketItem = dispensibleContainerItem instanceof final net.minecraft.world.item.BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (state.isAir() || state.canBeReplaced(bucketItem.content) || (state.getBlock() instanceof net.minecraft.world.level.block.LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, level, blockPos, state, bucketItem.content)));
|
||||
+ if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) {
|
||||
+ // Paper end - correctly check if the bucket place will succeed
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
@@ -203,7 +154,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
@@ -223,7 +174,7 @@
|
||||
return this.consumeWithRemainder(blockSource, item, new ItemStack(Items.BUCKET));
|
||||
} else {
|
||||
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
|
||||
@@ -219,12 +_,37 @@
|
||||
@@ -198,12 +_,19 @@
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockState = levelAccessor.getBlockState(blockPos);
|
||||
if (blockState.getBlock() instanceof BucketPickup bucketPickup) {
|
||||
@@ -234,64 +185,27 @@
|
||||
} else {
|
||||
levelAccessor.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos);
|
||||
Item item1 = itemStack.getItem();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); // From above
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
+ itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); // CraftBukkit - from above
|
||||
return this.consumeWithRemainder(blockSource, item, new ItemStack(item1));
|
||||
}
|
||||
} else {
|
||||
@@ -236,17 +_,44 @@
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -218,15 +_,26 @@
|
||||
this.setSuccess(true);
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
BlockState blockState = serverLevel.getBlockState(blockPos);
|
||||
if (BaseFireBlock.canBePlacedAt(serverLevel, blockPos, direction)) {
|
||||
- serverLevel.setBlockAndUpdate(blockPos, BaseFireBlock.getState(serverLevel, blockPos));
|
||||
@@ -303,42 +217,26 @@
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
} else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) {
|
||||
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
|
||||
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, true));
|
||||
serverLevel.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos);
|
||||
- } else if (blockState.getBlock() instanceof TntBlock) {
|
||||
+ } else if (blockState.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos())) { // CraftBukkit - TNTPrimeEvent
|
||||
TntBlock.explode(serverLevel, blockPos);
|
||||
serverLevel.removeBlock(blockPos, false);
|
||||
} else {
|
||||
@@ -266,11 +_,62 @@
|
||||
} else if (blockState.getBlock() instanceof TntBlock) {
|
||||
- if (TntBlock.prime(serverLevel, blockPos)) {
|
||||
+ if (TntBlock.prime(serverLevel, blockPos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos()))) { // CraftBukkit - TNTPrimeEvent
|
||||
serverLevel.removeBlock(blockPos, false);
|
||||
} else {
|
||||
this.setSuccess(false);
|
||||
@@ -248,11 +_,46 @@
|
||||
this.setSuccess(true);
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ level.captureTreeGeneration = true;
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
+ level.captureTreeGeneration = true; // CraftBukkit
|
||||
if (!BoneMealItem.growCrop(item, level, blockPos) && !BoneMealItem.growWaterPlant(item, level, blockPos, null)) {
|
||||
this.setSuccess(false);
|
||||
} else if (!level.isClientSide) {
|
||||
@@ -346,26 +244,27 @@
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ level.captureTreeGeneration = false;
|
||||
+ if (level.capturedBlockStates.size() > 0) {
|
||||
+ if (!level.capturedBlockStates.isEmpty()) {
|
||||
+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType;
|
||||
+ net.minecraft.world.level.block.SaplingBlock.treeType = null;
|
||||
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos, level.getWorld());
|
||||
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(level.capturedBlockStates.values());
|
||||
+ List<org.bukkit.block.BlockState> states = new java.util.ArrayList<>(level.capturedBlockStates.values());
|
||||
+ level.capturedBlockStates.clear();
|
||||
+ org.bukkit.event.world.StructureGrowEvent structureEvent = null;
|
||||
+ if (treeType != null) {
|
||||
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, blocks);
|
||||
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, states);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(location.getBlock(), null, blocks);
|
||||
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(location.getBlock(), null, states);
|
||||
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
|
||||
+
|
||||
+ if (!fertilizeEvent.isCancelled()) {
|
||||
+ for (org.bukkit.block.BlockState blockstate : blocks) {
|
||||
+ blockstate.update(true);
|
||||
+ blockSource.level().checkCapturedTreeStateForObserverNotify(blockPos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
|
||||
+ for (org.bukkit.block.BlockState state : states) {
|
||||
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) state;
|
||||
+ craftBlockState.place(craftBlockState.getFlags());
|
||||
+ blockSource.level().checkCapturedTreeStateForObserverNotify(blockPos, craftBlockState); // Paper - notify observers even if grow failed
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -373,79 +272,61 @@
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -280,11 +_,39 @@
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
- PrimedTnt primedTnt = new PrimedTnt(level, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt primedTnt = new PrimedTnt(level, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
|
||||
+ // CraftBukkit end
|
||||
level.addFreshEntity(primedTnt);
|
||||
level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
return item;
|
||||
}
|
||||
});
|
||||
@@ -296,6 +_,29 @@
|
||||
Level level = blockSource.level();
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
@@ -266,11 +_,36 @@
|
||||
return item;
|
||||
} else {
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
- PrimedTnt primedTnt = new PrimedTnt(serverLevel, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink at end and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt primedTnt = new PrimedTnt(serverLevel, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
|
||||
+ // CraftBukkit end
|
||||
serverLevel.addFreshEntity(primedTnt);
|
||||
serverLevel.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- serverLevel.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
|
||||
- item.shrink(1);
|
||||
+ serverLevel.gameEvent(null, GameEvent.ENTITY_PLACE, org.bukkit.craftbukkit.util.CraftVector.toBlockPos(event.getVelocity())); // Paper - update game event position
|
||||
+ if (shrink) item.shrink(1); // Paper
|
||||
this.setSuccess(true);
|
||||
return item;
|
||||
}
|
||||
@@ -284,6 +_,13 @@
|
||||
Level level = blockSource.level();
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, item)) {
|
||||
level.setBlock(
|
||||
blockPos,
|
||||
@@ -313,7 +_,7 @@
|
||||
@@ -299,7 +_,7 @@
|
||||
item.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
@@ -454,37 +335,21 @@
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -326,6 +_,29 @@
|
||||
@@ -312,6 +_,13 @@
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN;
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) {
|
||||
if (!level.isClientSide) {
|
||||
level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3);
|
||||
@@ -335,7 +_,7 @@
|
||||
@@ -321,7 +_,7 @@
|
||||
item.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
@@ -493,51 +358,34 @@
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -361,6 +_,29 @@
|
||||
@@ -347,6 +_,12 @@
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockState = serverLevel.getBlockState(blockPos);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - only single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (blockState.is(
|
||||
BlockTags.BEEHIVES,
|
||||
blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock
|
||||
@@ -389,6 +_,13 @@
|
||||
@@ -375,6 +_,13 @@
|
||||
this.setSuccess(true);
|
||||
if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
|
||||
if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
RespawnAnchorBlock.charge(null, level, blockPos, blockState);
|
||||
item.shrink(1);
|
||||
} else {
|
||||
@@ -412,6 +_,29 @@
|
||||
@@ -398,6 +_,28 @@
|
||||
this.setSuccess(false);
|
||||
return item;
|
||||
} else {
|
||||
@@ -546,19 +394,18 @@
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ this.setSuccess(false);
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
@@ -567,30 +414,30 @@
|
||||
for (Armadillo armadillo : entitiesOfClass) {
|
||||
if (armadillo.brushOffScute()) {
|
||||
item.hurtAndBreak(16, serverLevel, null, item1 -> {});
|
||||
@@ -432,6 +_,13 @@
|
||||
@@ -418,6 +_,13 @@
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
Optional<BlockState> waxed = HoneycombItem.getWaxed(blockState);
|
||||
if (waxed.isPresent()) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
level.setBlockAndUpdate(blockPos, waxed.get());
|
||||
level.levelEvent(3003, blockPos, 0);
|
||||
item.shrink(1);
|
||||
@@ -459,6 +_,12 @@
|
||||
@@ -445,6 +_,12 @@
|
||||
if (!serverLevel.getBlockState(blockPos1).is(BlockTags.CONVERTABLE_TO_MUD)) {
|
||||
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
|
||||
} else {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ // Paper start - Call BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos1, item, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
+ // Paper end - Call BlockDispenseEvent
|
||||
if (!serverLevel.isClientSide) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
serverLevel.sendParticles(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
@@ -14,10 +_,16 @@
|
||||
@@ -14,10 +_,17 @@
|
||||
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
@@ -13,12 +13,13 @@
|
||||
+ // Paper start
|
||||
+ return dispenseEquipment(blockSource, item, null);
|
||||
+ }
|
||||
+
|
||||
+ public static boolean dispenseEquipment(BlockSource blockSource, ItemStack item, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
|
||||
+ // Paper end
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> entitiesOfClass = blockSource.level()
|
||||
.getEntitiesOfClass(LivingEntity.class, new AABB(blockPos), entity -> entity.canEquipWithDispenser(item));
|
||||
@@ -26,13 +_,42 @@
|
||||
@@ -26,13 +_,39 @@
|
||||
} else {
|
||||
LivingEntity livingEntity = entitiesOfClass.getFirst();
|
||||
EquipmentSlot equipmentSlotForItem = livingEntity.getEquipmentSlotForItem(item);
|
||||
@@ -31,22 +32,19 @@
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) livingEntity.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) {
|
||||
+ dispenseItemBehavior.dispense(blockSource, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
@@ -55,7 +53,7 @@
|
||||
+ livingEntity.setItemSlot(equipmentSlotForItem, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
if (livingEntity instanceof Mob mob) {
|
||||
mob.setDropChance(equipmentSlotForItem, 2.0F);
|
||||
mob.setGuaranteedDrop(equipmentSlotForItem);
|
||||
mob.setPersistenceRequired();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
@@ -57,12 +_,38 @@
|
||||
@@ -57,12 +_,35 @@
|
||||
}
|
||||
|
||||
Vec3 vec31 = new Vec3(d, d1 + d3, d2);
|
||||
@@ -11,22 +11,19 @@
|
||||
+ org.bukkit.block.Block block2 = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec31.x, vec31.y, vec31.z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(vec31));
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && dispenseItemBehavior != this) {
|
||||
+ dispenseItemBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
@@ -27,17 +_,39 @@
|
||||
@@ -27,17 +_,36 @@
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
Position dispensePosition = this.dispenseConfig.positionFunction().getDispensePosition(blockSource, direction);
|
||||
@@ -15,38 +15,35 @@
|
||||
- this.dispenseConfig.uncertainty()
|
||||
- );
|
||||
- item.shrink(1);
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ ItemStack singleItemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(direction.getStepX(), direction.getStepY(), direction.getStepZ()));
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ boolean shrink = true;
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ shrink = false;
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // SPIGOT-7923: Avoid create projectiles with empty item
|
||||
+ if (!itemstack1.isEmpty()) {
|
||||
+ Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(serverLevel, dispensePosition, org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()), direction), serverLevel, itemstack1, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies
|
||||
+ iprojectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(blockSource.blockEntity());
|
||||
+ if (!singleItemStack.isEmpty()) {
|
||||
+ Projectile projectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(serverLevel, dispensePosition, org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()), direction), serverLevel, singleItemStack, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies
|
||||
+ projectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(blockSource.blockEntity());
|
||||
+ }
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
+ if (shrink) item.shrink(1);
|
||||
+ // CraftBukkit end
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -20,9 +_,32 @@
|
||||
@@ -20,9 +_,30 @@
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ this.setSuccess(false);
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
@@ -22,10 +_,38 @@
|
||||
@@ -22,10 +_,36 @@
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
Direction direction1 = blockSource.level().isEmptyBlock(blockPos.below()) ? direction : Direction.UP;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(blockSource.level(), blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1));
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ blockSource.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ blockSource.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
@@ -20,7 +18,7 @@
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack);
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
--- a/net/minecraft/core/registries/BuiltInRegistries.java
|
||||
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
|
||||
@@ -296,6 +_,17 @@
|
||||
public static final Registry<SlotDisplay.Type<?>> SLOT_DISPLAY = registerSimple(Registries.SLOT_DISPLAY, SlotDisplays::bootstrap);
|
||||
public static final Registry<RecipeBookCategory> RECIPE_BOOK_CATEGORY = registerSimple(Registries.RECIPE_BOOK_CATEGORY, RecipeBookCategories::bootstrap);
|
||||
@@ -311,6 +_,17 @@
|
||||
);
|
||||
public static final Registry<Consumer<GameTestHelper>> TEST_FUNCTION = registerSimple(Registries.TEST_FUNCTION, BuiltinTestFunctions::bootstrap);
|
||||
public static final Registry<? extends Registry<?>> REGISTRY = WRITABLE_REGISTRY;
|
||||
+ // Paper start - add built-in registry conversions
|
||||
+ public static final io.papermc.paper.registry.data.util.Conversions BUILT_IN_CONVERSIONS = new io.papermc.paper.registry.data.util.Conversions(new net.minecraft.resources.RegistryOps.RegistryInfoLookup() {
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> key, BuiltInRegistries.RegistryBootstrap<T> bootstrap) {
|
||||
return internalRegister(key, new MappedRegistry<>(key, Lifecycle.stable(), false), bootstrap);
|
||||
@@ -321,6 +_,7 @@
|
||||
@@ -336,6 +_,7 @@
|
||||
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> bootstrap
|
||||
) {
|
||||
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
|
||||
@@ -26,7 +26,7 @@
|
||||
ResourceLocation resourceLocation = key.location();
|
||||
LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
|
||||
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
|
||||
@@ -328,16 +_,34 @@
|
||||
@@ -343,16 +_,34 @@
|
||||
}
|
||||
|
||||
public static void bootStrap() {
|
||||
@@ -61,7 +61,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,6 +_,7 @@
|
||||
@@ -361,6 +_,7 @@
|
||||
|
||||
for (Registry<?> registry : REGISTRY) {
|
||||
bindBootstrappedTagsToEmpty(registry);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/data/loot/packs/VanillaChestLoot.java
|
||||
+++ b/net/minecraft/data/loot/packs/VanillaChestLoot.java
|
||||
@@ -946,7 +_,6 @@
|
||||
@@ -1000,7 +_,6 @@
|
||||
.add(
|
||||
LootItem.lootTableItem(Items.COMPASS)
|
||||
.apply(SetItemCountFunction.setCount(ConstantValue.exactly(1.0F)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestInfo.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestInfo.java
|
||||
@@ -241,7 +_,7 @@
|
||||
@@ -247,7 +_,7 @@
|
||||
AABB structureBounds = this.getStructureBounds();
|
||||
List<Entity> entitiesOfClass = this.getLevel()
|
||||
.getEntitiesOfClass(Entity.class, structureBounds.inflate(1.0), entity -> !(entity instanceof Player));
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestMainUtil.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestMainUtil.java
|
||||
@@ -77,7 +_,7 @@
|
||||
copyPacks(string, string1);
|
||||
}
|
||||
|
||||
- LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld");
|
||||
+ LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld", net.minecraft.world.level.dimension.LevelStem.OVERWORLD); // Paper
|
||||
PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess);
|
||||
MinecraftServer.spin(
|
||||
thread -> GameTestServer.create(thread, levelStorageAccess, packRepository, optionalFromOption(optionSet, tests), optionSet.has(verify))
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestServer.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestServer.java
|
||||
@@ -139,6 +_,8 @@
|
||||
BlockPos spawnPos
|
||||
@@ -133,6 +_,8 @@
|
||||
boolean verify
|
||||
) {
|
||||
super(
|
||||
+ null, // Paper
|
||||
@@ -9,7 +9,7 @@
|
||||
serverThread,
|
||||
storageSource,
|
||||
packRepository,
|
||||
@@ -154,8 +_,15 @@
|
||||
@@ -148,8 +_,15 @@
|
||||
|
||||
@Override
|
||||
public boolean initServer() {
|
||||
@@ -25,9 +25,9 @@
|
||||
+ this.loadLevel("blah");
|
||||
+ // Paper end
|
||||
ServerLevel serverLevel = this.overworld();
|
||||
this.testBatches = Lists.newArrayList(GameTestBatchFactory.fromTestFunction(this.testFunctions, serverLevel));
|
||||
serverLevel.setDefaultSpawnPos(this.spawnPos, 0.0F);
|
||||
@@ -303,6 +_,13 @@
|
||||
this.testBatches = this.evaluateTestsToRun(serverLevel);
|
||||
LOGGER.info("Started game test server");
|
||||
@@ -338,6 +_,13 @@
|
||||
public boolean shouldInformAdmins() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/gametest/framework/StructureUtils.java
|
||||
+++ b/net/minecraft/gametest/framework/StructureUtils.java
|
||||
@@ -187,7 +_,7 @@
|
||||
@@ -86,7 +_,7 @@
|
||||
level.clearBlockEvents(boundingBox1);
|
||||
AABB aabb = AABB.of(boundingBox1);
|
||||
List<Entity> entitiesOfClass = level.getEntitiesOfClass(Entity.class, aabb, entity -> !(entity instanceof Player));
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/gametest/framework/TestCommand.java
|
||||
+++ b/net/minecraft/gametest/framework/TestCommand.java
|
||||
@@ -278,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static int resetGameTestInfo(GameTestInfo gameTestInfo) {
|
||||
- gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED));
|
||||
+ gameTestInfo.getLevel().getEntities(null, gameTestInfo.getStructureBounds()).stream().forEach(entity -> entity.remove(Entity.RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD)); // Paper
|
||||
gameTestInfo.getStructureBlockEntity().placeStructure(gameTestInfo.getLevel());
|
||||
StructureUtils.removeBarriers(gameTestInfo.getStructureBounds(), gameTestInfo.getLevel());
|
||||
say(gameTestInfo.getLevel(), "Reset succeded for: " + gameTestInfo.getTestName(), ChatFormatting.GREEN);
|
||||
@@ -0,0 +1,30 @@
|
||||
--- a/net/minecraft/gametest/framework/TestEnvironmentDefinition.java
|
||||
+++ b/net/minecraft/gametest/framework/TestEnvironmentDefinition.java
|
||||
@@ -132,11 +_,11 @@
|
||||
MinecraftServer server = level.getServer();
|
||||
|
||||
for (TestEnvironmentDefinition.SetGameRules.Entry<Boolean, GameRules.BooleanValue> entry : this.boolRules) {
|
||||
- gameRules.getRule(entry.key()).set(entry.value(), server);
|
||||
+ gameRules.getRule(entry.key()).set(entry.value(), level); // Paper - per-world
|
||||
}
|
||||
|
||||
for (TestEnvironmentDefinition.SetGameRules.Entry<Integer, GameRules.IntegerValue> entry : this.intRules) {
|
||||
- gameRules.getRule(entry.key()).set(entry.value(), server);
|
||||
+ gameRules.getRule(entry.key()).set(entry.value(), level); // Paper - per-world
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,11 +_,11 @@
|
||||
MinecraftServer server = level.getServer();
|
||||
|
||||
for (TestEnvironmentDefinition.SetGameRules.Entry<Boolean, GameRules.BooleanValue> entry : this.boolRules) {
|
||||
- gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), server);
|
||||
+ gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), level); // Paper - per-world
|
||||
}
|
||||
|
||||
for (TestEnvironmentDefinition.SetGameRules.Entry<Integer, GameRules.IntegerValue> entry : this.intRules) {
|
||||
- gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), server);
|
||||
+ gameRules.getRule(entry.key()).setFrom(GameRules.getType(entry.key()).createRule(), level); // Paper - per-world
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/nbt/CompoundTag.java
|
||||
+++ b/net/minecraft/nbt/CompoundTag.java
|
||||
@@ -49,7 +_,7 @@
|
||||
@@ -54,7 +_,7 @@
|
||||
|
||||
private static CompoundTag loadCompound(DataInput input, NbtAccounter nbtAccounter) throws IOException {
|
||||
nbtAccounter.accountBytes(48L);
|
||||
@@ -9,55 +9,21 @@
|
||||
|
||||
byte b;
|
||||
while ((b = input.readByte()) != 0) {
|
||||
@@ -166,7 +_,7 @@
|
||||
@@ -171,7 +_,7 @@
|
||||
}
|
||||
|
||||
public CompoundTag() {
|
||||
- this(Maps.newHashMap());
|
||||
- this(new HashMap<>());
|
||||
+ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - Reduce memory footprint of CompoundTag
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,14 +_,34 @@
|
||||
}
|
||||
|
||||
public void putUUID(String key, UUID value) {
|
||||
+ // Paper start - Support old UUID format
|
||||
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
|
||||
+ this.tags.remove(key + "Most");
|
||||
+ this.tags.remove(key + "Least");
|
||||
+ }
|
||||
+ // Paper end - Support old UUID format
|
||||
this.tags.put(key, NbtUtils.createUUID(value));
|
||||
}
|
||||
|
||||
+
|
||||
+ /**
|
||||
+ * You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
|
||||
+ */
|
||||
public UUID getUUID(String key) {
|
||||
+ // Paper start - Support old UUID format
|
||||
+ if (!contains(key, 11) && this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
|
||||
+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
|
||||
+ }
|
||||
+ // Paper end - Support old UUID format
|
||||
return NbtUtils.loadUUID(this.get(key));
|
||||
}
|
||||
|
||||
public boolean hasUUID(String key) {
|
||||
+ // Paper start - Support old UUID format
|
||||
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Support old UUID format
|
||||
Tag tag = this.get(key);
|
||||
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
|
||||
}
|
||||
@@ -477,8 +_,16 @@
|
||||
@@ -402,9 +_,16 @@
|
||||
|
||||
@Override
|
||||
public CompoundTag copy() {
|
||||
- Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
|
||||
- HashMap<String, Tag> map = new HashMap<>();
|
||||
- this.tags.forEach((string, tag) -> map.put(string, tag.copy()));
|
||||
- return new CompoundTag(map);
|
||||
+ // Paper start - Reduce memory footprint of CompoundTag
|
||||
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);
|
||||
@@ -72,3 +38,55 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -525,22 +_,47 @@
|
||||
this.merge((CompoundTag)mapCodec.encoder().encodeStart(ops, data).getOrThrow());
|
||||
}
|
||||
|
||||
- public <T> Optional<T> read(String key, Codec<T> codec) {
|
||||
+ public <T> Optional<T> read(String key, Codec<T> codec) { // Paper - option to read via codec without logging errors - diff on change
|
||||
return this.read(key, codec, NbtOps.INSTANCE);
|
||||
}
|
||||
|
||||
- public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) {
|
||||
+ public <T> Optional<T> read(String key, Codec<T> codec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
|
||||
Tag tag = this.get(key);
|
||||
return tag == null
|
||||
? Optional.empty()
|
||||
: codec.parse(ops, tag).resultOrPartial(string -> LOGGER.error("Failed to read field ({}={}): {}", key, tag, string));
|
||||
}
|
||||
|
||||
- public <T> Optional<T> read(MapCodec<T> mapCodec) {
|
||||
+ public <T> Optional<T> read(MapCodec<T> mapCodec) { // Paper - option to read via codec without logging errors - diff on change
|
||||
return this.read(mapCodec, NbtOps.INSTANCE);
|
||||
}
|
||||
|
||||
- public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
|
||||
+ public <T> Optional<T> read(MapCodec<T> mapCodec, DynamicOps<Tag> ops) { // Paper - option to read via codec without logging errors - diff on change
|
||||
return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial(string -> LOGGER.error("Failed to read value ({}): {}", this, string));
|
||||
}
|
||||
+
|
||||
+ // Paper start - option to read via codec without logging errors
|
||||
+ // The below methods are 1 to 1 copies of the above-defined read methods without the logging part.
|
||||
+ // Copying was chosen over overloading the read methods as a boolean parameter to mark a method as quiet
|
||||
+ // is not intuitive and would require even more overloads.
|
||||
+ // Not a lot of diff in these methods is expected
|
||||
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec) {
|
||||
+ return this.readQuiet(key, codec, NbtOps.INSTANCE);
|
||||
+ }
|
||||
+
|
||||
+ public <T> Optional<T> readQuiet(String key, Codec<T> codec, DynamicOps<Tag> ops) {
|
||||
+ Tag tag = this.get(key);
|
||||
+ return tag == null
|
||||
+ ? Optional.empty()
|
||||
+ : codec.parse(ops, tag).resultOrPartial();
|
||||
+ }
|
||||
+
|
||||
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec) {
|
||||
+ return this.readQuiet(mapCodec, NbtOps.INSTANCE);
|
||||
+ }
|
||||
+
|
||||
+ public <T> Optional<T> readQuiet(MapCodec<T> mapCodec, DynamicOps<Tag> ops) {
|
||||
+ return mapCodec.decode(ops, ops.getMap(this).getOrThrow()).resultOrPartial();
|
||||
+ }
|
||||
+ // Paper end - option to read via codec without logging errors
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/nbt/NbtIo.java
|
||||
+++ b/net/minecraft/nbt/NbtIo.java
|
||||
@@ -118,6 +_,11 @@
|
||||
@@ -119,6 +_,11 @@
|
||||
}
|
||||
|
||||
public static CompoundTag read(DataInput input, NbtAccounter accounter) throws IOException {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
--- a/net/minecraft/nbt/NbtUtils.java
|
||||
+++ b/net/minecraft/nbt/NbtUtils.java
|
||||
@@ -143,8 +_,10 @@
|
||||
if (!tag.contains("Name", 8)) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
} else {
|
||||
- ResourceLocation resourceLocation = ResourceLocation.parse(tag.getString("Name"));
|
||||
- Optional<? extends Holder<Block>> optional = blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation));
|
||||
+ // Paper start - Validate resource location
|
||||
+ ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getString("Name"));
|
||||
+ Optional<? extends Holder<Block>> optional = resourceLocation != null ? blockGetter.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty();
|
||||
+ // Paper end - Validate resource location
|
||||
if (optional.isEmpty()) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
} else {
|
||||
@@ -0,0 +1,21 @@
|
||||
--- a/net/minecraft/nbt/SnbtGrammar.java
|
||||
+++ b/net/minecraft/nbt/SnbtGrammar.java
|
||||
@@ -591,7 +_,7 @@
|
||||
Atom<List<Entry<String, T>>> atom30 = Atom.of("map_entries");
|
||||
dictionary.put(atom30, Term.repeatedWithTrailingSeparator(namedRule3, atom30, StringReaderTerms.character(',')), scope -> scope.getOrThrow(atom30));
|
||||
Atom<T> atom31 = Atom.of("map_literal");
|
||||
- dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), dictionary.named(atom30), StringReaderTerms.character('}')), scope -> {
|
||||
+ dictionary.put(atom31, Term.sequence(StringReaderTerms.character('{'), Scope.increaseDepth(), dictionary.named(atom30), Scope.decreaseDepth(), StringReaderTerms.character('}')), scope -> { // Paper - track depth
|
||||
List<Entry<String, T>> list = scope.getOrThrow(atom30);
|
||||
if (list.isEmpty()) {
|
||||
return object2;
|
||||
@@ -626,7 +_,9 @@
|
||||
atom35,
|
||||
Term.sequence(
|
||||
StringReaderTerms.character('['),
|
||||
+ Scope.increaseDepth(), // Paper - track depth
|
||||
Term.alternative(Term.sequence(dictionary.named(atom33), StringReaderTerms.character(';'), dictionary.named(atom34)), dictionary.named(atom32)),
|
||||
+ Scope.decreaseDepth(), // Paper - track depth
|
||||
StringReaderTerms.character(']')
|
||||
),
|
||||
parseState -> {
|
||||
@@ -1,54 +0,0 @@
|
||||
--- a/net/minecraft/nbt/TagParser.java
|
||||
+++ b/net/minecraft/nbt/TagParser.java
|
||||
@@ -49,6 +_,7 @@
|
||||
}, CompoundTag::toString);
|
||||
public static final Codec<CompoundTag> LENIENT_CODEC = Codec.withAlternative(AS_CODEC, CompoundTag.CODEC);
|
||||
private final StringReader reader;
|
||||
+ private int depth; // Paper
|
||||
|
||||
public static CompoundTag parseTag(String text) throws CommandSyntaxException {
|
||||
return new TagParser(new StringReader(text)).readSingleStruct();
|
||||
@@ -159,6 +_,7 @@
|
||||
|
||||
public CompoundTag readStruct() throws CommandSyntaxException {
|
||||
this.expect('{');
|
||||
+ this.increaseDepth(); // Paper
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
this.reader.skipWhitespace();
|
||||
|
||||
@@ -182,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.expect('}');
|
||||
+ this.depth--; // Paper
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
@@ -191,6 +_,7 @@
|
||||
if (!this.reader.canRead()) {
|
||||
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
|
||||
} else {
|
||||
+ this.increaseDepth(); // Paper
|
||||
ListTag listTag = new ListTag();
|
||||
TagType<?> tagType = null;
|
||||
|
||||
@@ -216,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.expect(']');
|
||||
+ this.depth--; // Paper
|
||||
return listTag;
|
||||
}
|
||||
}
|
||||
@@ -287,5 +_,11 @@
|
||||
private void expect(char expected) throws CommandSyntaxException {
|
||||
this.reader.skipWhitespace();
|
||||
this.reader.expect(expected);
|
||||
+ }
|
||||
+ private void increaseDepth() throws CommandSyntaxException {
|
||||
+ this.depth++;
|
||||
+ if (this.depth > 512) {
|
||||
+ throw new io.papermc.paper.brigadier.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512");
|
||||
+ }
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
|
||||
public static <T> IntFunction<T> limitValue(IntFunction<T> function, int limit) {
|
||||
@@ -527,7 +_,7 @@
|
||||
@@ -539,7 +_,7 @@
|
||||
|
||||
try {
|
||||
NbtIo.writeAnyTag(nbt, new ByteBufOutputStream(buffer));
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
--- a/net/minecraft/network/HashedStack.java
|
||||
+++ b/net/minecraft/network/HashedStack.java
|
||||
@@ -17,7 +_,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
|
||||
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
|
||||
return stack.isEmpty();
|
||||
}
|
||||
};
|
||||
@@ -27,7 +_,7 @@
|
||||
hashedStack -> hashedStack instanceof HashedStack.ActualItem actualItem ? Optional.of(actualItem) : Optional.empty()
|
||||
);
|
||||
|
||||
- boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator);
|
||||
+ boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching); // Paper - add flag to simplify remote matching logic
|
||||
|
||||
static HashedStack create(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
|
||||
return (HashedStack)(stack.isEmpty()
|
||||
@@ -47,10 +_,10 @@
|
||||
);
|
||||
|
||||
@Override
|
||||
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
|
||||
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
|
||||
return this.count == stack.getCount()
|
||||
&& this.item.equals(stack.getItemHolder())
|
||||
- && this.components.matches(stack.getComponentsPatch(), hashGenerator);
|
||||
+ && (simplifyMatching || this.components.matches(stack.getComponentsPatch(), hashGenerator)); // Paper - add flag to simplify remote matching logic
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
- Component decorate(@Nullable ServerPlayer player, Component message);
|
||||
+ ChatDecorator PLAIN = (player, message) -> java.util.concurrent.CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events
|
||||
+
|
||||
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
|
||||
+ java.util.concurrent.CompletableFuture<Component> decorate(@Nullable ServerPlayer player, Component message); // Paper - adventure; support async chat decoration events
|
||||
+
|
||||
+ // Paper start - adventure; support async chat decoration events
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/chat/ComponentSerialization.java
|
||||
+++ b/net/minecraft/network/chat/ComponentSerialization.java
|
||||
@@ -37,9 +_,31 @@
|
||||
@@ -35,9 +_,31 @@
|
||||
|
||||
public class ComponentSerialization {
|
||||
public static final Codec<Component> CODEC = Codec.recursive("Component", ComponentSerialization::createCodec);
|
||||
@@ -34,7 +34,7 @@
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
|
||||
ByteBufCodecs::optional
|
||||
);
|
||||
@@ -102,7 +_,25 @@
|
||||
@@ -94,7 +_,25 @@
|
||||
return ExtraCodecs.orCompressed(mapCodec2, mapCodec1);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{
|
||||
PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
|
||||
};
|
||||
@@ -115,6 +_,34 @@
|
||||
@@ -107,6 +_,34 @@
|
||||
)
|
||||
.apply(instance, MutableComponent::new)
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate.
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate.
|
||||
public static Optional<MutableComponent> updateForEntity(
|
||||
@Nullable CommandSourceStack commandSourceStack, Optional<Component> optionalComponent, @Nullable Entity entity, int recursionDepth
|
||||
) throws CommandSyntaxException {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/chat/PlayerChatMessage.java
|
||||
+++ b/net/minecraft/network/chat/PlayerChatMessage.java
|
||||
@@ -17,6 +_,43 @@
|
||||
@@ -18,6 +_,43 @@
|
||||
public record PlayerChatMessage(
|
||||
SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask
|
||||
) {
|
||||
@@ -44,7 +44,7 @@
|
||||
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec(
|
||||
instance -> instance.group(
|
||||
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
|
||||
@@ -47,7 +_,14 @@
|
||||
@@ -48,7 +_,14 @@
|
||||
}
|
||||
|
||||
public PlayerChatMessage withUnsignedContent(Component message) {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
--- a/net/minecraft/network/chat/contents/NbtContents.java
|
||||
+++ b/net/minecraft/network/chat/contents/NbtContents.java
|
||||
@@ -115,7 +_,7 @@
|
||||
}).map(Tag::getAsString);
|
||||
@@ -119,7 +_,7 @@
|
||||
if (this.interpreting) {
|
||||
RegistryOps<Tag> registryOps = nbtPathPattern.registryAccess().createSerializationContext(NbtOps.INSTANCE);
|
||||
Component component = DataFixUtils.orElse(
|
||||
- ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR
|
||||
+ ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR // Paper - validate separator
|
||||
);
|
||||
return stream.flatMap(text -> {
|
||||
return stream.flatMap(tag -> {
|
||||
try {
|
||||
@@ -127,7 +_,7 @@
|
||||
}
|
||||
@@ -132,7 +_,7 @@
|
||||
}).reduce((mutableComponent, component1) -> mutableComponent.append(component).append(component1)).orElseGet(Component::empty);
|
||||
} else {
|
||||
Stream<String> stream1 = stream.map(NbtContents::asString);
|
||||
- return ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth)
|
||||
+ return ComponentUtils.updateSeparatorForEntity(nbtPathPattern, this.separator, entity, recursionDepth) // Paper - validate separator
|
||||
.map(
|
||||
mutableComponent -> stream.map(Component::literal)
|
||||
mutableComponent -> stream1.map(Component::literal)
|
||||
.reduce((mutableComponent1, otherMutableComponent) -> mutableComponent1.append(mutableComponent).append(otherMutableComponent))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
|
||||
@@ -378,6 +_,48 @@
|
||||
@@ -389,6 +_,48 @@
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
--- a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
|
||||
@@ -35,6 +_,20 @@
|
||||
this.items = ItemStack.OPTIONAL_LIST_STREAM_CODEC.decode(buffer);
|
||||
this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
|
||||
}
|
||||
@@ -22,6 +_,21 @@
|
||||
ClientboundContainerSetContentPacket::new
|
||||
);
|
||||
|
||||
+ // Paper start - Handle large packets disconnecting client
|
||||
+ @Override
|
||||
+ public boolean hasLargePacketFallback() {
|
||||
@@ -18,6 +18,7 @@
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Handle large packets disconnecting client
|
||||
|
||||
private void write(RegistryFriendlyByteBuf buffer) {
|
||||
buffer.writeContainerId(this.containerId);
|
||||
+
|
||||
@Override
|
||||
public PacketType<ClientboundContainerSetContentPacket> type() {
|
||||
return GamePacketTypes.CLIENTBOUND_CONTAINER_SET_CONTENT;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
||||
@@ -52,7 +_,7 @@
|
||||
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
|
||||
@@ -50,7 +_,7 @@
|
||||
public ClientboundLevelChunkPacketData(RegistryFriendlyByteBuf buffer, int x, int z) {
|
||||
this.heightmaps = HEIGHTMAPS_STREAM_CODEC.decode(buffer);
|
||||
int varInt = buffer.readVarInt();
|
||||
- if (varInt > 2097152) {
|
||||
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
|
||||
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
|
||||
} else {
|
||||
int varInt = buffer.readVarInt();
|
||||
- if (varInt > 2097152) {
|
||||
+ if (varInt > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
|
||||
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
|
||||
} else {
|
||||
this.buffer = new byte[varInt];
|
||||
@@ -154,6 +_,7 @@
|
||||
this.buffer = new byte[varInt];
|
||||
@@ -151,6 +_,7 @@
|
||||
CompoundTag updateTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
|
||||
BlockPos blockPos = blockEntity.getBlockPos();
|
||||
int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
- true,
|
||||
+ listed, // Paper - Add Listing API for Player
|
||||
player.connection.latency(),
|
||||
player.gameMode.getGameModeForPlayer(),
|
||||
player.gameMode(),
|
||||
player.getTabListDisplayName(),
|
||||
@@ -172,6 +_,11 @@
|
||||
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
private static void pack(List<SynchedEntityData.DataValue<?>> dataValues, RegistryFriendlyByteBuf buffer) {
|
||||
+ try (io.papermc.paper.util.ItemObfuscationSession ignored = io.papermc.paper.util.ItemObfuscationSession.start(io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level)) { // Paper - data sanitization
|
||||
+ try (io.papermc.paper.util.sanitizer.ItemObfuscationSession ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.start(io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level)) { // Paper - data sanitization
|
||||
for (SynchedEntityData.DataValue<?> dataValue : dataValues) {
|
||||
dataValue.write(buffer);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
buffer.writeVarInt(this.entity);
|
||||
int size = this.slots.size();
|
||||
|
||||
+ try (final io.papermc.paper.util.ItemObfuscationSession ignored = io.papermc.paper.util.ItemObfuscationSession.start(this.sanitize ? io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level : io.papermc.paper.util.ItemObfuscationSession.ObfuscationLevel.NONE)) { // Paper - data sanitization
|
||||
+ try (final io.papermc.paper.util.sanitizer.ItemObfuscationSession ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.start(this.sanitize ? io.papermc.paper.configuration.GlobalConfiguration.get().anticheat.obfuscation.items.binding.level : io.papermc.paper.util.sanitizer.ItemObfuscationSession.ObfuscationLevel.NONE)) { // Paper - data sanitization
|
||||
for (int i = 0; i < size; i++) {
|
||||
Pair<EquipmentSlot, ItemStack> pair = this.slots.get(i);
|
||||
EquipmentSlot equipmentSlot = pair.getFirst();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java
|
||||
@@ -30,6 +_,11 @@
|
||||
@@ -31,6 +_,11 @@
|
||||
private final Collection<String> players;
|
||||
private final Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters;
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
private ClientboundSetPlayerTeamPacket(String name, int method, Optional<ClientboundSetPlayerTeamPacket.Parameters> parameters, Collection<String> players) {
|
||||
this.name = name;
|
||||
this.method = method;
|
||||
@@ -198,7 +_,7 @@
|
||||
@@ -199,7 +_,7 @@
|
||||
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.displayName);
|
||||
buffer.writeByte(this.options);
|
||||
buffer.writeUtf(this.nametagVisibility);
|
||||
- buffer.writeUtf(this.collisionRule);
|
||||
+ buffer.writeUtf(!io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER.name : this.collisionRule); // Paper - Configurable player collision
|
||||
Team.Visibility.STREAM_CODEC.encode(buffer, this.nametagVisibility);
|
||||
- Team.CollisionRule.STREAM_CODEC.encode(buffer, this.collisionRule);
|
||||
+ Team.CollisionRule.STREAM_CODEC.encode(buffer, !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions ? PlayerTeam.CollisionRule.NEVER : this.collisionRule); // Paper - Configurable player collision
|
||||
buffer.writeEnum(this.color);
|
||||
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerPrefix);
|
||||
ComponentSerialization.TRUSTED_STREAM_CODEC.encode(buffer, this.playerSuffix);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
);
|
||||
+ // Spigot start
|
||||
+ public ClientboundSystemChatPacket(net.md_5.bungee.api.chat.BaseComponent[] content, boolean overlay) {
|
||||
+ this(org.bukkit.craftbukkit.util.CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(content)), overlay);
|
||||
+ this(org.bukkit.craftbukkit.util.CraftChatMessage.bungeeToVanilla(content), overlay);
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+ // Paper start
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundContainerClickPacket.java
|
||||
@@ -17,7 +_,7 @@
|
||||
);
|
||||
private static final int MAX_SLOT_COUNT = 128;
|
||||
private static final StreamCodec<RegistryFriendlyByteBuf, Int2ObjectMap<ItemStack>> SLOTS_STREAM_CODEC = ByteBufCodecs.map(
|
||||
- Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC, 128
|
||||
+ Int2ObjectOpenHashMap::new, ByteBufCodecs.SHORT.map(Short::intValue, Integer::shortValue), ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth), 128 // Paper - Track codec depth
|
||||
);
|
||||
private final int containerId;
|
||||
private final int stateId;
|
||||
@@ -46,7 +_,7 @@
|
||||
this.buttonNum = buffer.readByte();
|
||||
this.clickType = buffer.readEnum(ClickType.class);
|
||||
this.changedSlots = Int2ObjectMaps.unmodifiable(SLOTS_STREAM_CODEC.decode(buffer));
|
||||
- this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
|
||||
+ this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs::trackDepth).decode(buffer); // Paper - Track codec depth
|
||||
}
|
||||
|
||||
private void write(RegistryFriendlyByteBuf buffer) {
|
||||
@@ -4,8 +4,8 @@
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, ServerboundSetCreativeModeSlotPacket> STREAM_CODEC = StreamCodec.composite(
|
||||
ByteBufCodecs.SHORT,
|
||||
ServerboundSetCreativeModeSlotPacket::slotNum,
|
||||
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC),
|
||||
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
|
||||
- ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC),
|
||||
+ ItemStack.validatedStreamCodec(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC).apply(ByteBufCodecs::trackDepth), // Paper - Track codec depth
|
||||
ServerboundSetCreativeModeSlotPacket::itemStack,
|
||||
ServerboundSetCreativeModeSlotPacket::new
|
||||
);
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
--- a/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
+++ b/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
@@ -45,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) {
|
||||
+ public <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { // Paper - public
|
||||
return (SynchedEntityData.DataItem<T>)this.itemsById[key.id()];
|
||||
}
|
||||
|
||||
@@ -67,6 +_,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/resources/RegistryDataLoader.java
|
||||
+++ b/net/minecraft/resources/RegistryDataLoader.java
|
||||
@@ -247,13 +_,14 @@
|
||||
@@ -271,13 +_,14 @@
|
||||
RegistryOps<JsonElement> ops,
|
||||
ResourceKey<E> resourceKey,
|
||||
Resource resource,
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +_,7 @@
|
||||
@@ -291,6 +_,7 @@
|
||||
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
|
||||
RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
for (Entry<ResourceLocation, Resource> entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) {
|
||||
ResourceLocation resourceLocation = entry.getKey();
|
||||
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), fileToIdConverter.fileToId(resourceLocation));
|
||||
@@ -274,7 +_,7 @@
|
||||
@@ -298,7 +_,7 @@
|
||||
RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(resource.knownPackInfo());
|
||||
|
||||
try {
|
||||
@@ -34,7 +34,7 @@
|
||||
} catch (Exception var14) {
|
||||
loadingErrors.put(
|
||||
resourceKey,
|
||||
@@ -283,7 +_,9 @@
|
||||
@@ -307,7 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
static <E> void loadContentsFromNetwork(
|
||||
@@ -300,6 +_,7 @@
|
||||
@@ -324,6 +_,7 @@
|
||||
RegistryOps<JsonElement> registryOps1 = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
|
||||
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
for (RegistrySynchronization.PackedRegistryEntry packedRegistryEntry : networkedRegistryData.elements) {
|
||||
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), packedRegistryEntry.id());
|
||||
Optional<Tag> optional = packedRegistryEntry.data();
|
||||
@@ -318,7 +_,7 @@
|
||||
@@ -342,7 +_,7 @@
|
||||
|
||||
try {
|
||||
Resource resourceOrThrow = resourceProvider.getResourceOrThrow(resourceLocation);
|
||||
@@ -62,7 +62,7 @@
|
||||
} catch (Exception var17) {
|
||||
loadingErrors.put(resourceKey, new IllegalStateException("Failed to parse local data", var17));
|
||||
}
|
||||
@@ -360,6 +_,7 @@
|
||||
@@ -384,6 +_,7 @@
|
||||
|
||||
RegistryDataLoader.Loader<T> create(Lifecycle registryLifecycle, Map<ResourceKey<?>, Exception> loadingErrors) {
|
||||
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, registryLifecycle);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/resources/ResourceLocation.java
|
||||
+++ b/net/minecraft/resources/ResourceLocation.java
|
||||
@@ -32,6 +_,7 @@
|
||||
@@ -23,6 +_,7 @@
|
||||
public static final char NAMESPACE_SEPARATOR = ':';
|
||||
public static final String DEFAULT_NAMESPACE = "minecraft";
|
||||
public static final String REALMS_NAMESPACE = "realms";
|
||||
@@ -8,7 +8,7 @@
|
||||
private final String namespace;
|
||||
private final String path;
|
||||
|
||||
@@ -40,6 +_,13 @@
|
||||
@@ -31,6 +_,13 @@
|
||||
|
||||
assert isValidPath(path);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
this.namespace = namespace;
|
||||
this.path = path;
|
||||
}
|
||||
@@ -252,7 +_,7 @@
|
||||
@@ -243,7 +_,7 @@
|
||||
|
||||
private static String assertValidNamespace(String namespace, String path) {
|
||||
if (!isValidNamespace(namespace)) {
|
||||
@@ -31,7 +31,7 @@
|
||||
} else {
|
||||
return namespace;
|
||||
}
|
||||
@@ -277,7 +_,7 @@
|
||||
@@ -268,7 +_,7 @@
|
||||
|
||||
private static String assertValidPath(String namespace, String path) {
|
||||
if (!isValidPath(path)) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) {
|
||||
throw new IllegalStateException("Unable to load registries");
|
||||
} else {
|
||||
@@ -54,11 +_,80 @@
|
||||
@@ -54,11 +_,85 @@
|
||||
EntitySelectorOptions.bootStrap();
|
||||
DispenseItemBehavior.bootStrap();
|
||||
CauldronInteraction.bootStrap();
|
||||
@@ -25,25 +25,30 @@
|
||||
+ // CraftBukkit start
|
||||
+ // TODO Check what of this is needed, maybe report it to Mojira. if deemed relevant, move to the respective classes
|
||||
+ // Used in CraftLegacy
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign");
|
||||
+ for (int i = 0; i <= 15; i++) {
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(
|
||||
+ 1008 + i,
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:oak_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:standing_sign",
|
||||
+ "Properties", java.util.Map.of("rotation", String.valueOf(i))
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440, "{Name:'minecraft:portal',Properties:{axis:'x'}}", "{Name:'minecraft:portal',Properties:{axis:'x'}}");
|
||||
+ net.minecraft.util.datafix.fixes.BlockStateData.register(1440,
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE),
|
||||
+ new com.mojang.serialization.Dynamic<>(com.mojang.serialization.JavaOps.INSTANCE, java.util.Map.of(
|
||||
+ "Name", "minecraft:portal",
|
||||
+ "Properties", java.util.Map.of("axis", "x")
|
||||
+ )).convert(net.minecraft.nbt.NbtOps.INSTANCE)
|
||||
+ );
|
||||
+
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard");
|
||||
+ net.minecraft.util.datafix.fixes.ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals");
|
||||
|
||||
@@ -52,13 +52,13 @@
|
||||
+ File configFile = (File) optionSet.valueOf("bukkit-settings");
|
||||
+ org.bukkit.configuration.file.YamlConfiguration configuration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(configFile);
|
||||
+ configuration.options().copyDefaults(true);
|
||||
+ configuration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), com.google.common.base.Charsets.UTF_8)));
|
||||
+ configuration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), java.nio.charset.StandardCharsets.UTF_8)));
|
||||
+ configuration.save(configFile);
|
||||
+
|
||||
+ File commandFile = (File) optionSet.valueOf("commands-settings");
|
||||
+ org.bukkit.configuration.file.YamlConfiguration commandsConfiguration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(commandFile);
|
||||
+ commandsConfiguration.options().copyDefaults(true);
|
||||
+ commandsConfiguration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), com.google.common.base.Charsets.UTF_8)));
|
||||
+ commandsConfiguration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), java.nio.charset.StandardCharsets.UTF_8)));
|
||||
+ commandsConfiguration.save(commandFile);
|
||||
+ // CraftBukkit end
|
||||
LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath());
|
||||
@@ -116,7 +116,7 @@
|
||||
Dynamic<?> dataTag;
|
||||
if (levelStorageAccess.hasWorldData()) {
|
||||
LevelSummary summary;
|
||||
@@ -169,12 +_,30 @@
|
||||
@@ -169,12 +_,33 @@
|
||||
}
|
||||
|
||||
Dynamic<?> dynamic = dataTag;
|
||||
@@ -134,12 +134,15 @@
|
||||
+ }
|
||||
+ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta");
|
||||
+ try {
|
||||
+ com.google.common.io.Files.write("{\n"
|
||||
+ + " \"pack\": {\n"
|
||||
+ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n"
|
||||
+ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(net.minecraft.server.packs.PackType.SERVER_DATA) + "\n"
|
||||
+ + " }\n"
|
||||
+ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8);
|
||||
+ com.google.common.io.Files.asCharSink(mcMeta, java.nio.charset.StandardCharsets.UTF_8).write("""
|
||||
+ {
|
||||
+ "pack": {
|
||||
+ "description": "Data pack for resources provided by Bukkit plugins",
|
||||
+ "pack_format": %d
|
||||
+ }
|
||||
+ }
|
||||
+ """.formatted(SharedConstants.getCurrentVersion().getPackVersion(net.minecraft.server.packs.PackType.SERVER_DATA))
|
||||
+ );
|
||||
+ } catch (java.io.IOException ex) {
|
||||
+ throw new RuntimeException("Could not initialize Bukkit datapack", ex);
|
||||
+ }
|
||||
@@ -180,11 +183,11 @@
|
||||
|
||||
+ /*
|
||||
RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess();
|
||||
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
|
||||
if (optionSet.has(optionSpec4) || hasOptionSpec1) {
|
||||
@@ -245,9 +_,13 @@
|
||||
|
||||
WorldData worldData = worldStem.worldData();
|
||||
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
|
||||
@@ -245,9 +_,13 @@
|
||||
}
|
||||
|
||||
levelStorageAccess.saveDataTag(frozen, worldData);
|
||||
+ */
|
||||
final DedicatedServer dedicatedServer = MinecraftServer.spin(
|
||||
@@ -241,12 +244,12 @@
|
||||
} catch (Exception var42) {
|
||||
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var42);
|
||||
}
|
||||
@@ -316,7 +_,7 @@
|
||||
@@ -317,7 +_,7 @@
|
||||
RegistryAccess registryAccess,
|
||||
boolean recreateRegionFiles
|
||||
) {
|
||||
- LOGGER.info("Forcing world upgrade!");
|
||||
+ LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit
|
||||
|
||||
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, registryAccess, eraseCache, recreateRegionFiles)) {
|
||||
try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, worldData, registryAccess, eraseCache, recreateRegionFiles)) {
|
||||
Component component = null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -174,11 +_,13 @@
|
||||
@@ -173,11 +_,13 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource {
|
||||
@@ -15,7 +15,7 @@
|
||||
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
|
||||
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
|
||||
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
|
||||
@@ -218,6 +_,7 @@
|
||||
@@ -217,6 +_,7 @@
|
||||
private Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap();
|
||||
private PlayerList playerList;
|
||||
private volatile boolean running = true;
|
||||
@@ -23,7 +23,7 @@
|
||||
private boolean stopped;
|
||||
private int tickCount;
|
||||
private int ticksUntilAutosave = 6000;
|
||||
@@ -226,11 +_,15 @@
|
||||
@@ -225,11 +_,15 @@
|
||||
private boolean preventProxyConnections;
|
||||
private boolean pvp;
|
||||
private boolean allowFlight;
|
||||
@@ -41,7 +41,7 @@
|
||||
@Nullable
|
||||
private KeyPair keyPair;
|
||||
@Nullable
|
||||
@@ -271,10 +_,37 @@
|
||||
@@ -270,10 +_,37 @@
|
||||
private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector();
|
||||
private final DiscontinuousFrame tickFrame;
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
if (Runtime.getRuntime().availableProcessors() > 4) {
|
||||
thread.setPriority(8);
|
||||
}
|
||||
@@ -286,6 +_,10 @@
|
||||
@@ -285,6 +_,10 @@
|
||||
}
|
||||
|
||||
public MinecraftServer(
|
||||
@@ -91,7 +91,7 @@
|
||||
Thread serverThread,
|
||||
LevelStorageSource.LevelStorageAccess storageSource,
|
||||
PackRepository packRepository,
|
||||
@@ -296,9 +_,10 @@
|
||||
@@ -295,9 +_,10 @@
|
||||
ChunkProgressListenerFactory progressListenerFactory
|
||||
) {
|
||||
super("Server");
|
||||
@@ -103,7 +103,7 @@
|
||||
throw new IllegalStateException("Missing Overworld dimension data");
|
||||
} else {
|
||||
this.proxy = proxy;
|
||||
@@ -309,7 +_,7 @@
|
||||
@@ -308,7 +_,7 @@
|
||||
services.profileCache().setExecutor(this);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
this.tickRateManager = new ServerTickRateManager(this);
|
||||
this.progressListenerFactory = progressListenerFactory;
|
||||
this.storageSource = storageSource;
|
||||
@@ -328,6 +_,38 @@
|
||||
@@ -327,6 +_,38 @@
|
||||
this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures());
|
||||
this.tickFrame = TracyClient.createDiscontinuousFrame("Server Tick");
|
||||
}
|
||||
@@ -151,7 +151,7 @@
|
||||
}
|
||||
|
||||
private void readScoreboard(DimensionDataStorage dataStorage) {
|
||||
@@ -336,18 +_,13 @@
|
||||
@@ -335,18 +_,13 @@
|
||||
|
||||
protected abstract boolean initServer() throws IOException;
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
if (profiledDuration != null) {
|
||||
profiledDuration.finish(true);
|
||||
}
|
||||
@@ -364,25 +_,265 @@
|
||||
@@ -363,25 +_,265 @@
|
||||
protected void forceDifficulty() {
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@
|
||||
+
|
||||
+ primaryLevelData.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end)
|
||||
+ if (this.options.has("forceUpgrade")) {
|
||||
+ net.minecraft.server.Main.forceUpgrade(levelStorageAccess, net.minecraft.util.datafix.DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> true, registryAccess, this.options.has("recreateRegionFiles"));
|
||||
+ net.minecraft.server.Main.forceUpgrade(levelStorageAccess, primaryLevelData, net.minecraft.util.datafix.DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> true, registryAccess, this.options.has("recreateRegionFiles"));
|
||||
+ }
|
||||
+
|
||||
+ // Now modelled off the createLevels method
|
||||
@@ -457,7 +457,7 @@
|
||||
if (!serverLevelData.isInitialized()) {
|
||||
try {
|
||||
setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld);
|
||||
@@ -403,47 +_,30 @@
|
||||
@@ -402,47 +_,30 @@
|
||||
|
||||
serverLevelData.setInitialized(true);
|
||||
}
|
||||
@@ -522,7 +522,7 @@
|
||||
int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level);
|
||||
if (spawnHeight < level.getMinY()) {
|
||||
BlockPos worldPosition = chunkPos.getWorldPosition();
|
||||
@@ -495,26 +_,31 @@
|
||||
@@ -494,36 +_,48 @@
|
||||
serverLevelData.setGameType(GameType.SPECTATOR);
|
||||
}
|
||||
|
||||
@@ -557,12 +557,11 @@
|
||||
|
||||
- for (ServerLevel serverLevel1 : this.levels.values()) {
|
||||
+ if (true) {
|
||||
+ ServerLevel serverLevel1 = serverLevel;
|
||||
+ final ServerLevel serverLevel1 = serverLevel;
|
||||
+ // CraftBukkit end
|
||||
ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks");
|
||||
if (forcedChunksSavedData != null) {
|
||||
LongIterator longIterator = forcedChunksSavedData.getChunks().iterator();
|
||||
@@ -527,10 +_,17 @@
|
||||
TicketStorage ticketStorage = serverLevel1.getDataStorage().get(TicketStorage.TYPE);
|
||||
if (ticketStorage != null) {
|
||||
ticketStorage.activateAllDeactivatedTickets();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,11 +582,11 @@
|
||||
}
|
||||
|
||||
public GameType getDefaultGameType() {
|
||||
@@ -559,11 +_,14 @@
|
||||
@@ -552,11 +_,14 @@
|
||||
flag = true;
|
||||
}
|
||||
|
||||
+ /* // CraftBukkit start - moved to WorldServer.save
|
||||
+ /* // CraftBukkit start - moved to ServerLevel#save
|
||||
ServerLevel serverLevel1 = this.overworld();
|
||||
ServerLevelData serverLevelData = this.worldData.overworldData();
|
||||
serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings());
|
||||
@@ -598,7 +597,7 @@
|
||||
if (flush) {
|
||||
for (ServerLevel serverLevel2 : this.getAllLevels()) {
|
||||
LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName());
|
||||
@@ -593,18 +_,48 @@
|
||||
@@ -586,18 +_,48 @@
|
||||
this.stopServer();
|
||||
}
|
||||
|
||||
@@ -648,7 +647,7 @@
|
||||
}
|
||||
|
||||
LOGGER.info("Saving worlds");
|
||||
@@ -646,6 +_,25 @@
|
||||
@@ -639,6 +_,25 @@
|
||||
} catch (IOException var4) {
|
||||
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4);
|
||||
}
|
||||
@@ -674,7 +673,7 @@
|
||||
}
|
||||
|
||||
public String getLocalIp() {
|
||||
@@ -661,6 +_,14 @@
|
||||
@@ -654,6 +_,14 @@
|
||||
}
|
||||
|
||||
public void halt(boolean waitForServer) {
|
||||
@@ -689,7 +688,7 @@
|
||||
this.running = false;
|
||||
if (waitForServer) {
|
||||
try {
|
||||
@@ -671,6 +_,57 @@
|
||||
@@ -664,6 +_,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,7 +746,7 @@
|
||||
protected void runServer() {
|
||||
try {
|
||||
if (!this.initServer()) {
|
||||
@@ -681,6 +_,35 @@
|
||||
@@ -674,6 +_,35 @@
|
||||
this.statusIcon = this.loadStatusIcon().orElse(null);
|
||||
this.status = this.buildServerStatus();
|
||||
|
||||
@@ -783,7 +782,7 @@
|
||||
while (this.running) {
|
||||
long l;
|
||||
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
|
||||
@@ -693,11 +_,30 @@
|
||||
@@ -686,11 +_,30 @@
|
||||
if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l
|
||||
&& this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) {
|
||||
long l2 = l1 / l;
|
||||
@@ -814,7 +813,7 @@
|
||||
|
||||
boolean flag = l == 0L;
|
||||
if (this.debugCommandProfilerDelayStart) {
|
||||
@@ -705,6 +_,8 @@
|
||||
@@ -698,6 +_,8 @@
|
||||
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
|
||||
}
|
||||
|
||||
@@ -823,7 +822,7 @@
|
||||
this.nextTickTimeNanos += l;
|
||||
|
||||
try (Profiler.Scope scope = Profiler.use(this.createProfiler())) {
|
||||
@@ -755,7 +_,7 @@
|
||||
@@ -748,7 +_,7 @@
|
||||
this.services.profileCache().clearExecutor();
|
||||
}
|
||||
|
||||
@@ -832,7 +831,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -807,7 +_,14 @@
|
||||
@@ -800,7 +_,14 @@
|
||||
}
|
||||
|
||||
private boolean haveTime() {
|
||||
@@ -848,7 +847,7 @@
|
||||
}
|
||||
|
||||
public static boolean throwIfFatalException() {
|
||||
@@ -852,6 +_,12 @@
|
||||
@@ -845,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public TickTask wrapRunnable(Runnable runnable) {
|
||||
@@ -861,7 +860,7 @@
|
||||
return new TickTask(this.tickCount, runnable);
|
||||
}
|
||||
|
||||
@@ -871,15 +_,16 @@
|
||||
@@ -864,15 +_,16 @@
|
||||
if (super.pollTask()) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -880,7 +879,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,26 +_,44 @@
|
||||
@@ -920,26 +_,44 @@
|
||||
}
|
||||
|
||||
public void tickServer(BooleanSupplier hasTimeLeft) {
|
||||
@@ -926,7 +925,7 @@
|
||||
this.tickCount++;
|
||||
this.tickRateManager.tick();
|
||||
this.tickChildren(hasTimeLeft);
|
||||
@@ -956,11 +_,19 @@
|
||||
@@ -949,11 +_,19 @@
|
||||
}
|
||||
|
||||
this.ticksUntilAutosave--;
|
||||
@@ -947,7 +946,7 @@
|
||||
profilerFiller.push("tallying");
|
||||
long l = Util.getNanos() - nanos;
|
||||
int i1 = this.tickCount % 100;
|
||||
@@ -968,12 +_,17 @@
|
||||
@@ -961,12 +_,17 @@
|
||||
this.aggregatedTickTimesNanos += l;
|
||||
this.tickTimesNanos[i1] = l;
|
||||
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
|
||||
@@ -966,7 +965,7 @@
|
||||
LOGGER.debug("Autosave started");
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("save");
|
||||
@@ -1015,7 +_,7 @@
|
||||
@@ -1008,7 +_,7 @@
|
||||
private ServerStatus buildServerStatus() {
|
||||
ServerStatus.Players players = this.buildPlayerStatus();
|
||||
return new ServerStatus(
|
||||
@@ -975,7 +974,7 @@
|
||||
Optional.of(players),
|
||||
Optional.of(ServerStatus.Version.current()),
|
||||
Optional.ofNullable(this.statusIcon),
|
||||
@@ -1029,7 +_,7 @@
|
||||
@@ -1022,7 +_,7 @@
|
||||
if (this.hidesOnlinePlayers()) {
|
||||
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||
} else {
|
||||
@@ -984,7 +983,7 @@
|
||||
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
|
||||
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
|
||||
|
||||
@@ -1046,17 +_,66 @@
|
||||
@@ -1039,17 +_,66 @@
|
||||
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
||||
@@ -1051,7 +1050,7 @@
|
||||
|
||||
profilerFiller.push("tick");
|
||||
|
||||
@@ -1070,7 +_,9 @@
|
||||
@@ -1063,7 +_,9 @@
|
||||
|
||||
profilerFiller.pop();
|
||||
profilerFiller.pop();
|
||||
@@ -1061,7 +1060,7 @@
|
||||
|
||||
profilerFiller.popPush("connection");
|
||||
this.tickConnection();
|
||||
@@ -1148,6 +_,22 @@
|
||||
@@ -1141,6 +_,22 @@
|
||||
return this.levels.get(dimension);
|
||||
}
|
||||
|
||||
@@ -1084,7 +1083,7 @@
|
||||
public Set<ResourceKey<Level>> levelKeys() {
|
||||
return this.levels.keySet();
|
||||
}
|
||||
@@ -1177,7 +_,7 @@
|
||||
@@ -1170,7 +_,7 @@
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
@@ -1093,7 +1092,7 @@
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport systemReport) {
|
||||
@@ -1212,7 +_,7 @@
|
||||
@@ -1205,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void sendSystemMessage(Component component) {
|
||||
@@ -1102,7 +1101,7 @@
|
||||
}
|
||||
|
||||
public KeyPair getKeyPair() {
|
||||
@@ -1250,11 +_,14 @@
|
||||
@@ -1243,11 +_,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1112,9 +1111,9 @@
|
||||
- this.updateMobSpawningFlags();
|
||||
- this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
|
||||
+ // Paper start - per level difficulty
|
||||
+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forceUpdate) {
|
||||
+ net.minecraft.world.level.storage.PrimaryLevelData worldData = (net.minecraft.world.level.storage.PrimaryLevelData) level.serverLevelData;
|
||||
+ if (forceUpdate || !worldData.isDifficultyLocked()) {
|
||||
+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forced) {
|
||||
+ net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData;
|
||||
+ if (forced || !worldData.isDifficultyLocked()) {
|
||||
+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty);
|
||||
+ level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters);
|
||||
+ // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
|
||||
@@ -1122,7 +1121,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1264,7 +_,7 @@
|
||||
@@ -1257,7 +_,7 @@
|
||||
|
||||
private void updateMobSpawningFlags() {
|
||||
for (ServerLevel serverLevel : this.getAllLevels()) {
|
||||
@@ -1131,7 +1130,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1340,10 +_,20 @@
|
||||
@@ -1333,10 +_,20 @@
|
||||
|
||||
@Override
|
||||
public String getMotd() {
|
||||
@@ -1153,7 +1152,7 @@
|
||||
this.motd = motd;
|
||||
}
|
||||
|
||||
@@ -1366,7 +_,7 @@
|
||||
@@ -1359,7 +_,7 @@
|
||||
}
|
||||
|
||||
public ServerConnectionListener getConnection() {
|
||||
@@ -1162,7 +1161,7 @@
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
@@ -1452,7 +_,7 @@
|
||||
@@ -1445,7 +_,7 @@
|
||||
@Override
|
||||
public void executeIfPossible(Runnable task) {
|
||||
if (this.isStopped()) {
|
||||
@@ -1171,7 +1170,7 @@
|
||||
} else {
|
||||
super.executeIfPossible(task);
|
||||
}
|
||||
@@ -1491,7 +_,13 @@
|
||||
@@ -1484,7 +_,14 @@
|
||||
return this.functionManager;
|
||||
}
|
||||
|
||||
@@ -1180,12 +1179,13 @@
|
||||
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds) {
|
||||
+ return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
+ }
|
||||
+
|
||||
+ public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
|
||||
+ // Paper end - Add ServerResourcesReloadedEvent
|
||||
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
|
||||
() -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()),
|
||||
this
|
||||
@@ -1499,7 +_,7 @@
|
||||
@@ -1492,7 +_,7 @@
|
||||
.thenCompose(
|
||||
list -> {
|
||||
CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list);
|
||||
@@ -1194,7 +1194,7 @@
|
||||
return ReloadableServerResources.loadResources(
|
||||
closeableResourceManager,
|
||||
this.registries,
|
||||
@@ -1520,20 +_,39 @@
|
||||
@@ -1513,20 +_,39 @@
|
||||
)
|
||||
.thenAcceptAsync(
|
||||
reloadableResources -> {
|
||||
@@ -1236,7 +1236,7 @@
|
||||
},
|
||||
this
|
||||
);
|
||||
@@ -1550,7 +_,7 @@
|
||||
@@ -1543,7 +_,7 @@
|
||||
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
|
||||
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
|
||||
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
|
||||
@@ -1245,7 +1245,7 @@
|
||||
if (safeMode) {
|
||||
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
|
||||
} else {
|
||||
@@ -1605,7 +_,7 @@
|
||||
@@ -1598,7 +_,7 @@
|
||||
private static WorldDataConfiguration configureRepositoryWithSelection(
|
||||
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
|
||||
) {
|
||||
@@ -1254,7 +1254,7 @@
|
||||
enableForcedFeaturePacks(packRepository, enabledFeatures);
|
||||
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
|
||||
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
|
||||
@@ -1637,7 +_,7 @@
|
||||
@@ -1630,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1263,7 +1263,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1651,11 +_,12 @@
|
||||
@@ -1644,11 +_,12 @@
|
||||
public void kickUnlistedPlayers(CommandSourceStack commandSource) {
|
||||
if (this.isEnforceWhitelist()) {
|
||||
PlayerList playerList = commandSource.getServer().getPlayerList();
|
||||
@@ -1278,7 +1278,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1859,6 +_,22 @@
|
||||
@@ -1852,6 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1289,19 +1289,14 @@
|
||||
+ }
|
||||
+
|
||||
+ public static MinecraftServer getServer() {
|
||||
+ return SERVER; // Paper
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public static RegistryAccess getDefaultRegistryAccess() {
|
||||
+ return org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry();
|
||||
+ return SERVER;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private ProfilerFiller createProfiler() {
|
||||
if (this.willStartRecordingMetrics) {
|
||||
this.metricsRecorder = ActiveMetricsRecorder.createStarted(
|
||||
@@ -1980,16 +_,22 @@
|
||||
@@ -1973,16 +_,22 @@
|
||||
}
|
||||
|
||||
public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) {
|
||||
@@ -1328,7 +1323,7 @@
|
||||
}
|
||||
|
||||
public boolean logIPs() {
|
||||
@@ -2122,4 +_,53 @@
|
||||
@@ -2115,4 +_,53 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
});
|
||||
}
|
||||
@@ -247,7 +_,7 @@
|
||||
public void flushDirty(ServerPlayer serverPlayer) {
|
||||
public void flushDirty(ServerPlayer player, boolean showAdvancements) {
|
||||
if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
|
||||
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();
|
||||
- Set<AdvancementHolder> set = new HashSet<>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/ServerScoreboard.java
|
||||
+++ b/net/minecraft/server/ServerScoreboard.java
|
||||
@@ -39,9 +_,7 @@
|
||||
@@ -43,9 +_,7 @@
|
||||
protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) {
|
||||
super.onScoreChanged(scoreHolder, objective, score);
|
||||
if (this.trackedObjectives.contains(objective)) {
|
||||
@@ -11,7 +11,7 @@
|
||||
new ClientboundSetScorePacket(
|
||||
scoreHolder.getScoreboardName(),
|
||||
objective.getName(),
|
||||
@@ -64,7 +_,7 @@
|
||||
@@ -68,7 +_,7 @@
|
||||
@Override
|
||||
public void onPlayerRemoved(ScoreHolder scoreHolder) {
|
||||
super.onPlayerRemoved(scoreHolder);
|
||||
@@ -20,7 +20,7 @@
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@@ -72,7 +_,7 @@
|
||||
@@ -76,7 +_,7 @@
|
||||
public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) {
|
||||
super.onPlayerScoreRemoved(scoreHolder, objective);
|
||||
if (this.trackedObjectives.contains(objective)) {
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
this.setDirty();
|
||||
@@ -84,7 +_,7 @@
|
||||
@@ -88,7 +_,7 @@
|
||||
super.setDisplayObjective(slot, objective);
|
||||
if (displayObjective != objective && displayObjective != null) {
|
||||
if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) {
|
||||
@@ -38,7 +38,7 @@
|
||||
} else {
|
||||
this.stopTrackingObjective(displayObjective);
|
||||
}
|
||||
@@ -92,7 +_,7 @@
|
||||
@@ -96,7 +_,7 @@
|
||||
|
||||
if (objective != null) {
|
||||
if (this.trackedObjectives.contains(objective)) {
|
||||
@@ -47,7 +47,7 @@
|
||||
} else {
|
||||
this.startTrackingObjective(objective);
|
||||
}
|
||||
@@ -104,24 +_,50 @@
|
||||
@@ -108,24 +_,50 @@
|
||||
@Override
|
||||
public boolean addPlayerToTeam(String playerName, PlayerTeam team) {
|
||||
if (super.addPlayerToTeam(playerName, team)) {
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
@Override
|
||||
public void onObjectiveAdded(Objective objective) {
|
||||
@@ -133,7 +_,7 @@
|
||||
@@ -137,7 +_,7 @@
|
||||
public void onObjectiveChanged(Objective objective) {
|
||||
super.onObjectiveChanged(objective);
|
||||
if (this.trackedObjectives.contains(objective)) {
|
||||
@@ -121,7 +121,7 @@
|
||||
}
|
||||
|
||||
this.setDirty();
|
||||
@@ -152,21 +_,21 @@
|
||||
@@ -156,21 +_,21 @@
|
||||
@Override
|
||||
public void onTeamAdded(PlayerTeam playerTeam) {
|
||||
super.onTeamAdded(playerTeam);
|
||||
@@ -146,7 +146,7 @@
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@@ -209,6 +_,7 @@
|
||||
@@ -213,6 +_,7 @@
|
||||
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
|
||||
|
||||
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
|
||||
@@ -154,7 +154,7 @@
|
||||
for (Packet<?> packet : startTrackingPackets) {
|
||||
serverPlayer.connection.send(packet);
|
||||
}
|
||||
@@ -234,6 +_,7 @@
|
||||
@@ -238,6 +_,7 @@
|
||||
List<Packet<?>> stopTrackingPackets = this.getStopTrackingPackets(objective);
|
||||
|
||||
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
|
||||
@@ -162,9 +162,9 @@
|
||||
for (Packet<?> packet : stopTrackingPackets) {
|
||||
serverPlayer.connection.send(packet);
|
||||
}
|
||||
@@ -267,6 +_,16 @@
|
||||
private ScoreboardSaveData createData(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
return this.createData().load(tag, registries);
|
||||
@@ -269,6 +_,16 @@
|
||||
scoreboardSaveData.loadFrom(data);
|
||||
return scoreboardSaveData;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - Send to players
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
- MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache
|
||||
+ MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations // Paper - add paper configuration files
|
||||
) {
|
||||
- private static final String USERID_CACHE_FILE = "usercache.json";
|
||||
-
|
||||
public static final String USERID_CACHE_FILE = "usercache.json";
|
||||
|
||||
- public static Services create(YggdrasilAuthenticationService authenticationService, File profileRepository) {
|
||||
+ public static final String USERID_CACHE_FILE = "usercache.json"; // Paper - private -> public
|
||||
+
|
||||
+ // Paper start - add paper configuration files
|
||||
+ public Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache) {
|
||||
+ this(sessionService, servicesKeySet, profileRepository, profileCache, null);
|
||||
|
||||
@@ -8,15 +8,6 @@
|
||||
int maxStackSize = itemStack.getMaxStackSize();
|
||||
int i = maxStackSize * 100;
|
||||
if (count > i) {
|
||||
@@ -66,7 +_,7 @@
|
||||
ItemStack itemStack1 = item.createItemStack(min, false);
|
||||
boolean flag = serverPlayer.getInventory().add(itemStack1);
|
||||
if (flag && itemStack1.isEmpty()) {
|
||||
- ItemEntity itemEntity = serverPlayer.drop(itemStack, false);
|
||||
+ ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event
|
||||
if (itemEntity != null) {
|
||||
itemEntity.makeFakeItem();
|
||||
}
|
||||
@@ -95,11 +_,11 @@
|
||||
|
||||
if (targets.size() == 1) {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/server/commands/OpCommand.java
|
||||
+++ b/net/minecraft/server/commands/OpCommand.java
|
||||
@@ -46,7 +_,7 @@
|
||||
if (!playerList.isOp(gameProfile)) {
|
||||
playerList.op(gameProfile);
|
||||
i++;
|
||||
- source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfiles.iterator().next().getName()), true);
|
||||
+ source.sendSuccess(() -> Component.translatable("commands.op.success", gameProfile.getName()), true); // Paper - fixes MC-253721
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/commands/PlaceCommand.java
|
||||
+++ b/net/minecraft/server/commands/PlaceCommand.java
|
||||
@@ -280,6 +_,7 @@
|
||||
@@ -301,6 +_,7 @@
|
||||
if (!structureStart.isValid()) {
|
||||
throw ERROR_STRUCTURE_FAILED.create();
|
||||
} else {
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
+ final Collection<ServerPlayer> actualTargets = new java.util.ArrayList<>(); // Paper - Add PlayerSetSpawnEvent
|
||||
for (ServerPlayer serverPlayer : targets) {
|
||||
- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false);
|
||||
- serverPlayer.setRespawnPosition(new ServerPlayer.RespawnConfig(resourceKey, pos, angle, true), false);
|
||||
- }
|
||||
+ // Paper start - Add PlayerSetSpawnEvent
|
||||
+ if (serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
|
||||
+ if (serverPlayer.setRespawnPosition(new ServerPlayer.RespawnConfig(resourceKey, pos, angle, true), false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
|
||||
+ actualTargets.add(serverPlayer);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerSetSpawnEvent
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@@ -82,6 +_,7 @@
|
||||
ServerLevel level = source.getLevel();
|
||||
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, EntitySpawnReason.COMMAND, entity1 -> {
|
||||
entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
|
||||
entity1.snapTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot());
|
||||
+ entity1.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND; // Paper - Entity#getEntitySpawnReason
|
||||
return entity1;
|
||||
});
|
||||
|
||||
@@ -33,56 +33,24 @@
|
||||
this.serverTextFilter = ServerTextFilter.createFromConfig(settings.getProperties());
|
||||
this.serverLinks = createServerLinks(settings);
|
||||
}
|
||||
@@ -102,26 +_,95 @@
|
||||
@@ -102,6 +_,10 @@
|
||||
Thread thread = new Thread("Server console handler") {
|
||||
@Override
|
||||
public void run() {
|
||||
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
|
||||
-
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.Main.useConsole) return;
|
||||
+ if (!org.bukkit.craftbukkit.Main.useConsole) return; // CraftBukkit
|
||||
+ // Paper start - Use TerminalConsoleAppender
|
||||
+ new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
|
||||
+ /*
|
||||
+ jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader;
|
||||
+ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return
|
||||
+ try {
|
||||
+ System.in.available();
|
||||
+ } catch (IOException ex) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
|
||||
|
||||
String string1;
|
||||
try {
|
||||
- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (string1 = bufferedReader.readLine()) != null) {
|
||||
- DedicatedServer.this.handleConsoleInput(string1, DedicatedServer.this.createCommandSourceStack());
|
||||
+ // CraftBukkit start - JLine disabling compatibility
|
||||
+ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) {
|
||||
+ if (org.bukkit.craftbukkit.Main.useJline) {
|
||||
+ string1 = bufferedreader.readLine(">", null);
|
||||
+ } else {
|
||||
+ string1 = bufferedreader.readLine();
|
||||
+ }
|
||||
+
|
||||
+ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null
|
||||
+ if (string1 == null) {
|
||||
+ try {
|
||||
+ Thread.sleep(50L);
|
||||
+ } catch (InterruptedException ex) {
|
||||
+ Thread.currentThread().interrupt();
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (string1.trim().length() > 0) { // Trim to filter lines which are just spaces
|
||||
+ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -111,17 +_,41 @@
|
||||
}
|
||||
} catch (IOException var4) {
|
||||
DedicatedServer.LOGGER.error("Exception handling console input", (Throwable)var4);
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
- }
|
||||
+ }*/
|
||||
+ // Paper end - Use TerminalConsoleAppender
|
||||
}
|
||||
};
|
||||
+ // CraftBukkit start - TODO: handle command-line logging arguments
|
||||
@@ -93,21 +61,7 @@
|
||||
+ }
|
||||
+ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler());
|
||||
+
|
||||
+ // Paper start - Not needed with TerminalConsoleAppender
|
||||
+ final org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getRootLogger();
|
||||
+ /*
|
||||
+ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger());
|
||||
+ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) {
|
||||
+ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) {
|
||||
+ logger.removeAppender(appender);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ TerminalConsoleWriterThread writerThread = new TerminalConsoleWriterThread(System.out, this.reader);
|
||||
+ this.reader.setCompletionHandler(new TerminalCompletionHandler(writerThread, this.reader.getCompletionHandler()));
|
||||
+ writerThread.start();
|
||||
+ */
|
||||
+ // Paper end - Not needed with TerminalConsoleAppender
|
||||
+
|
||||
+ System.setOut(org.apache.logging.log4j.io.IoBuilder.forLogger(logger).setLevel(org.apache.logging.log4j.Level.INFO).buildPrintStream());
|
||||
+ System.setErr(org.apache.logging.log4j.io.IoBuilder.forLogger(logger).setLevel(org.apache.logging.log4j.Level.WARN).buildPrintStream());
|
||||
@@ -187,7 +141,7 @@
|
||||
InetAddress inetAddress = null;
|
||||
if (!this.getLocalIp().isEmpty()) {
|
||||
inetAddress = InetAddress.getByName(this.getLocalIp());
|
||||
@@ -147,36 +_,62 @@
|
||||
@@ -147,36 +_,61 @@
|
||||
if (this.getPort() < 0) {
|
||||
this.setPort(properties.serverPort);
|
||||
}
|
||||
@@ -210,7 +164,6 @@
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up
|
||||
+ this.server.loadPlugins();
|
||||
+ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP);
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
+ }
|
||||
+
|
||||
+ private String getOverride(String name, String value) {
|
||||
+ if ((this.options != null) && (this.options.has(name))) {
|
||||
+ if (this.options != null && this.options.has(name)) {
|
||||
+ return String.valueOf(this.options.valueOf(name));
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -145,6 +_,33 @@
|
||||
@@ -149,6 +_,33 @@
|
||||
public int serverViewDistance;
|
||||
private final WorldGenContext worldGenContext;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
public ChunkMap(
|
||||
ServerLevel level,
|
||||
LevelStorageSource.LevelStorageAccess levelStorageAccess,
|
||||
@@ -171,13 +_,19 @@
|
||||
@@ -176,13 +_,19 @@
|
||||
this.level = level;
|
||||
RegistryAccess registryAccess = level.registryAccess();
|
||||
long seed = level.getSeed();
|
||||
@@ -56,7 +56,7 @@
|
||||
this.mainThreadExecutor = mainThreadExecutor;
|
||||
ConsecutiveExecutor consecutiveExecutor = new ConsecutiveExecutor(dispatcher, "worldgen");
|
||||
this.progressListener = progressListener;
|
||||
@@ -207,6 +_,12 @@
|
||||
@@ -213,6 +_,12 @@
|
||||
this.chunksToEagerlySave.add(chunkPos.toLong());
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
protected ChunkGenerator generator() {
|
||||
return this.worldGenContext.generator();
|
||||
}
|
||||
@@ -354,9 +_,9 @@
|
||||
@@ -352,9 +_,9 @@
|
||||
}
|
||||
);
|
||||
stringBuilder.append("Updating:").append(System.lineSeparator());
|
||||
@@ -81,17 +81,15 @@
|
||||
CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading");
|
||||
crashReportCategory.setDetail("Details", details);
|
||||
@@ -392,6 +_,9 @@
|
||||
@@ -390,6 +_,7 @@
|
||||
holder.setTicketLevel(newLevel);
|
||||
} else {
|
||||
holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this::onLevelChange, this);
|
||||
+ // Paper start
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder);
|
||||
+ // Paper end
|
||||
+ ca.spottedleaf.moonrise.common.PlatformHooks.get().onChunkHolderCreate(this.level, holder); // Paper
|
||||
}
|
||||
|
||||
this.updatingChunkMap.put(chunkPos, holder);
|
||||
@@ -420,8 +_,8 @@
|
||||
@@ -418,8 +_,8 @@
|
||||
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
if (flush) {
|
||||
@@ -102,7 +100,7 @@
|
||||
.stream()
|
||||
.filter(ChunkHolder::wasAccessibleSinceLastSave)
|
||||
.peek(ChunkHolder::refreshAccessibility)
|
||||
@@ -447,7 +_,7 @@
|
||||
@@ -445,7 +_,7 @@
|
||||
this.nextChunkSaveTime.clear();
|
||||
long millis = Util.getMillis();
|
||||
|
||||
@@ -111,7 +109,7 @@
|
||||
this.saveChunkIfNeeded(chunkHolder, millis);
|
||||
}
|
||||
}
|
||||
@@ -468,6 +_,7 @@
|
||||
@@ -466,6 +_,7 @@
|
||||
public boolean hasWork() {
|
||||
return this.lightEngine.hasLightWork()
|
||||
|| !this.pendingUnloads.isEmpty()
|
||||
@@ -119,7 +117,7 @@
|
||||
|| !this.updatingChunkMap.isEmpty()
|
||||
|| this.poiManager.hasWork()
|
||||
|| !this.toDrop.isEmpty()
|
||||
@@ -526,7 +_,11 @@
|
||||
@@ -524,7 +_,11 @@
|
||||
this.scheduleUnload(chunkPos, chunkHolder);
|
||||
} else {
|
||||
ChunkAccess latestChunk = chunkHolder.getLatestChunk();
|
||||
@@ -132,7 +130,7 @@
|
||||
if (latestChunk instanceof LevelChunk levelChunk) {
|
||||
levelChunk.setLoaded(false);
|
||||
}
|
||||
@@ -540,7 +_,9 @@
|
||||
@@ -538,7 +_,9 @@
|
||||
this.lightEngine.tryScheduleUpdate();
|
||||
this.progressListener.onStatusChange(latestChunk.getPos(), null);
|
||||
this.nextChunkSaveTime.remove(latestChunk.getPos().toLong());
|
||||
@@ -143,7 +141,7 @@
|
||||
}
|
||||
}, this.unloadQueue::add).whenComplete((_void, error) -> {
|
||||
if (error != null) {
|
||||
@@ -856,7 +_,7 @@
|
||||
@@ -854,7 +_,7 @@
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@@ -152,7 +150,7 @@
|
||||
}
|
||||
|
||||
public net.minecraft.server.level.DistanceManager getDistanceManager() {
|
||||
@@ -864,7 +_,7 @@
|
||||
@@ -862,7 +_,7 @@
|
||||
}
|
||||
|
||||
protected Iterable<ChunkHolder> getChunks() {
|
||||
@@ -161,9 +159,9 @@
|
||||
}
|
||||
|
||||
void dumpChunks(Writer writer) throws IOException {
|
||||
@@ -888,10 +_,10 @@
|
||||
@@ -885,10 +_,10 @@
|
||||
.addColumn("fluid_ticks")
|
||||
.build(writer);
|
||||
TickingTracker tickingTracker = this.distanceManager.tickingTracker();
|
||||
|
||||
- for (Entry<ChunkHolder> entry : this.visibleChunkMap.long2ObjectEntrySet()) {
|
||||
- long longKey = entry.getLongKey();
|
||||
@@ -175,7 +173,7 @@
|
||||
Optional<ChunkAccess> optional = Optional.ofNullable(chunkHolder.getLatestChunk());
|
||||
Optional<LevelChunk> optional1 = optional.flatMap(chunk -> chunk instanceof LevelChunk ? Optional.of((LevelChunk)chunk) : Optional.empty());
|
||||
csvOutput.writeRow(
|
||||
@@ -931,11 +_,13 @@
|
||||
@@ -928,11 +_,13 @@
|
||||
}
|
||||
|
||||
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
|
||||
@@ -191,18 +189,28 @@
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> action) {
|
||||
@@ -951,12 +_,34 @@
|
||||
void collectSpawningChunks(List<LevelChunk> output) {
|
||||
@@ -942,7 +_,7 @@
|
||||
ChunkHolder chunkHolder = this.visibleChunkMap.get(spawnCandidateChunks.nextLong());
|
||||
if (chunkHolder != null) {
|
||||
LevelChunk tickingChunk = chunkHolder.getTickingChunk();
|
||||
- if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos())) {
|
||||
+ if (tickingChunk != null && this.anyPlayerCloseEnoughForSpawningInternal(chunkHolder.getPos(), true)) { // Spigot
|
||||
output.add(tickingChunk);
|
||||
}
|
||||
}
|
||||
@@ -962,13 +_,35 @@
|
||||
}
|
||||
|
||||
public boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) {
|
||||
- return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos);
|
||||
+ // Spigot start
|
||||
+ return this.anyPlayerCloseEnoughForSpawning(chunkPos, false);
|
||||
+ }
|
||||
+
|
||||
+ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos, boolean reducedRange) {
|
||||
+ return this.distanceManager.hasPlayersNearby(chunkPos.toLong()) && this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange);
|
||||
TriState triState = this.distanceManager.hasPlayersNearby(chunkPos.toLong());
|
||||
- return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos) : triState.toBoolean(true);
|
||||
+ return triState == TriState.DEFAULT ? this.anyPlayerCloseEnoughForSpawningInternal(chunkPos, reducedRange) : triState.toBoolean(true);
|
||||
+ // Spigot end
|
||||
}
|
||||
|
||||
@@ -224,12 +232,12 @@
|
||||
+ if (event == null || event.isCancelled()) continue;
|
||||
+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
|
||||
+ }
|
||||
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
+ if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos, blockRange)) {
|
||||
+ // Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -972,7 +_,7 @@
|
||||
@@ -984,7 +_,7 @@
|
||||
Builder<ServerPlayer> builder = ImmutableList.builder();
|
||||
|
||||
for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) {
|
||||
@@ -238,7 +246,7 @@
|
||||
builder.add(serverPlayer);
|
||||
}
|
||||
}
|
||||
@@ -981,12 +_,12 @@
|
||||
@@ -993,12 +_,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,13 +255,13 @@
|
||||
if (player.isSpectator()) {
|
||||
return false;
|
||||
} else {
|
||||
double d = euclideanDistanceSquared(chunkPos, player);
|
||||
double d = euclideanDistanceSquared(chunkPos, player.position());
|
||||
- return d < 16384.0;
|
||||
+ return d < range; // Spigot
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,9 +_,19 @@
|
||||
@@ -1120,9 +_,19 @@
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
@@ -273,7 +281,7 @@
|
||||
if (i != 0) {
|
||||
int updateInterval = type.updateInterval();
|
||||
if (this.entityMap.containsKey(entity.getId())) {
|
||||
@@ -1126,6 +_,7 @@
|
||||
@@ -1146,6 +_,7 @@
|
||||
}
|
||||
|
||||
protected void removeEntity(Entity entity) {
|
||||
@@ -281,16 +289,7 @@
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
this.updatePlayerStatus(serverPlayer, false);
|
||||
|
||||
@@ -1230,7 +_,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
- class DistanceManager extends net.minecraft.server.level.DistanceManager {
|
||||
+ public class DistanceManager extends net.minecraft.server.level.DistanceManager { // Paper - public
|
||||
protected DistanceManager(final Executor dispatcher, final Executor mainThreadExecutor) {
|
||||
super(dispatcher, mainThreadExecutor);
|
||||
}
|
||||
@@ -1258,10 +_,10 @@
|
||||
@@ -1278,10 +_,10 @@
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
@@ -298,12 +297,12 @@
|
||||
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
|
||||
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast);
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this.seenBy); // CraftBukkit
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers);
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers, this.seenBy); // Paper
|
||||
this.entity = entity;
|
||||
this.range = range;
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
@@ -1297,24 +_,47 @@
|
||||
@@ -1325,24 +_,47 @@
|
||||
}
|
||||
|
||||
public void removePlayer(ServerPlayer player) {
|
||||
@@ -356,7 +355,7 @@
|
||||
}
|
||||
} else if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
@@ -1331,6 +_,7 @@
|
||||
@@ -1359,6 +_,7 @@
|
||||
|
||||
for (Entity entity : this.entity.getIndirectPassengers()) {
|
||||
int i1 = entity.getType().clientTrackingRange() * 16;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -107,6 +_,12 @@
|
||||
@@ -72,6 +_,12 @@
|
||||
}
|
||||
|
||||
if (!this.chunksToUpdateFutures.isEmpty()) {
|
||||
@@ -13,51 +13,7 @@
|
||||
for (ChunkHolder chunkHolder : this.chunksToUpdateFutures) {
|
||||
chunkHolder.updateHighestAllowedStatus(chunkMap);
|
||||
}
|
||||
@@ -177,16 +_,42 @@
|
||||
public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
|
||||
long packedChunkPos = pos.toLong();
|
||||
- this.addTicket(packedChunkPos, ticket);
|
||||
+ this.addTicket(packedChunkPos, ticket); // Paper - diff on change above
|
||||
this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
|
||||
}
|
||||
|
||||
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
Ticket<T> ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value);
|
||||
long packedChunkPos = pos.toLong();
|
||||
+ this.removeTicket(packedChunkPos, ticket); // Paper - diff on change above
|
||||
+ this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
|
||||
+ }
|
||||
+
|
||||
+ // Paper start
|
||||
+ public boolean addPluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
|
||||
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
|
||||
+ final long packedChunkPos = pos.toLong();
|
||||
+ final Set<Ticket<?>> tickets = this.getTickets(packedChunkPos);
|
||||
+ if (tickets.contains(ticket)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ this.addTicket(packedChunkPos, ticket);
|
||||
+ this.tickingTicketsTracker.addTicket(packedChunkPos, ticket);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public boolean removePluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
|
||||
+ Ticket<org.bukkit.plugin.Plugin> ticket = new Ticket<>(TicketType.PLUGIN_TICKET, ChunkLevel.byStatus(FullChunkStatus.FULL) - 2, value); // Copied from below and keep in-line with force loading, add at level 31
|
||||
+ final long packedChunkPos = pos.toLong();
|
||||
+ final Set<Ticket<?>> tickets = this.tickets.get(packedChunkPos); // Don't use getTickets, we don't want to create a new set
|
||||
+ if (tickets == null || !tickets.contains(ticket)) {
|
||||
+ return false;
|
||||
+ }
|
||||
this.removeTicket(packedChunkPos, ticket);
|
||||
this.tickingTicketsTracker.removeTicket(packedChunkPos, ticket);
|
||||
+ return true;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
private SortedArraySet<Ticket<?>> getTickets(long chunkPos) {
|
||||
return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4));
|
||||
@@ -217,8 +_,10 @@
|
||||
@@ -121,8 +_,10 @@
|
||||
ChunkPos chunkPos = sectionPos.chunk();
|
||||
long packedChunkPos = chunkPos.toLong();
|
||||
ObjectSet<ServerPlayer> set = this.playersPerChunk.get(packedChunkPos);
|
||||
@@ -70,39 +26,3 @@
|
||||
this.playersPerChunk.remove(packedChunkPos);
|
||||
this.naturalSpawnChunkCounter.update(packedChunkPos, Integer.MAX_VALUE, false);
|
||||
this.playerTicketManager.update(packedChunkPos, Integer.MAX_VALUE, false);
|
||||
@@ -299,7 +_,7 @@
|
||||
}
|
||||
|
||||
public void removeTicketsOnClosing() {
|
||||
- ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN);
|
||||
+ ImmutableSet<TicketType<?>> set = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
|
||||
ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectIterator = this.tickets.long2ObjectEntrySet().fastIterator();
|
||||
|
||||
while (objectIterator.hasNext()) {
|
||||
@@ -329,6 +_,26 @@
|
||||
public boolean hasTickets() {
|
||||
return !this.tickets.isEmpty();
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
|
||||
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
|
||||
+
|
||||
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
|
||||
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
|
||||
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
|
||||
+ if (tickets.remove(target)) {
|
||||
+ // copied from removeTicket
|
||||
+ this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt(tickets), false);
|
||||
+
|
||||
+ // can't use entry after it's removed
|
||||
+ if (tickets.isEmpty()) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
class ChunkTicketTracker extends ChunkTracker {
|
||||
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -73,6 +_,13 @@
|
||||
@@ -77,6 +_,13 @@
|
||||
@Nullable
|
||||
@VisibleForDebug
|
||||
private NaturalSpawner.SpawnState lastSpawnState;
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
public ServerChunkCache(
|
||||
ServerLevel level,
|
||||
@@ -121,6 +_,64 @@
|
||||
@@ -127,6 +_,64 @@
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@
|
||||
+ return holder.getLatestChunk();
|
||||
+ }
|
||||
+
|
||||
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
|
||||
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
|
||||
+ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
|
||||
+ this.ticketStorage.addTicket(new Ticket(ticketType, ticketLevel), chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
|
||||
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
|
||||
+ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel) {
|
||||
+ this.ticketStorage.removeTicket(new Ticket(ticketType, ticketLevel), chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ // "real" get chunk if loaded
|
||||
@@ -79,7 +79,7 @@
|
||||
@Override
|
||||
public ThreadedLevelLightEngine getLightEngine() {
|
||||
return this.lightEngine;
|
||||
@@ -160,7 +_,7 @@
|
||||
@@ -166,7 +_,7 @@
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (packedChunkPos == this.lastChunkPos[i] && chunkStatus == this.lastChunkStatus[i]) {
|
||||
ChunkAccess chunkAccess = this.lastChunk[i];
|
||||
@@ -88,7 +88,7 @@
|
||||
return chunkAccess;
|
||||
}
|
||||
}
|
||||
@@ -169,6 +_,7 @@
|
||||
@@ -175,6 +_,7 @@
|
||||
profilerFiller.incrementCounter("getChunkCacheMiss");
|
||||
CompletableFuture<ChunkResult<ChunkAccess>> chunkFutureMainThread = this.getChunkFutureMainThread(x, z, chunkStatus, requireChunk);
|
||||
this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone);
|
||||
@@ -96,7 +96,7 @@
|
||||
ChunkResult<ChunkAccess> chunkResult = chunkFutureMainThread.join();
|
||||
ChunkAccess chunkAccess1 = chunkResult.orElse(null);
|
||||
if (chunkAccess1 == null && requireChunk) {
|
||||
@@ -240,7 +_,15 @@
|
||||
@@ -246,7 +_,15 @@
|
||||
long packedChunkPos = chunkPos.toLong();
|
||||
int i = ChunkLevel.byStatus(chunkStatus);
|
||||
ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(packedChunkPos);
|
||||
@@ -109,11 +109,11 @@
|
||||
+ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
|
||||
+ }
|
||||
+ if (requireChunk && !currentlyUnloading) {
|
||||
+ // CraftBukkit end
|
||||
this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos);
|
||||
+ // CraftBukkit end
|
||||
this.addTicket(new Ticket(TicketType.UNKNOWN, i), chunkPos);
|
||||
if (this.chunkAbsent(visibleChunkIfPresent, i)) {
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
@@ -260,7 +_,7 @@
|
||||
@@ -266,7 +_,7 @@
|
||||
}
|
||||
|
||||
private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) {
|
||||
@@ -122,16 +122,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -287,7 +_,7 @@
|
||||
return this.mainThreadProcessor.pollTask();
|
||||
}
|
||||
|
||||
- boolean runDistanceManagerUpdates() {
|
||||
+ public boolean runDistanceManagerUpdates() { // Paper - public
|
||||
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
|
||||
boolean flag1 = this.chunkMap.promoteChunkMap();
|
||||
this.chunkMap.runGenerationTasks();
|
||||
@@ -315,17 +_,39 @@
|
||||
@@ -321,17 +_,39 @@
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
@@ -155,7 +146,7 @@
|
||||
+ ProfilerFiller gameprofilerfiller = Profiler.get();
|
||||
+
|
||||
+ gameprofilerfiller.push("purge");
|
||||
+ this.distanceManager.purgeStaleTickets();
|
||||
+ this.ticketStorage.purgeStaleTickets();
|
||||
+ this.runDistanceManagerUpdates();
|
||||
+ gameprofilerfiller.popPush("unload");
|
||||
+ this.chunkMap.tick(() -> true);
|
||||
@@ -170,10 +161,10 @@
|
||||
profilerFiller.push("purge");
|
||||
- if (this.level.tickRateManager().runsNormally() || !tickChunks) {
|
||||
+ if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
|
||||
this.distanceManager.purgeStaleTickets();
|
||||
this.ticketStorage.purgeStaleTickets();
|
||||
}
|
||||
|
||||
@@ -400,12 +_,20 @@
|
||||
@@ -388,12 +_,20 @@
|
||||
);
|
||||
this.lastSpawnState = spawnState;
|
||||
profiler.popPush("spawnAndTick");
|
||||
@@ -197,16 +188,7 @@
|
||||
} else {
|
||||
filteredSpawningCategories = List.of();
|
||||
}
|
||||
@@ -413,7 +_,7 @@
|
||||
for (LevelChunk levelChunk : chunks) {
|
||||
ChunkPos pos = levelChunk.getPos();
|
||||
levelChunk.incrementInhabitedTime(timeInhabited);
|
||||
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos)) {
|
||||
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
|
||||
NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
|
||||
}
|
||||
|
||||
@@ -526,8 +_,13 @@
|
||||
@@ -544,8 +_,13 @@
|
||||
|
||||
@Override
|
||||
public void setSpawnSettings(boolean spawnSettings) {
|
||||
@@ -221,7 +203,7 @@
|
||||
}
|
||||
|
||||
public String getChunkDebugData(ChunkPos chunkPos) {
|
||||
@@ -603,12 +_,18 @@
|
||||
@@ -618,12 +_,18 @@
|
||||
|
||||
@Override
|
||||
public boolean pollTask() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -65,13 +_,17 @@
|
||||
@@ -69,11 +_,12 @@
|
||||
private Vec3 lastSentMovement;
|
||||
private int tickCount;
|
||||
private int teleportDelay;
|
||||
@@ -10,26 +10,25 @@
|
||||
private boolean wasOnGround;
|
||||
@Nullable
|
||||
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
|
||||
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers; // Paper
|
||||
|
||||
- public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast) {
|
||||
+ // CraftBukkit start
|
||||
+ private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers;
|
||||
+ public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer<Packet<?>> broadcast, final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers) {
|
||||
+ this.trackedPlayers = trackedPlayers;
|
||||
+ // CraftBukkit end
|
||||
public ServerEntity(
|
||||
ServerLevel level,
|
||||
@@ -81,8 +_,12 @@
|
||||
int updateInterval,
|
||||
boolean trackDelta,
|
||||
Consumer<Packet<?>> broadcast,
|
||||
- BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore
|
||||
+ // Paper start
|
||||
+ BiConsumer<Packet<?>, List<UUID>> broadcastWithIgnore,
|
||||
+ final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers
|
||||
+ // Paper end
|
||||
) {
|
||||
+ this.trackedPlayers = trackedPlayers; // Paper
|
||||
this.level = level;
|
||||
this.broadcast = broadcast;
|
||||
this.entity = entity;
|
||||
@@ -89,7 +_,7 @@
|
||||
public void sendChanges() {
|
||||
List<Entity> passengers = this.entity.getPassengers();
|
||||
if (!passengers.equals(this.lastPassengers)) {
|
||||
- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
|
||||
+ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
|
||||
removedPassengers(passengers, this.lastPassengers)
|
||||
.forEach(
|
||||
removedPassenger -> {
|
||||
@@ -102,13 +_,14 @@
|
||||
@@ -106,13 +_,14 @@
|
||||
this.lastPassengers = passengers;
|
||||
}
|
||||
|
||||
@@ -48,7 +47,7 @@
|
||||
savedData.tickCarriedBy(serverPlayer, item);
|
||||
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
||||
if (updatePacket != null) {
|
||||
@@ -141,7 +_,13 @@
|
||||
@@ -145,7 +_,13 @@
|
||||
} else {
|
||||
this.teleportDelay++;
|
||||
Vec3 vec3 = this.entity.trackingPosition();
|
||||
@@ -63,7 +62,7 @@
|
||||
Packet<?> packet = null;
|
||||
boolean flag2 = flag1 || this.tickCount % 60 == 0;
|
||||
boolean flag3 = false;
|
||||
@@ -219,6 +_,25 @@
|
||||
@@ -223,6 +_,25 @@
|
||||
|
||||
this.tickCount++;
|
||||
if (this.entity.hurtMarked) {
|
||||
@@ -89,7 +88,7 @@
|
||||
this.entity.hurtMarked = false;
|
||||
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
||||
}
|
||||
@@ -273,7 +_,10 @@
|
||||
@@ -280,7 +_,10 @@
|
||||
|
||||
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> consumer) {
|
||||
if (this.entity.isRemoved()) {
|
||||
@@ -101,7 +100,7 @@
|
||||
}
|
||||
|
||||
Packet<ClientGamePacketListener> addEntityPacket = this.entity.getAddEntityPacket(this);
|
||||
@@ -285,6 +_,12 @@
|
||||
@@ -292,6 +_,12 @@
|
||||
boolean flag = this.trackDelta;
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Collection<AttributeInstance> syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes();
|
||||
@@ -114,18 +113,18 @@
|
||||
if (!syncableAttributes.isEmpty()) {
|
||||
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes));
|
||||
}
|
||||
@@ -309,8 +_,9 @@
|
||||
@@ -316,8 +_,9 @@
|
||||
}
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
- consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
|
||||
+ consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization
|
||||
}
|
||||
+ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
+ ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
}
|
||||
|
||||
if (!this.entity.getPassengers().isEmpty()) {
|
||||
@@ -357,6 +_,11 @@
|
||||
@@ -364,6 +_,11 @@
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
|
||||
if (!attributesToSync.isEmpty()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -182,7 +_,7 @@
|
||||
@@ -178,7 +_,7 @@
|
||||
final List<ServerPlayer> players = Lists.newArrayList();
|
||||
public final ServerChunkCache chunkSource;
|
||||
private final MinecraftServer server;
|
||||
@@ -9,17 +9,18 @@
|
||||
private int lastSpawnChunkRadius;
|
||||
final EntityTickList entityTickList = new EntityTickList();
|
||||
public final PersistentEntitySectionManager<Entity> entityManager;
|
||||
@@ -209,11 +_,132 @@
|
||||
@@ -205,11 +_,131 @@
|
||||
private final boolean tickTime;
|
||||
private final RandomSequences randomSequences;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
|
||||
+ public final UUID uuid;
|
||||
+ public final java.util.UUID uuid;
|
||||
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
||||
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
+
|
||||
+ public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ @Override
|
||||
+ public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
+ }
|
||||
+
|
||||
@@ -91,14 +92,12 @@
|
||||
+ int requiredChunks = (maxChunkX - minChunkX + 1) * (maxChunkZ - minChunkZ + 1);
|
||||
+ int[] loadedChunks = new int[1];
|
||||
+
|
||||
+ Long holderIdentifier = Long.valueOf(chunkProvider.chunkFutureAwaitCounter++);
|
||||
+
|
||||
+ java.util.function.Consumer<net.minecraft.world.level.chunk.ChunkAccess> consumer = (net.minecraft.world.level.chunk.ChunkAccess chunk) -> {
|
||||
+ if (chunk != null) {
|
||||
+ int ticketLevel = Math.max(33, chunkProvider.chunkMap.getUpdatingChunkIfPresent(chunk.getPos().toLong()).getTicketLevel());
|
||||
+ ret.add(chunk);
|
||||
+ ticketLevels.add(ticketLevel);
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel, holderIdentifier);
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel);
|
||||
+ }
|
||||
+ if (++loadedChunks[0] == requiredChunks) {
|
||||
+ try {
|
||||
@@ -108,8 +107,8 @@
|
||||
+ ChunkPos chunkPos = ret.get(i).getPos();
|
||||
+ int ticketLevel = ticketLevels.getInt(i);
|
||||
+
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos);
|
||||
+ chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, holderIdentifier);
|
||||
+ chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel);
|
||||
+ chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -128,7 +127,7 @@
|
||||
+ // Paper start - optimise getPlayerByUUID
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Player getPlayerByUUID(UUID uuid) {
|
||||
+ public Player getPlayerByUUID(java.util.UUID uuid) {
|
||||
+ final Player player = this.getServer().getPlayerList().getPlayer(uuid);
|
||||
+ return player != null && player.level() == this ? player : null;
|
||||
+ }
|
||||
@@ -143,7 +142,7 @@
|
||||
ResourceKey<Level> dimension,
|
||||
LevelStem levelStem,
|
||||
ChunkProgressListener progressListener,
|
||||
@@ -221,14 +_,38 @@
|
||||
@@ -217,14 +_,38 @@
|
||||
long biomeZoomSeed,
|
||||
List<CustomSpawner> customSpawners,
|
||||
boolean tickTime,
|
||||
@@ -158,7 +157,7 @@
|
||||
+ super(serverLevelData, dimension, server.registryAccess(), levelStem.type(), false, isDebug, biomeZoomSeed, server.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> server.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(levelStorageAccess.levelDirectory.path(), serverLevelData.getLevelName(), dimension.location(), spigotConfig, server.registryAccess(), serverLevelData.getGameRules()))); // Paper - create paper world configs
|
||||
+ this.pvpMode = server.isPvpAllowed();
|
||||
+ this.levelStorageAccess = levelStorageAccess;
|
||||
+ this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getUUID(levelStorageAccess.levelDirectory.path().toFile());
|
||||
+ this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getOrCreate(levelStorageAccess.levelDirectory.path().toFile());
|
||||
+ // CraftBukkit end
|
||||
this.tickTime = tickTime;
|
||||
this.server = server;
|
||||
@@ -184,7 +183,7 @@
|
||||
boolean flag = server.forceSynchronousWrites();
|
||||
DataFixer fixerUpper = server.getFixerUpper();
|
||||
EntityPersistentStorage<Entity> entityPersistentStorage = new EntityStorage(
|
||||
@@ -250,8 +_,8 @@
|
||||
@@ -246,8 +_,8 @@
|
||||
server.getStructureManager(),
|
||||
dispatcher,
|
||||
chunkGenerator,
|
||||
@@ -195,7 +194,7 @@
|
||||
flag,
|
||||
progressListener,
|
||||
this.entityManager::updateChunkStatus,
|
||||
@@ -272,7 +_,7 @@
|
||||
@@ -268,7 +_,7 @@
|
||||
this.chunkSource.chunkScanner(),
|
||||
this.registryAccess(),
|
||||
server.getStructureManager(),
|
||||
@@ -204,7 +203,7 @@
|
||||
chunkGenerator,
|
||||
this.chunkSource.randomState(),
|
||||
this,
|
||||
@@ -280,9 +_,9 @@
|
||||
@@ -276,9 +_,9 @@
|
||||
seed,
|
||||
fixerUpper
|
||||
);
|
||||
@@ -217,10 +216,10 @@
|
||||
} else {
|
||||
this.dragonFight = null;
|
||||
}
|
||||
@@ -292,7 +_,15 @@
|
||||
this.randomSequences = Objects.requireNonNullElseGet(
|
||||
randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(seed), "random_sequences")
|
||||
);
|
||||
@@ -286,7 +_,15 @@
|
||||
this.sleepStatus = new SleepStatus();
|
||||
this.gameEventDispatcher = new GameEventDispatcher(this);
|
||||
this.randomSequences = Objects.requireNonNullElseGet(randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.TYPE));
|
||||
- }
|
||||
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
+ }
|
||||
@@ -234,7 +233,7 @@
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
@@ -304,8 +_,8 @@
|
||||
@@ -298,8 +_,8 @@
|
||||
this.serverLevelData.setClearWeatherTime(clearTime);
|
||||
this.serverLevelData.setRainTime(weatherTime);
|
||||
this.serverLevelData.setThunderTime(weatherTime);
|
||||
@@ -245,7 +244,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -332,12 +_,25 @@
|
||||
@@ -326,12 +_,25 @@
|
||||
|
||||
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) {
|
||||
@@ -274,7 +273,7 @@
|
||||
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
|
||||
this.resetWeatherCycle();
|
||||
}
|
||||
@@ -352,9 +_,9 @@
|
||||
@@ -346,9 +_,9 @@
|
||||
if (!this.isDebug() && runsNormally) {
|
||||
long l = this.getGameTime();
|
||||
profilerFiller.push("blockTicks");
|
||||
@@ -286,16 +285,30 @@
|
||||
profilerFiller.pop();
|
||||
}
|
||||
|
||||
@@ -372,7 +_,7 @@
|
||||
@@ -366,7 +_,7 @@
|
||||
|
||||
this.handlingTick = false;
|
||||
profilerFiller.pop();
|
||||
- boolean flag = !this.players.isEmpty() || !this.getForcedChunks().isEmpty();
|
||||
+ boolean flag = !paperConfig().unsupportedSettings.disableWorldTickingWhenEmpty || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players // Paper - restore this
|
||||
- boolean flag = !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty();
|
||||
+ boolean flag = !paperConfig().unsupportedSettings.disableWorldTickingWhenEmpty || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players // Paper - restore this
|
||||
if (flag) {
|
||||
this.resetEmptyTime();
|
||||
}
|
||||
@@ -461,12 +_,12 @@
|
||||
@@ -455,11 +_,13 @@
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("iceandsnow");
|
||||
|
||||
+ if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
|
||||
for (int i = 0; i < randomTickSpeed; i++) {
|
||||
if (this.random.nextInt(48) == 0) {
|
||||
this.tickPrecipitation(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15));
|
||||
}
|
||||
}
|
||||
+ } // Paper - Option to disable ice and snow
|
||||
|
||||
profilerFiller.popPush("tickBlocks");
|
||||
if (randomTickSpeed > 0) {
|
||||
@@ -502,12 +_,12 @@
|
||||
int minBlockZ = pos.getMinBlockZ();
|
||||
ProfilerFiller profilerFiller = Profiler.get();
|
||||
profilerFiller.push("thunder");
|
||||
@@ -310,7 +323,7 @@
|
||||
&& !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD);
|
||||
if (flag) {
|
||||
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
|
||||
@@ -474,7 +_,7 @@
|
||||
@@ -515,7 +_,7 @@
|
||||
skeletonHorse.setTrap(true);
|
||||
skeletonHorse.setAge(0);
|
||||
skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
@@ -319,63 +332,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,18 +_,20 @@
|
||||
@@ -523,7 +_,7 @@
|
||||
if (lightningBolt != null) {
|
||||
lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos));
|
||||
lightningBolt.snapTo(Vec3.atBottomCenterOf(blockPos));
|
||||
lightningBolt.setVisualOnly(flag);
|
||||
- this.addFreshEntity(lightningBolt);
|
||||
+ this.strikeLightning(lightningBolt, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profilerFiller.popPush("iceandsnow");
|
||||
|
||||
+ if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
|
||||
for (int i = 0; i < randomTickSpeed; i++) {
|
||||
if (this.random.nextInt(48) == 0) {
|
||||
this.tickPrecipitation(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15));
|
||||
}
|
||||
}
|
||||
+ } // Paper - Option to disable ice and snow
|
||||
|
||||
profilerFiller.popPush("tickBlocks");
|
||||
if (randomTickSpeed > 0) {
|
||||
@@ -535,7 +_,7 @@
|
||||
@@ -537,7 +_,7 @@
|
||||
BlockPos blockPos1 = heightmapPos.below();
|
||||
Biome biome = this.getBiome(heightmapPos).value();
|
||||
if (biome.shouldFreeze(this, blockPos1)) {
|
||||
- this.setBlockAndUpdate(blockPos1, Blocks.ICE.defaultBlockState());
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockPos1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockPos1, Blocks.ICE.defaultBlockState(), 3, null); // CraftBukkit
|
||||
}
|
||||
|
||||
if (this.isRaining()) {
|
||||
@@ -547,10 +_,10 @@
|
||||
@@ -549,10 +_,10 @@
|
||||
if (layersValue < Math.min(_int, 8)) {
|
||||
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, Integer.valueOf(layersValue + 1));
|
||||
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, layersValue + 1);
|
||||
Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos);
|
||||
- this.setBlockAndUpdate(heightmapPos, blockState1);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, 3, null); // CraftBukkit
|
||||
}
|
||||
} else {
|
||||
- this.setBlockAndUpdate(heightmapPos, Blocks.SNOW.defaultBlockState());
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), 3, null); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,6 +_,11 @@
|
||||
@@ -577,6 +_,12 @@
|
||||
}
|
||||
|
||||
protected BlockPos findLightningTargetAround(BlockPos pos) {
|
||||
+ // Paper start - Add methods to find targets for lightning strikes
|
||||
+ return this.findLightningTargetAround(pos, false);
|
||||
+ }
|
||||
+
|
||||
+ public BlockPos findLightningTargetAround(BlockPos pos, boolean returnNullWhenNoTarget) {
|
||||
+ // Paper end - Add methods to find targets for lightning strikes
|
||||
BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
|
||||
Optional<BlockPos> optional = this.findLightningRod(heightmapPos);
|
||||
if (optional.isPresent()) {
|
||||
@@ -582,11 +_,12 @@
|
||||
@@ -584,11 +_,12 @@
|
||||
} else {
|
||||
AABB aabb = AABB.encapsulatingFullBlocks(heightmapPos, heightmapPos.atY(this.getMaxY() + 1)).inflate(3.0);
|
||||
List<LivingEntity> entitiesOfClass = this.getEntitiesOfClass(
|
||||
@@ -389,7 +390,7 @@
|
||||
if (heightmapPos.getY() == this.getMinY() - 1) {
|
||||
heightmapPos = heightmapPos.above(2);
|
||||
}
|
||||
@@ -673,8 +_,8 @@
|
||||
@@ -675,8 +_,8 @@
|
||||
this.serverLevelData.setThunderTime(thunderTime);
|
||||
this.serverLevelData.setRainTime(rainTime);
|
||||
this.serverLevelData.setClearWeatherTime(clearWeatherTime);
|
||||
@@ -400,7 +401,7 @@
|
||||
}
|
||||
|
||||
this.oThunderLevel = this.thunderLevel;
|
||||
@@ -695,6 +_,7 @@
|
||||
@@ -697,6 +_,7 @@
|
||||
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
@@ -408,7 +409,7 @@
|
||||
if (this.oRainLevel != this.rainLevel) {
|
||||
this.server
|
||||
.getPlayerList()
|
||||
@@ -717,14 +_,47 @@
|
||||
@@ -719,14 +_,47 @@
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel));
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
|
||||
}
|
||||
@@ -460,7 +461,7 @@
|
||||
}
|
||||
|
||||
public void resetEmptyTime() {
|
||||
@@ -746,18 +_,46 @@
|
||||
@@ -748,18 +_,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +508,7 @@
|
||||
}
|
||||
|
||||
private void tickPassenger(Entity ridingEntity, Entity passengerEntity) {
|
||||
@@ -766,10 +_,12 @@
|
||||
@@ -768,10 +_,12 @@
|
||||
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
|
||||
passengerEntity.setOldPosAndRot();
|
||||
passengerEntity.tickCount++;
|
||||
@@ -520,7 +521,7 @@
|
||||
profilerFiller.pop();
|
||||
|
||||
for (Entity entity : passengerEntity.getPassengers()) {
|
||||
@@ -786,6 +_,7 @@
|
||||
@@ -788,6 +_,7 @@
|
||||
public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
|
||||
ServerChunkCache chunkSource = this.getChunkSource();
|
||||
if (!skipSave) {
|
||||
@@ -528,15 +529,15 @@
|
||||
if (progress != null) {
|
||||
progress.progressStartNoAbort(Component.translatable("menu.savingLevel"));
|
||||
}
|
||||
@@ -802,11 +_,19 @@
|
||||
@@ -804,11 +_,19 @@
|
||||
this.entityManager.autoSave();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
|
||||
+ ServerLevel worldserver1 = this;
|
||||
+ // CraftBukkit start - moved from MinecraftServer#saveAllChunks
|
||||
+ ServerLevel serverLevel1 = this;
|
||||
+
|
||||
+ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings());
|
||||
+ this.serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings());
|
||||
+ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess()));
|
||||
+ this.levelStorageAccess.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
|
||||
+ // CraftBukkit end
|
||||
@@ -549,7 +550,7 @@
|
||||
}
|
||||
|
||||
DimensionDataStorage dataStorage = this.getChunkSource().getDataStorage();
|
||||
@@ -871,18 +_,40 @@
|
||||
@@ -873,18 +_,40 @@
|
||||
|
||||
@Override
|
||||
public boolean addFreshEntity(Entity entity) {
|
||||
@@ -559,7 +560,7 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public boolean addFreshEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
@@ -570,7 +571,7 @@
|
||||
+ return this.addWithUUID(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ public boolean addWithUUID(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public boolean addWithUUID(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
@@ -583,7 +584,7 @@
|
||||
+ this.addDuringTeleport(entity, null);
|
||||
+ }
|
||||
+
|
||||
+ public void addDuringTeleport(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public void addDuringTeleport(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ // CraftBukkit end
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
this.addPlayer(serverPlayer);
|
||||
@@ -593,13 +594,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,40 +_,119 @@
|
||||
@@ -907,40 +_,119 @@
|
||||
this.entityManager.addNewEntity(player);
|
||||
}
|
||||
|
||||
- private boolean addEntity(Entity entity) {
|
||||
+ // CraftBukkit start
|
||||
+ private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ private boolean addEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
+ entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process
|
||||
+ // Paper start - extra debug info
|
||||
@@ -718,16 +719,16 @@
|
||||
if (d * d + d1 * d1 + d2 * d2 < 1024.0) {
|
||||
serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress));
|
||||
}
|
||||
@@ -1000,7 +_,7 @@
|
||||
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {
|
||||
this.server
|
||||
.getPlayerList()
|
||||
- .broadcast(player, pos.getX(), pos.getY(), pos.getZ(), 64.0, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false));
|
||||
+ .broadcast(player, pos.getX(), pos.getY(), pos.getZ(), 64.0, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false)); // Paper - diff on change (the 64.0 distance is used as defaults for sound ranges in spigot config for ender dragon, end portal and wither)
|
||||
}
|
||||
|
||||
public int getLogicalHeight() {
|
||||
@@ -1009,6 +_,11 @@
|
||||
@@ -1015,7 +_,7 @@
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ(),
|
||||
- 64.0,
|
||||
+ 64.0, // Paper - diff on change (the 64.0 distance is used as defaults for sound ranges in spigot config for ender dragon, end portal and wither)
|
||||
this.dimension(),
|
||||
new ClientboundLevelEventPacket(type, pos, data, false)
|
||||
);
|
||||
@@ -1027,6 +_,11 @@
|
||||
|
||||
@Override
|
||||
public void gameEvent(Holder<GameEvent> gameEvent, Vec3 pos, GameEvent.Context context) {
|
||||
@@ -739,7 +740,7 @@
|
||||
this.gameEventDispatcher.post(gameEvent, pos, context);
|
||||
}
|
||||
|
||||
@@ -1021,17 +_,28 @@
|
||||
@@ -1039,17 +_,28 @@
|
||||
|
||||
this.getChunkSource().blockChanged(pos);
|
||||
this.pathTypesByPosCache.invalidate(pos);
|
||||
@@ -768,7 +769,7 @@
|
||||
|
||||
try {
|
||||
this.isUpdatingNavigations = true;
|
||||
@@ -1043,15 +_,18 @@
|
||||
@@ -1061,15 +_,23 @@
|
||||
this.isUpdatingNavigations = false;
|
||||
}
|
||||
}
|
||||
@@ -777,6 +778,11 @@
|
||||
|
||||
@Override
|
||||
public void updateNeighborsAt(BlockPos pos, Block block) {
|
||||
+ // CraftBukkit start
|
||||
+ if (this.populating) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement
|
||||
this.updateNeighborsAt(pos, block, ExperimentalRedstoneUtils.initialOrientation(this, null, null));
|
||||
}
|
||||
@@ -787,7 +793,7 @@
|
||||
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null, orientation);
|
||||
}
|
||||
|
||||
@@ -1100,6 +_,42 @@
|
||||
@@ -1118,6 +_,42 @@
|
||||
ParticleOptions largeExplosionParticles,
|
||||
Holder<SoundEvent> explosionSound
|
||||
) {
|
||||
@@ -830,7 +836,7 @@
|
||||
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
|
||||
case NONE -> Explosion.BlockInteraction.KEEP;
|
||||
case BLOCK -> this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
|
||||
@@ -1108,10 +_,17 @@
|
||||
@@ -1126,10 +_,17 @@
|
||||
: Explosion.BlockInteraction.KEEP;
|
||||
case TNT -> this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
|
||||
case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK;
|
||||
@@ -848,7 +854,7 @@
|
||||
ParticleOptions particleOptions = serverExplosion.isSmall() ? smallExplosionParticles : largeExplosionParticles;
|
||||
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
@@ -1120,6 +_,8 @@
|
||||
@@ -1138,6 +_,8 @@
|
||||
serverPlayer.connection.send(new ClientboundExplodePacket(vec3, optional, particleOptions, explosionSound));
|
||||
}
|
||||
}
|
||||
@@ -857,7 +863,7 @@
|
||||
}
|
||||
|
||||
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayGameRule) {
|
||||
@@ -1190,7 +_,7 @@
|
||||
@@ -1208,7 +_,7 @@
|
||||
public <T extends ParticleOptions> int sendParticles(
|
||||
T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed
|
||||
) {
|
||||
@@ -866,7 +872,7 @@
|
||||
}
|
||||
|
||||
public <T extends ParticleOptions> int sendParticles(
|
||||
@@ -1206,13 +_,49 @@
|
||||
@@ -1224,13 +_,49 @@
|
||||
double zOffset,
|
||||
double speed
|
||||
) {
|
||||
@@ -874,7 +880,7 @@
|
||||
+ return this.sendParticlesSource(null, type, overrideLimiter, alwaysShow, posX, posY, posZ, particleCount, xOffset, yOffset, zOffset, speed);
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ @Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -891,7 +897,7 @@
|
||||
+ }
|
||||
+ public <T extends ParticleOptions> int sendParticlesSource(
|
||||
+ List<ServerPlayer> receivers,
|
||||
+ @javax.annotation.Nullable Entity sender,
|
||||
+ @Nullable Entity sender,
|
||||
+ T type,
|
||||
+ boolean overrideLimiter,
|
||||
+ boolean alwaysShow,
|
||||
@@ -918,7 +924,7 @@
|
||||
if (this.sendParticles(serverPlayer, overrideLimiter, posX, posY, posZ, clientboundLevelParticlesPacket)) {
|
||||
i++;
|
||||
}
|
||||
@@ -1280,7 +_,7 @@
|
||||
@@ -1293,7 +_,7 @@
|
||||
|
||||
@Nullable
|
||||
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipExistingChunks) {
|
||||
@@ -927,17 +933,17 @@
|
||||
return null;
|
||||
} else {
|
||||
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
|
||||
@@ -1327,11 +_,38 @@
|
||||
@@ -1340,10 +_,36 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public MapItemSavedData getMapData(MapId mapId) {
|
||||
- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapId.key());
|
||||
- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.type(mapId));
|
||||
+ // Paper start - Call missing map initialize event and set id
|
||||
+ final DimensionDataStorage storage = this.getServer().overworld().getDataStorage();
|
||||
+
|
||||
+ final Optional<net.minecraft.world.level.saveddata.SavedData> cacheEntry = storage.cache.get(mapId.key());
|
||||
+ if (cacheEntry == null) { // Cache did not contain, try to load and may init
|
||||
+ final MapItemSavedData mapData = storage.get(MapItemSavedData.factory(), mapId.key()); // get populates the cache
|
||||
+ final MapItemSavedData mapData = storage.get(MapItemSavedData.type(mapId)); // get populates the cache
|
||||
+ if (mapData != null) { // map was read, init it and return
|
||||
+ mapData.id = mapId;
|
||||
+ new org.bukkit.event.server.MapInitializeEvent(mapData.mapView).callEvent();
|
||||
@@ -946,7 +952,6 @@
|
||||
+
|
||||
+ return null; // Map does not exist, reading failed.
|
||||
+ }
|
||||
+
|
||||
+ // Cache entry exists, update it with the id ref and return.
|
||||
+ if (cacheEntry.orElse(null) instanceof final MapItemSavedData mapItemSavedData) {
|
||||
+ mapItemSavedData.id = mapId;
|
||||
@@ -957,17 +962,16 @@
|
||||
+ // Paper end - Call missing map initialize event and set id
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMapData(MapId mapId, MapItemSavedData mapData) {
|
||||
public void setMapData(MapId mapId, MapItemSavedData data) {
|
||||
+ // CraftBukkit start
|
||||
+ mapData.id = mapId;
|
||||
+ org.bukkit.event.server.MapInitializeEvent event = new org.bukkit.event.server.MapInitializeEvent(mapData.mapView);
|
||||
+ data.id = mapId;
|
||||
+ org.bukkit.event.server.MapInitializeEvent event = new org.bukkit.event.server.MapInitializeEvent(data.mapView);
|
||||
+ event.callEvent();
|
||||
+ // CraftBukkit end
|
||||
this.getServer().overworld().getDataStorage().set(mapId.key(), mapData);
|
||||
this.getServer().overworld().getDataStorage().set(MapItemSavedData.type(mapId), data);
|
||||
}
|
||||
|
||||
@@ -1344,17 +_,27 @@
|
||||
@@ -1355,17 +_,27 @@
|
||||
BlockPos spawnPos = this.levelData.getSpawnPos();
|
||||
float spawnAngle = this.levelData.getSpawnAngle();
|
||||
if (!spawnPos.equals(pos) || spawnAngle != angle) {
|
||||
@@ -978,50 +982,38 @@
|
||||
}
|
||||
|
||||
if (this.lastSpawnChunkRadius > 1) {
|
||||
- this.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(spawnPos), this.lastSpawnChunkRadius, Unit.INSTANCE);
|
||||
- this.getChunkSource().removeTicketWithRadius(TicketType.START, new ChunkPos(spawnPos), this.lastSpawnChunkRadius);
|
||||
+ // Paper start - allow disabling gamerule limits
|
||||
+ for (ChunkPos chunkPos : io.papermc.paper.util.MCUtil.getSpiralOutChunks(spawnPos, this.lastSpawnChunkRadius - 2)) {
|
||||
+ this.getChunkSource().removeTicketAtLevel(TicketType.START, chunkPos, net.minecraft.server.level.ChunkLevel.ENTITY_TICKING_LEVEL, Unit.INSTANCE);
|
||||
+ this.getChunkSource().removeTicketAtLevel(TicketType.START, chunkPos, ChunkLevel.ENTITY_TICKING_LEVEL);
|
||||
+ }
|
||||
+ // Paper end - allow disabling gamerule limits
|
||||
}
|
||||
|
||||
int i = this.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS) + 1;
|
||||
if (i > 1) {
|
||||
- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), i, Unit.INSTANCE);
|
||||
- this.getChunkSource().addTicketWithRadius(TicketType.START, new ChunkPos(pos), i);
|
||||
+ // Paper start - allow disabling gamerule limits
|
||||
+ for (ChunkPos chunkPos : io.papermc.paper.util.MCUtil.getSpiralOutChunks(pos, i - 2)) {
|
||||
+ this.getChunkSource().addTicketAtLevel(TicketType.START, chunkPos, net.minecraft.server.level.ChunkLevel.ENTITY_TICKING_LEVEL, Unit.INSTANCE);
|
||||
+ this.getChunkSource().addTicketAtLevel(TicketType.START, chunkPos, ChunkLevel.ENTITY_TICKING_LEVEL);
|
||||
+ }
|
||||
+ // Paper end - allow disabling gamerule limits
|
||||
}
|
||||
|
||||
this.lastSpawnChunkRadius = i;
|
||||
@@ -1403,6 +_,11 @@
|
||||
@@ -1400,6 +_,11 @@
|
||||
DebugPackets.sendPoiRemovedPacket(this, blockPos);
|
||||
}));
|
||||
optional1.ifPresent(poiType -> this.getServer().execute(() -> {
|
||||
optional1.ifPresent(holder -> this.getServer().execute(() -> {
|
||||
+ // Paper start - Remove stale POIs
|
||||
+ if (optional.isEmpty() && this.getPoiManager().exists(blockPos, ignored -> true)) {
|
||||
+ this.getPoiManager().remove(blockPos);
|
||||
+ }
|
||||
+ // Paper end - Remove stale POIs
|
||||
this.getPoiManager().add(blockPos, (Holder<PoiType>)poiType);
|
||||
this.getPoiManager().add(blockPos, (Holder<PoiType>)holder);
|
||||
DebugPackets.sendPoiAddedPacket(this, blockPos);
|
||||
}));
|
||||
@@ -1543,6 +_,11 @@
|
||||
@Override
|
||||
public void blockUpdated(BlockPos pos, Block block) {
|
||||
if (!this.isDebug()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (this.populating) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.updateNeighborsAt(pos, block);
|
||||
}
|
||||
}
|
||||
@@ -1562,12 +_,12 @@
|
||||
@@ -1552,12 +_,12 @@
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
@@ -1036,7 +1028,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1618,6 +_,7 @@
|
||||
@@ -1608,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
@@ -1044,7 +1036,7 @@
|
||||
return this.entityManager.getEntityGetter();
|
||||
}
|
||||
|
||||
@@ -1699,6 +_,27 @@
|
||||
@@ -1697,6 +_,28 @@
|
||||
return this.serverLevelData.getGameRules();
|
||||
}
|
||||
|
||||
@@ -1059,12 +1051,13 @@
|
||||
+ }
|
||||
+ // Paper end - respect global sound events gamerule
|
||||
+ // Paper start - notify observers even if grow failed
|
||||
+ @Deprecated
|
||||
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final org.bukkit.craftbukkit.block.CraftBlockState craftBlockState) {
|
||||
+ // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
|
||||
+ // blocks at the same Y level with the same state can be assumed to be saplings which trigger observers regardless of if the
|
||||
+ // tree grew or not
|
||||
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) {
|
||||
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
|
||||
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlags(), 512);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - notify observers even if grow failed
|
||||
@@ -1072,7 +1065,7 @@
|
||||
@Override
|
||||
public CrashReportCategory fillReportDetails(CrashReport report) {
|
||||
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
|
||||
@@ -1714,6 +_,7 @@
|
||||
@@ -1712,6 +_,7 @@
|
||||
final class EntityCallbacks implements LevelCallback<Entity> {
|
||||
@Override
|
||||
public void onCreated(Entity entity) {
|
||||
@@ -1080,7 +1073,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1723,24 +_,32 @@
|
||||
@@ -1721,24 +_,32 @@
|
||||
|
||||
@Override
|
||||
public void onTickingStart(Entity entity) {
|
||||
@@ -1115,7 +1108,7 @@
|
||||
String string = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1757,10 +_,52 @@
|
||||
@@ -1755,10 +_,52 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
@@ -1123,12 +1116,12 @@
|
||||
+ entity.valid = true; // CraftBukkit
|
||||
+ ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server
|
||||
+ // Paper start - Entity origin API
|
||||
+ if (entity.getOriginVector() == null) {
|
||||
+ entity.setOrigin(entity.getBukkitEntity().getLocation());
|
||||
+ if (entity.origin == null) {
|
||||
+ entity.origin = entity.position();
|
||||
+ }
|
||||
+ // Default to current world if unknown, gross assumption but entities rarely change world
|
||||
+ if (entity.getOriginWorld() == null) {
|
||||
+ entity.setOrigin(entity.getOriginVector().toLocation(getWorld()));
|
||||
+ if (entity.originWorld == null) {
|
||||
+ entity.originWorld = ServerLevel.this.getWorld().getUID();
|
||||
+ }
|
||||
+ // Paper end - Entity origin API
|
||||
+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity(), ServerLevel.this.getWorld()).callEvent(); // Paper - fire while valid
|
||||
@@ -1168,7 +1161,7 @@
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
ServerLevel.this.players.remove(serverPlayer);
|
||||
@@ -1768,7 +_,7 @@
|
||||
@@ -1766,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (entity instanceof Mob mob) {
|
||||
@@ -1177,7 +1170,7 @@
|
||||
String string = "onTrackingStart called during navigation iteration";
|
||||
Util.logAndPauseIfInIde(
|
||||
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
|
||||
@@ -1785,6 +_,15 @@
|
||||
@@ -1783,6 +_,15 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
|
||||
@@ -1193,7 +1186,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1792,4 +_,24 @@
|
||||
@@ -1790,4 +_,24 @@
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1194,7 @@
|
||||
+ // Paper start - check global player list where appropriate
|
||||
+ @Override
|
||||
+ @Nullable
|
||||
+ public Player getGlobalPlayerByUUID(UUID uuid) {
|
||||
+ public Player getGlobalPlayerByUUID(java.util.UUID uuid) {
|
||||
+ return this.server.getPlayerList().getPlayer(uuid);
|
||||
+ }
|
||||
+ // Paper end - check global player list where appropriate
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -41,28 +_,49 @@
|
||||
@@ -41,28 +_,50 @@
|
||||
private BlockPos delayedDestroyPos = BlockPos.ZERO;
|
||||
private int delayedTickStart;
|
||||
private int lastSentState = -1;
|
||||
@@ -18,6 +18,7 @@
|
||||
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = this.changeGameModeForPlayer(gameModeForPlayer, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null);
|
||||
+ return event != null && event.isCancelled();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public org.bukkit.event.player.PlayerGameModeChangeEvent changeGameModeForPlayer(GameType gameModeForPlayer, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause playerGameModeChangeCause, @Nullable net.kyori.adventure.text.Component cancelMessage) {
|
||||
+ // Paper end - Expand PlayerGameModeChangeEvent
|
||||
@@ -92,34 +93,30 @@
|
||||
this.debugLogging(pos, false, sequence, "too far");
|
||||
} else if (pos.getY() > maxBuildHeight) {
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
@@ -138,16 +_,39 @@
|
||||
@@ -138,16 +_,35 @@
|
||||
} else {
|
||||
if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) {
|
||||
if (!this.level.mayInteract(this.player, pos)) {
|
||||
+ // CraftBukkit start - fire PlayerInteractEvent
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelectedItem(), InteractionHand.MAIN_HAND);
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
this.debugLogging(pos, false, sequence, "may not interact");
|
||||
- return;
|
||||
- }
|
||||
+ // Update any tile entity data for this block
|
||||
+ this.capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
|
||||
+ // CraftBukkit end
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
|
||||
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(this.player, org.bukkit.event.block.Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelectedItem(), InteractionHand.MAIN_HAND);
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Let the client know the block still exists
|
||||
+ // this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // Paper - Don't resync blocks
|
||||
+ // Update any tile entity data for this block
|
||||
+ this.capturedBlockEntity = true; // Paper - Send block entities after destroy prediction
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (this.isCreative()) {
|
||||
if (this.player.getAbilities().instabuild) {
|
||||
this.destroyAndAck(pos, sequence, "creative destroy");
|
||||
return;
|
||||
}
|
||||
@@ -153,7 +150,7 @@
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDamageEvent blockEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageEvent(this.player, pos, face, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
|
||||
+ org.bukkit.event.block.BlockDamageEvent blockEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageEvent(this.player, pos, face, this.player.getInventory().getSelectedItem(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
|
||||
+
|
||||
+ if (blockEvent.isCancelled()) {
|
||||
+ return;
|
||||
@@ -188,7 +185,7 @@
|
||||
this.level.destroyBlockProgress(this.player.getId(), pos, -1);
|
||||
this.debugLogging(pos, true, sequence, "aborted destroying");
|
||||
+
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelectedItem()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,13 +193,13 @@
|
||||
|
||||
public boolean destroyBlock(BlockPos pos) {
|
||||
BlockState blockState = this.level.getBlockState(pos);
|
||||
- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) {
|
||||
- if (!this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player)) {
|
||||
+ // CraftBukkit start - fire BlockBreakEvent
|
||||
+ org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, pos);
|
||||
+ org.bukkit.event.block.BlockBreakEvent event = null;
|
||||
+ if (this.player instanceof ServerPlayer) {
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
+ boolean canAttackBlock = !this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player);
|
||||
+ boolean canAttackBlock = !this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player);
|
||||
+ event = new org.bukkit.event.block.BlockBreakEvent(bblock, this.player.getBukkitEntity());
|
||||
+
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
@@ -238,7 +235,7 @@
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
+ if (false && !this.player.getMainHandItem().canDestroyBlock(blockState, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
return false;
|
||||
} else {
|
||||
+ blockState = this.level.getBlockState(pos); // CraftBukkit - update state from plugins
|
||||
@@ -264,7 +261,7 @@
|
||||
|
||||
+ ItemStack mainHandStack = null; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
+ boolean isCorrectTool = false; // Paper - Trigger bee_nest_destroyed trigger in the correct place
|
||||
if (this.isCreative()) {
|
||||
if (this.player.preventsBlockDrops()) {
|
||||
- return true;
|
||||
+ // return true; // CraftBukkit
|
||||
} else {
|
||||
@@ -368,7 +365,7 @@
|
||||
+ if (!stack.isEmpty() && !this.interactResult) { // add !interactResult SPIGOT-764
|
||||
UseOnContext useOnContext = new UseOnContext(player, hand, hitResult);
|
||||
InteractionResult interactionResult1;
|
||||
if (this.isCreative()) {
|
||||
if (player.hasInfiniteMaterials()) {
|
||||
@@ -357,6 +_,11 @@
|
||||
|
||||
return interactionResult1;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
--- a/net/minecraft/server/level/Ticket.java
|
||||
+++ b/net/minecraft/server/level/Ticket.java
|
||||
@@ -14,17 +_,36 @@
|
||||
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("level").forGetter(Ticket::getTicketLevel),
|
||||
Codec.LONG.optionalFieldOf("ticks_left", 0L).forGetter(ticket -> ticket.ticksLeft)
|
||||
)
|
||||
- .apply(instance, Ticket::new)
|
||||
+ .apply(instance, (type, level, ticks) -> new Ticket(type, level.intValue(), ticks.longValue())) // Paper - add identifier
|
||||
);
|
||||
private final TicketType type;
|
||||
private final int ticketLevel;
|
||||
private long ticksLeft;
|
||||
+ // Paper start - add identifier
|
||||
+ private Object identifier;
|
||||
+
|
||||
+ public Object getIdentifier() {
|
||||
+ return this.identifier;
|
||||
+ }
|
||||
+ // Paper end - add identifier
|
||||
+
|
||||
|
||||
public Ticket(TicketType type, int ticketLevel) {
|
||||
- this(type, ticketLevel, type.timeout());
|
||||
+ // Paper start - add identifier
|
||||
+ this(type, ticketLevel, null);
|
||||
+ }
|
||||
+ public Ticket(TicketType type, int ticketLevel, Object identifier) {
|
||||
+ this(type, ticketLevel, type.timeout(), identifier);
|
||||
+ // Paper end - add identifier
|
||||
}
|
||||
|
||||
private Ticket(TicketType type, int ticketLevel, long ticksLeft) {
|
||||
+ // Paper start - add identifier
|
||||
+ this(type, ticketLevel, ticksLeft, null);
|
||||
+ }
|
||||
+ private Ticket(TicketType type, int ticketLevel, long ticksLeft, Object identifier) {
|
||||
+ this.identifier = identifier;
|
||||
+ // Paper end - add identifier
|
||||
this.type = type;
|
||||
this.ticketLevel = ticketLevel;
|
||||
this.ticksLeft = ticksLeft;
|
||||
@@ -1,20 +1,36 @@
|
||||
--- a/net/minecraft/server/level/TicketType.java
|
||||
+++ b/net/minecraft/server/level/TicketType.java
|
||||
@@ -7,6 +_,7 @@
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -13,11 +_,24 @@
|
||||
public static final TicketType PORTAL = register("portal", 300L, true, TicketType.TicketUse.LOADING_AND_SIMULATION);
|
||||
public static final TicketType ENDER_PEARL = register("ender_pearl", 40L, false, TicketType.TicketUse.LOADING_AND_SIMULATION);
|
||||
public static final TicketType UNKNOWN = register("unknown", 1L, false, TicketType.TicketUse.LOADING);
|
||||
+ public static final TicketType PLUGIN = register("plugin", 0L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // CraftBukkit
|
||||
+ public static final TicketType POST_TELEPORT = register("post_teleport", 5L, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType PLUGIN_TICKET = register("plugin_ticket", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType FUTURE_AWAIT = register("future_await", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING_AND_SIMULATION); // Paper
|
||||
+ public static final TicketType CHUNK_LOAD = register("chunk_load", TicketType.NO_TIMEOUT, false, TicketType.TicketUse.LOADING); // Paper - moonrise
|
||||
|
||||
public class TicketType<T> {
|
||||
+ public static final TicketType<Long> FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper
|
||||
private final String name;
|
||||
private final Comparator<T> comparator;
|
||||
public long timeout;
|
||||
@@ -17,6 +_,9 @@
|
||||
public static final TicketType<BlockPos> PORTAL = create("portal", Vec3i::compareTo, 300);
|
||||
public static final TicketType<ChunkPos> ENDER_PEARL = create("ender_pearl", Comparator.comparingLong(ChunkPos::toLong), 40);
|
||||
public static final TicketType<ChunkPos> UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
|
||||
+ public static final TicketType<Unit> PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit
|
||||
+ public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit
|
||||
+ public static final TicketType<Integer> POST_TELEPORT = TicketType.create("post_teleport", Integer::compare, 5); // Paper - post teleport ticket type
|
||||
public static TicketType register(String name, long timeout, boolean persist, TicketType.TicketUse use) {
|
||||
return Registry.register(BuiltInRegistries.TICKET_TYPE, name, new TicketType(timeout, persist, use));
|
||||
}
|
||||
|
||||
public static <T> TicketType<T> create(String name, Comparator<T> comparator) {
|
||||
return new TicketType<>(name, comparator, 0L);
|
||||
+ // Paper start - chunk-gc config
|
||||
+ public static int PLUGIN_TYPE_TIMEOUT = 600;
|
||||
+ @Override
|
||||
+ public long timeout() {
|
||||
+ return this == PLUGIN ? PLUGIN_TYPE_TIMEOUT : this.timeout;
|
||||
+ }
|
||||
+ // Paper end - chunk-gc config
|
||||
+
|
||||
public boolean doesLoad() {
|
||||
return this.use == TicketType.TicketUse.LOADING || this.use == TicketType.TicketUse.LOADING_AND_SIMULATION;
|
||||
}
|
||||
@@ -27,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean hasTimeout() {
|
||||
- return this.timeout != 0L;
|
||||
+ return this.timeout() != 0L; // Paper - chunk-gc config
|
||||
}
|
||||
|
||||
public static enum TicketUse {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -151,6 +_,26 @@
|
||||
@@ -151,6 +_,28 @@
|
||||
return chessboardDistance < this.generatingStep.directDependencies().size();
|
||||
}
|
||||
|
||||
@@ -11,16 +11,18 @@
|
||||
+ return this.getChunk(x, z, ChunkStatus.FULL, false);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getBlockState(blockposition);
|
||||
+ public final BlockState getBlockStateIfLoaded(BlockPos pos) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getBlockState(pos);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getFluidState(blockposition);
|
||||
+ public final FluidState getFluidIfLoaded(BlockPos pos) {
|
||||
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
+ return chunk == null ? null : chunk.getFluidState(pos);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@@ -71,10 +73,10 @@
|
||||
return false;
|
||||
} else {
|
||||
ChunkAccess chunk = this.getChunk(pos);
|
||||
- BlockState blockState = chunk.setBlockState(pos, state, false);
|
||||
+ BlockState blockState = chunk.setBlockState(pos, state, false); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
|
||||
- BlockState blockState = chunk.setBlockState(pos, state, flags);
|
||||
+ BlockState blockState = chunk.setBlockState(pos, state, flags); final BlockState previousBlockState = blockState; // Paper - Clear block entity before setting up a DUMMY block entity - obfhelper
|
||||
if (blockState != null) {
|
||||
this.level.onBlockStateChange(pos, blockState, state);
|
||||
this.level.updatePOIOnBlockStateChange(pos, blockState, state);
|
||||
}
|
||||
@@ -294,6 +_,17 @@
|
||||
chunk.removeBlockEntity(pos);
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ private static String readLegacyString(ByteBuf buf) {
|
||||
+ private static @javax.annotation.Nullable String readLegacyString(ByteBuf buf) {
|
||||
+ int size = buf.readShort() * Character.BYTES;
|
||||
+ if (!buf.isReadable(size)) {
|
||||
+ return null;
|
||||
@@ -111,7 +111,7 @@
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ private String readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) {
|
||||
+ private @javax.annotation.Nullable String readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) {
|
||||
+ ByteBuf buf = this.buf;
|
||||
+
|
||||
+ if (buf == null) {
|
||||
@@ -168,7 +168,7 @@
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(),
|
||||
+ String response = String.format("§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(),
|
||||
+ com.destroystokyo.paper.network.PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers());
|
||||
+ return response;
|
||||
+ }
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.craftbukkit.entity.CraftPlayer getCraftPlayer() {
|
||||
+ return this.player == null ? null : this.player.getBukkitEntity();
|
||||
+ return this.player.getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
@@ -81,7 +81,7 @@
|
||||
+ this.onDisconnect(details, null);
|
||||
+ }
|
||||
+
|
||||
+ public void onDisconnect(DisconnectionDetails info, @Nullable net.kyori.adventure.text.Component quitMessage) {
|
||||
+ public void onDisconnect(DisconnectionDetails details, @Nullable net.kyori.adventure.text.Component quitMessage) {
|
||||
+ // Paper end - Fix kick event leave message not being sent
|
||||
if (this.isSingleplayerOwner()) {
|
||||
LOGGER.info("Stopping singleplayer server as player logged out");
|
||||
@@ -99,7 +99,7 @@
|
||||
public void handlePong(ServerboundPongPacket packet) {
|
||||
}
|
||||
|
||||
+ private static final net.minecraft.resources.ResourceLocation CUSTOM_REGISTER = net.minecraft.resources.ResourceLocation.withDefaultNamespace("register"); // CraftBukkit
|
||||
+ public static final net.minecraft.resources.ResourceLocation CUSTOM_REGISTER = net.minecraft.resources.ResourceLocation.withDefaultNamespace("register"); // CraftBukkit
|
||||
+ private static final net.minecraft.resources.ResourceLocation CUSTOM_UNREGISTER = net.minecraft.resources.ResourceLocation.withDefaultNamespace("unregister"); // CraftBukkit
|
||||
+
|
||||
@Override
|
||||
@@ -272,7 +272,7 @@
|
||||
+ this.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN);
|
||||
+ }
|
||||
+
|
||||
+ public void disconnect(final Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
|
||||
+ public void disconnect(Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) {
|
||||
+ this.disconnect(new DisconnectionDetails(reason), cause);
|
||||
+ // Paper end - kick event causes
|
||||
+ }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,7 @@
|
||||
--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -12,11 +_,27 @@
|
||||
import net.minecraft.network.protocol.status.StatusProtocols;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -14,9 +_,20 @@
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.net.InetAddress;
|
||||
+import java.util.HashMap;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener {
|
||||
private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request");
|
||||
+ // Spigot start
|
||||
@@ -17,7 +10,7 @@
|
||||
+ static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}");
|
||||
+ // Spigot end
|
||||
+ // CraftBukkit start - add fields
|
||||
+ private static final HashMap<InetAddress, Long> throttleTracker = new HashMap<>();
|
||||
+ private static final java.util.HashMap<java.net.InetAddress, Long> throttleTracker = new java.util.HashMap<>();
|
||||
+ private static int throttleCounter = 0;
|
||||
+ // CraftBukkit end
|
||||
+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper
|
||||
@@ -54,7 +47,7 @@
|
||||
+ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket
|
||||
+ long currentTime = System.currentTimeMillis();
|
||||
+ long connectionThrottle = this.server.server.getConnectionThrottle();
|
||||
+ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress();
|
||||
+ java.net.InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress();
|
||||
+
|
||||
+ synchronized (ServerHandshakePacketListenerImpl.throttleTracker) {
|
||||
+ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
|
||||
@@ -102,7 +95,7 @@
|
||||
+ // Try and handle the handshake through the event
|
||||
+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me?
|
||||
+ java.net.SocketAddress socketAddress = this.connection.address;
|
||||
+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress();
|
||||
+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : java.net.InetAddress.getLoopbackAddress().getHostAddress();
|
||||
+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packet.hostName(), hostnameOfRemote, !proxyLogicEnabled);
|
||||
+ if (event.callEvent()) {
|
||||
+ // If we've failed somehow, let the client know so and go no further.
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -43,10 +_,19 @@
|
||||
import net.minecraft.util.StringUtil;
|
||||
@@ -44,9 +_,17 @@
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener {
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.network.protocol.Packet;
|
||||
+import net.minecraft.network.protocol.PacketUtils;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.craftbukkit.util.Waitable;
|
||||
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
+import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||
|
||||
-public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener {
|
||||
+
|
||||
+public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener, CraftPlayer.TransferCookieConnection {
|
||||
+ // CraftBukkit end
|
||||
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
||||
@@ -47,7 +45,7 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendPacket(Packet<?> packet) {
|
||||
+ public void sendPacket(net.minecraft.network.protocol.Packet<?> packet) {
|
||||
+ this.connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
@@ -342,7 +340,7 @@
|
||||
|
||||
@Override
|
||||
public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket packet) {
|
||||
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.server); // CraftBukkit
|
||||
+ net.minecraft.network.protocol.PacketUtils.ensureRunningOnSameThread(packet, this, this.server); // CraftBukkit
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet");
|
||||
this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND);
|
||||
CommonListenerCookie commonListenerCookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile), this.transferred);
|
||||
@@ -359,7 +357,7 @@
|
||||
@Override
|
||||
public void handleCookieResponse(ServerboundCookieResponsePacket packet) {
|
||||
+ // CraftBukkit start
|
||||
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.server);
|
||||
+ net.minecraft.network.protocol.PacketUtils.ensureRunningOnSameThread(packet, this, this.server);
|
||||
+ if (this.player != null && this.player.getBukkitEntity().handleCookieResponse(packet)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -56,6 +_,10 @@
|
||||
@@ -54,6 +_,10 @@
|
||||
private final AtomicLong operationCount = new AtomicLong();
|
||||
@Nullable
|
||||
private Executor executor;
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
public GameProfileCache(GameProfileRepository profileRepository, File file) {
|
||||
this.profileRepository = profileRepository;
|
||||
@@ -64,10 +_,12 @@
|
||||
@@ -62,17 +_,21 @@
|
||||
}
|
||||
|
||||
private void safeAdd(GameProfileCache.GameProfileInfo profile) {
|
||||
@@ -24,16 +24,17 @@
|
||||
}
|
||||
|
||||
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository profileRepo, String name) {
|
||||
@@ -86,6 +_,8 @@
|
||||
atomicReference.set(null);
|
||||
}
|
||||
};
|
||||
+ if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
|
||||
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - Add setting for proxy online mode status
|
||||
profileRepo.findProfilesByNames(new String[]{name}, profileLookupCallback);
|
||||
GameProfile gameProfile = atomicReference.get();
|
||||
return gameProfile != null ? Optional.of(gameProfile) : createUnknownProfile(name);
|
||||
@@ -101,7 +_,7 @@
|
||||
if (!StringUtil.isValidPlayerName(name)) {
|
||||
return createUnknownProfile(name);
|
||||
} else {
|
||||
- Optional<GameProfile> optional = profileRepo.findProfileByName(name);
|
||||
+ final boolean shouldLookup = !org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
|
||||
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper - Add setting for proxy online mode status
|
||||
+ Optional<GameProfile> optional = shouldLookup ? profileRepo.findProfileByName(name) : Optional.empty(); // Paper - Don't lookup a profile with a blank name
|
||||
return optional.isEmpty() ? createUnknownProfile(name) : optional;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static boolean usesAuthentication() {
|
||||
@@ -42,7 +43,7 @@
|
||||
}
|
||||
|
||||
public void add(GameProfile gameProfile) {
|
||||
@@ -111,15 +_,29 @@
|
||||
@@ -96,15 +_,29 @@
|
||||
Date time = instance.getTime();
|
||||
GameProfileCache.GameProfileInfo gameProfileInfo = new GameProfileCache.GameProfileInfo(gameProfile, time);
|
||||
this.safeAdd(gameProfileInfo);
|
||||
@@ -73,7 +74,7 @@
|
||||
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
|
||||
boolean flag = false;
|
||||
if (gameProfileInfo != null && new Date().getTime() >= gameProfileInfo.expirationDate.getTime()) {
|
||||
@@ -133,19 +_,24 @@
|
||||
@@ -118,19 +_,24 @@
|
||||
if (gameProfileInfo != null) {
|
||||
gameProfileInfo.setLastAccess(this.getNextOperation());
|
||||
optional = Optional.of(gameProfileInfo.getProfile());
|
||||
@@ -101,7 +102,7 @@
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<GameProfile>> getAsync(String name) {
|
||||
@@ -157,7 +_,7 @@
|
||||
@@ -142,7 +_,7 @@
|
||||
return completableFuture;
|
||||
} else {
|
||||
CompletableFuture<Optional<GameProfile>> completableFuture1 = CompletableFuture.<Optional<GameProfile>>supplyAsync(
|
||||
@@ -110,7 +111,7 @@
|
||||
)
|
||||
.whenCompleteAsync((gameProfile, exception) -> this.requests.remove(name), this.executor);
|
||||
this.requests.put(name, completableFuture1);
|
||||
@@ -167,6 +_,7 @@
|
||||
@@ -152,6 +_,7 @@
|
||||
}
|
||||
|
||||
public Optional<GameProfile> get(UUID uuid) {
|
||||
@@ -118,7 +119,7 @@
|
||||
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByUUID.get(uuid);
|
||||
if (gameProfileInfo == null) {
|
||||
return Optional.empty();
|
||||
@@ -174,6 +_,7 @@
|
||||
@@ -159,6 +_,7 @@
|
||||
gameProfileInfo.setLastAccess(this.getNextOperation());
|
||||
return Optional.of(gameProfileInfo.getProfile());
|
||||
}
|
||||
@@ -126,7 +127,7 @@
|
||||
}
|
||||
|
||||
public void setExecutor(Executor exectutor) {
|
||||
@@ -206,6 +_,11 @@
|
||||
@@ -191,6 +_,11 @@
|
||||
|
||||
return (List<GameProfileCache.GameProfileInfo>)var9;
|
||||
} catch (FileNotFoundException var7) {
|
||||
@@ -138,7 +139,7 @@
|
||||
} catch (JsonParseException | IOException var8) {
|
||||
LOGGER.warn("Failed to load profile cache {}", this.file, var8);
|
||||
}
|
||||
@@ -213,24 +_,45 @@
|
||||
@@ -198,24 +_,45 @@
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
--- a/net/minecraft/server/players/OldUsersConverter.java
|
||||
+++ b/net/minecraft/server/players/OldUsersConverter.java
|
||||
@@ -20,6 +_,9 @@
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.core.UUIDUtil;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.NbtAccounter;
|
||||
+import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.util.StringUtil;
|
||||
@@ -49,7 +_,8 @@
|
||||
|
||||
private static void lookupPlayers(MinecraftServer server, Collection<String> names, ProfileLookupCallback callback) {
|
||||
@@ -61,10 +51,10 @@
|
||||
File file4 = new File(worldPlayersDirectory, oldFileName + ".dat");
|
||||
File file5 = new File(file3, newFileName + ".dat");
|
||||
+ // CraftBukkit start - Use old file name to seed lastKnownName
|
||||
+ CompoundTag root = null;
|
||||
+ net.minecraft.nbt.CompoundTag root = null;
|
||||
+
|
||||
+ try {
|
||||
+ root = NbtIo.readCompressed(new java.io.FileInputStream(file4), NbtAccounter.unlimitedHeap());
|
||||
+ root = net.minecraft.nbt.NbtIo.readCompressed(new java.io.FileInputStream(file4), net.minecraft.nbt.NbtAccounter.unlimitedHeap());
|
||||
+ } catch (Exception exception) {
|
||||
+ // Paper start
|
||||
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
|
||||
@@ -75,13 +65,13 @@
|
||||
+
|
||||
+ if (root != null) {
|
||||
+ if (!root.contains("bukkit")) {
|
||||
+ root.put("bukkit", new CompoundTag());
|
||||
+ root.put("bukkit", new net.minecraft.nbt.CompoundTag());
|
||||
+ }
|
||||
+ CompoundTag data = root.getCompound("bukkit");
|
||||
+ net.minecraft.nbt.CompoundTag data = root.getCompoundOrEmpty("bukkit");
|
||||
+ data.putString("lastKnownName", oldFileName);
|
||||
+
|
||||
+ try {
|
||||
+ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file1));
|
||||
+ net.minecraft.nbt.NbtIo.writeCompressed(root, new java.io.FileOutputStream(file1));
|
||||
+ } catch (Exception exception) {
|
||||
+ // Paper start
|
||||
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
GameProfile gameProfile = player.getGameProfile();
|
||||
GameProfileCache profileCache = this.server.getProfileCache();
|
||||
String string;
|
||||
@@ -150,30 +_,93 @@
|
||||
@@ -150,30 +_,94 @@
|
||||
}
|
||||
|
||||
Optional<CompoundTag> optional = this.load(player);
|
||||
@@ -55,11 +55,7 @@
|
||||
- compoundTag -> DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error)
|
||||
+ // CraftBukkit start - Better rename detection
|
||||
+ if (optional.isPresent()) {
|
||||
+ CompoundTag nbttagcompound = optional.get();
|
||||
+ if (nbttagcompound.contains("bukkit")) {
|
||||
+ CompoundTag bukkit = nbttagcompound.getCompound("bukkit");
|
||||
+ string = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : string;
|
||||
+ }
|
||||
+ string = optional.flatMap(t -> t.getCompound("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
|
||||
@@ -68,10 +64,15 @@
|
||||
+ bukkitData: if (optional.isPresent()) {
|
||||
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
|
||||
+ final org.bukkit.World bWorld;
|
||||
+ if (optional.get().contains("WorldUUIDMost") && optional.get().contains("WorldUUIDLeast")) {
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(optional.get().getLong("WorldUUIDMost"), optional.get().getLong("WorldUUIDLeast")));
|
||||
+ } else if (optional.get().contains("world", net.minecraft.nbt.Tag.TAG_STRING)) { // Paper - legacy bukkit world name
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(optional.get().getString("world"));
|
||||
+ final CompoundTag playerData = optional.get();
|
||||
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
|
||||
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
|
||||
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
|
||||
+ final java.util.Optional<String> worldName = playerData.getString("world");
|
||||
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
|
||||
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
|
||||
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
|
||||
+ } else {
|
||||
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
|
||||
+ }
|
||||
@@ -113,7 +114,7 @@
|
||||
+ }
|
||||
+ if (optional.isEmpty() || invalidPlayerWorld[0]) {
|
||||
+ // Paper end - reset to main world spawn if first spawn or invalid world
|
||||
+ player.moveTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
+ player.snapTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
+ }
|
||||
+ // Paper end - Entity#getEntitySpawnReason
|
||||
player.setServerLevel(serverLevel);
|
||||
@@ -153,7 +154,7 @@
|
||||
LevelData levelData = serverLevel.getLevelData();
|
||||
player.loadGameTypes(optional.orElse(null));
|
||||
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
|
||||
@@ -190,8 +_,8 @@
|
||||
@@ -191,8 +_,8 @@
|
||||
levelData.isHardcore(),
|
||||
this.server.levelKeys(),
|
||||
this.getMaxPlayers(),
|
||||
@@ -164,15 +165,15 @@
|
||||
_boolean1,
|
||||
!_boolean,
|
||||
_boolean2,
|
||||
@@ -199,6 +_,7 @@
|
||||
@@ -200,6 +_,7 @@
|
||||
this.server.enforceSecureProfile()
|
||||
)
|
||||
);
|
||||
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
||||
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
|
||||
@@ -218,24 +_,117 @@
|
||||
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
@@ -219,26 +_,119 @@
|
||||
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
|
||||
}
|
||||
|
||||
@@ -201,8 +202,10 @@
|
||||
- this.sendActivePlayerEffects(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
|
||||
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
|
||||
player.loadAndSpawnEnderpearls(optional);
|
||||
player.loadAndSpawnParentVehicle(optional);
|
||||
optional.ifPresent(compoundTag -> {
|
||||
player.loadAndSpawnEnderPearls(compoundTag);
|
||||
player.loadAndSpawnParentVehicle(compoundTag);
|
||||
});
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||
+
|
||||
@@ -296,7 +299,7 @@
|
||||
}
|
||||
|
||||
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
|
||||
@@ -258,30 +_,31 @@
|
||||
@@ -261,30 +_,31 @@
|
||||
}
|
||||
|
||||
public void addWorldborderListener(ServerLevel level) {
|
||||
@@ -333,7 +336,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,56 +_,162 @@
|
||||
@@ -312,56 +_,156 @@
|
||||
}
|
||||
|
||||
protected void save(ServerPlayer player) {
|
||||
@@ -353,11 +356,11 @@
|
||||
}
|
||||
|
||||
- public void remove(ServerPlayer player) {
|
||||
+ public net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
|
||||
+ public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
|
||||
+ // Paper start - Fix kick event leave message not being sent
|
||||
+ return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
|
||||
+ }
|
||||
+ public net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
|
||||
+ public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
|
||||
+ // Paper end - Fix kick event leave message not being sent
|
||||
ServerLevel serverLevel = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
@@ -469,28 +472,22 @@
|
||||
- if (this.bans.isBanned(gameProfile)) {
|
||||
- UserBanListEntry userBanListEntry = this.bans.get(gameProfile);
|
||||
+ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer
|
||||
+ public ServerPlayer canPlayerLogin(net.minecraft.server.network.ServerLoginPacketListenerImpl loginlistener, GameProfile gameProfile) {
|
||||
+ public @Nullable ServerPlayer canPlayerLogin(net.minecraft.server.network.ServerLoginPacketListenerImpl loginlistener, GameProfile gameProfile) {
|
||||
+ // if (this.bans.isBanned(gameProfile)) {
|
||||
+ // UserBanListEntry userBanListEntry = this.bans.get(gameProfile);
|
||||
+ // Moved from processLogin
|
||||
+ // Moved from disconnectAllPlayersWithProfile
|
||||
+ UUID uuid = gameProfile.getId();
|
||||
+ List<ServerPlayer> list = Lists.newArrayList();
|
||||
+
|
||||
+ ServerPlayer entityplayer;
|
||||
+
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ entityplayer = (ServerPlayer) this.players.get(i);
|
||||
+ if (entityplayer.getUUID().equals(uuid) || (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && entityplayer.getGameProfile().getName().equalsIgnoreCase(gameProfile.getName()))) { // Paper - validate usernames
|
||||
+ list.add(entityplayer);
|
||||
+ for (net.minecraft.server.level.ServerPlayer serverPlayer : this.players) {
|
||||
+ if (serverPlayer.getUUID().equals(uuid) || (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && serverPlayer.getGameProfile().getName().equalsIgnoreCase(gameProfile.getName()))) { // Paper - validate usernames
|
||||
+ list.add(serverPlayer);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ java.util.Iterator iterator = list.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ entityplayer = (ServerPlayer) iterator.next();
|
||||
+ this.save(entityplayer); // CraftBukkit - Force the player's inventory to be saved
|
||||
+ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login"), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause
|
||||
+ for (final net.minecraft.server.level.ServerPlayer serverPlayer : list) {
|
||||
+ this.save(serverPlayer); // CraftBukkit - Force the player's inventory to be saved
|
||||
+ serverPlayer.connection.disconnect(DUPLICATE_LOGIN_DISCONNECT_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause
|
||||
+ }
|
||||
+
|
||||
+ // Instead of kicking then returning, we need to store the kick reason
|
||||
@@ -510,7 +507,7 @@
|
||||
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason());
|
||||
if (userBanListEntry.getExpires() != null) {
|
||||
mutableComponent.append(
|
||||
@@ -366,10 +_,12 @@
|
||||
@@ -369,10 +_,12 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -527,7 +524,7 @@
|
||||
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
|
||||
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
|
||||
if (ipBanListEntry.getExpires() != null) {
|
||||
@@ -378,69 +_,129 @@
|
||||
@@ -381,69 +_,130 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -614,10 +611,11 @@
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason) {
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason) {
|
||||
+ return this.respawn(player, keepInventory, reason, eventReason, null);
|
||||
+ }
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, org.bukkit.Location location) {
|
||||
+
|
||||
+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, @Nullable org.bukkit.Location location) {
|
||||
+ player.stopRiding(); // CraftBukkit
|
||||
this.players.remove(player);
|
||||
+ this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
@@ -665,7 +663,7 @@
|
||||
+ location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(teleportTransition.position(), teleportTransition.newLevel().getWorld(), teleportTransition.yRot(), teleportTransition.xRot());
|
||||
+ // Paper end - Add PlayerPostRespawnEvent
|
||||
+ } else {
|
||||
+ teleportTransition = new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3D(location), Vec3.ZERO, location.getYaw(), location.getPitch(), TeleportTransition.DO_NOTHING);
|
||||
+ teleportTransition = new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3(location), Vec3.ZERO, location.getYaw(), location.getPitch(), TeleportTransition.DO_NOTHING);
|
||||
+ }
|
||||
+ // Spigot start
|
||||
+ if (teleportTransition == null) { // Paper - Add PlayerPostRespawnEvent - diff on change - spigot early returns if respawn pos is null, that is how they handle disconnected player in respawn event
|
||||
@@ -677,13 +675,13 @@
|
||||
+ serverPlayer.unsetRemoved();
|
||||
+ serverPlayer.setShiftKeyDown(false);
|
||||
Vec3 vec3 = teleportTransition.position();
|
||||
- serverPlayer.moveTo(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
|
||||
- serverPlayer.snapTo(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
|
||||
+ serverPlayer.forceSetPositionRotation(vec3.x, vec3.y, vec3.z, teleportTransition.yRot(), teleportTransition.xRot());
|
||||
+ level.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3.x()) >> 4, net.minecraft.util.Mth.floor(vec3.z()) >> 4), 1, player.getId()); // Paper - post teleport ticket type
|
||||
+ level.getChunkSource().addTicketWithRadius(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3.x()) >> 4, net.minecraft.util.Mth.floor(vec3.z()) >> 4), 1); // Paper - post teleport ticket type
|
||||
+ // CraftBukkit end
|
||||
if (teleportTransition.missingRespawnBlock()) {
|
||||
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
|
||||
+ serverPlayer.setRespawnPosition(null, null, 0f, false, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - PlayerSetSpawnEvent
|
||||
+ serverPlayer.setRespawnPosition(null, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - PlayerSetSpawnEvent
|
||||
}
|
||||
|
||||
byte b = (byte)(keepInventory ? 1 : 0);
|
||||
@@ -698,7 +696,7 @@
|
||||
serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
|
||||
serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
|
||||
serverPlayer.connection
|
||||
@@ -448,10 +_,13 @@
|
||||
@@ -451,10 +_,13 @@
|
||||
this.sendActivePlayerEffects(serverPlayer);
|
||||
this.sendLevelInfo(serverPlayer, level);
|
||||
this.sendPlayerPermissionLevel(serverPlayer);
|
||||
@@ -714,19 +712,19 @@
|
||||
+ }
|
||||
+ // serverPlayer.initInventoryMenu();
|
||||
serverPlayer.setHealth(serverPlayer.getHealth());
|
||||
BlockPos respawnPosition = serverPlayer.getRespawnPosition();
|
||||
ServerLevel level1 = this.server.getLevel(serverPlayer.getRespawnDimension());
|
||||
@@ -472,7 +_,40 @@
|
||||
)
|
||||
);
|
||||
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
|
||||
if (!keepInventory && respawnConfig != null) {
|
||||
@@ -477,8 +_,41 @@
|
||||
)
|
||||
);
|
||||
}
|
||||
+ // Paper start - Add PlayerPostRespawnEvent
|
||||
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) {
|
||||
+ isBedSpawn = true;
|
||||
+ }
|
||||
+ // Paper end - Add PlayerPostRespawnEvent
|
||||
}
|
||||
- }
|
||||
+ // Paper start - Add PlayerPostRespawnEvent
|
||||
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) {
|
||||
+ isBedSpawn = true;
|
||||
+ }
|
||||
+ // Paper end - Add PlayerPostRespawnEvent
|
||||
+ }
|
||||
}
|
||||
+ // Added from changeDimension
|
||||
+ this.sendAllPlayerInfo(player); // Update health, etc...
|
||||
+ player.onUpdateAbilities();
|
||||
@@ -758,7 +756,7 @@
|
||||
|
||||
return serverPlayer;
|
||||
}
|
||||
@@ -482,24 +_,60 @@
|
||||
@@ -488,24 +_,60 @@
|
||||
}
|
||||
|
||||
public void sendActiveEffects(LivingEntity entity, ServerGamePacketListenerImpl connection) {
|
||||
@@ -822,19 +820,20 @@
|
||||
public void broadcastAll(Packet<?> packet) {
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
serverPlayer.connection.send(packet);
|
||||
@@ -575,6 +_,11 @@
|
||||
@@ -581,6 +_,12 @@
|
||||
}
|
||||
|
||||
private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) {
|
||||
+ // Paper start - Add sendOpLevel API
|
||||
+ this.sendPlayerPermissionLevel(player, permLevel, true);
|
||||
+ }
|
||||
+
|
||||
+ public void sendPlayerPermissionLevel(ServerPlayer player, int permLevel, boolean recalculatePermissions) {
|
||||
+ // Paper end - Add sendOpLevel API
|
||||
if (player.connection != null) {
|
||||
byte b;
|
||||
if (permLevel <= 0) {
|
||||
@@ -588,11 +_,32 @@
|
||||
@@ -594,11 +_,33 @@
|
||||
player.connection.send(new ClientboundEntityEventPacket(player, b));
|
||||
}
|
||||
|
||||
@@ -849,6 +848,7 @@
|
||||
+ // Paper start - ProfileWhitelistVerifyEvent
|
||||
+ return this.isWhiteListed(profile, null);
|
||||
+ }
|
||||
+
|
||||
+ public boolean isWhiteListed(GameProfile gameprofile, @Nullable org.bukkit.event.player.PlayerLoginEvent loginEvent) {
|
||||
+ boolean isOp = this.ops.contains(gameprofile);
|
||||
+ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile);
|
||||
@@ -868,7 +868,7 @@
|
||||
}
|
||||
|
||||
public boolean isOp(GameProfile profile) {
|
||||
@@ -603,21 +_,17 @@
|
||||
@@ -609,21 +_,17 @@
|
||||
|
||||
@Nullable
|
||||
public ServerPlayer getPlayerByName(String username) {
|
||||
@@ -896,7 +896,7 @@
|
||||
if (serverPlayer != except && serverPlayer.level().dimension() == dimension) {
|
||||
double d = x - serverPlayer.getX();
|
||||
double d1 = y - serverPlayer.getY();
|
||||
@@ -630,9 +_,11 @@
|
||||
@@ -636,9 +_,11 @@
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
@@ -908,7 +908,7 @@
|
||||
}
|
||||
|
||||
public UserWhiteList getWhiteList() {
|
||||
@@ -655,14 +_,18 @@
|
||||
@@ -661,14 +_,18 @@
|
||||
}
|
||||
|
||||
public void sendLevelInfo(ServerPlayer player, ServerLevel level) {
|
||||
@@ -931,7 +931,7 @@
|
||||
}
|
||||
|
||||
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
|
||||
@@ -671,8 +_,21 @@
|
||||
@@ -677,8 +_,21 @@
|
||||
|
||||
public void sendAllPlayerInfo(ServerPlayer player) {
|
||||
player.inventoryMenu.sendAllDataToRemote();
|
||||
@@ -944,7 +944,7 @@
|
||||
+ 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));
|
||||
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
+ // CraftBukkit start - from GameRules
|
||||
+ int i = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
|
||||
+ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i));
|
||||
@@ -954,7 +954,7 @@
|
||||
}
|
||||
|
||||
public int getPlayerCount() {
|
||||
@@ -688,6 +_,7 @@
|
||||
@@ -694,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void setUsingWhiteList(boolean whitelistEnabled) {
|
||||
@@ -962,7 +962,7 @@
|
||||
this.doWhiteList = whitelistEnabled;
|
||||
}
|
||||
|
||||
@@ -725,10 +_,35 @@
|
||||
@@ -731,10 +_,35 @@
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
@@ -1002,7 +1002,7 @@
|
||||
|
||||
public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) {
|
||||
this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat);
|
||||
@@ -750,20 +_,39 @@
|
||||
@@ -756,20 +_,39 @@
|
||||
}
|
||||
|
||||
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) {
|
||||
@@ -1045,12 +1045,7 @@
|
||||
flag1 |= flag2 && message.isFullyFiltered();
|
||||
}
|
||||
|
||||
@@ -772,18 +_,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private boolean verifyChatTrusted(PlayerChatMessage message) {
|
||||
+ public boolean verifyChatTrusted(PlayerChatMessage message) { // Paper - private -> public
|
||||
@@ -782,14 +_,21 @@
|
||||
return message.hasSignature() && !message.hasExpiredServer(Instant.now());
|
||||
}
|
||||
|
||||
@@ -1076,7 +1071,7 @@
|
||||
Path path = file2.toPath();
|
||||
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
|
||||
file2.renameTo(file1);
|
||||
@@ -791,7 +_,7 @@
|
||||
@@ -797,7 +_,7 @@
|
||||
}
|
||||
|
||||
serverStatsCounter = new ServerStatsCounter(this.server, file1);
|
||||
@@ -1085,7 +1080,7 @@
|
||||
}
|
||||
|
||||
return serverStatsCounter;
|
||||
@@ -799,11 +_,11 @@
|
||||
@@ -805,11 +_,11 @@
|
||||
|
||||
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
|
||||
UUID uuid = player.getUUID();
|
||||
@@ -1099,7 +1094,7 @@
|
||||
}
|
||||
|
||||
playerAdvancements.setPlayer(player);
|
||||
@@ -846,11 +_,34 @@
|
||||
@@ -852,11 +_,34 @@
|
||||
}
|
||||
|
||||
public void reloadResources() {
|
||||
@@ -1118,7 +1113,7 @@
|
||||
+ // }
|
||||
+ for (ServerPlayer player : this.players) {
|
||||
+ player.getAdvancements().reload(this.server.getAdvancements());
|
||||
+ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements
|
||||
+ player.getAdvancements().flushDirty(player, false); // CraftBukkit - trigger immediate flush of advancements
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/stats/ServerRecipeBook.java
|
||||
+++ b/net/minecraft/stats/ServerRecipeBook.java
|
||||
@@ -67,7 +_,7 @@
|
||||
@@ -66,7 +_,7 @@
|
||||
|
||||
for (RecipeHolder<?> recipeHolder : recipes) {
|
||||
ResourceKey<Recipe<?>> resourceKey = recipeHolder.id();
|
||||
@@ -9,7 +9,7 @@
|
||||
this.add(resourceKey);
|
||||
this.addHighlight(resourceKey);
|
||||
this.displayResolver
|
||||
@@ -78,7 +_,7 @@
|
||||
@@ -77,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
player.connection.send(new ClientboundRecipeBookAddPacket(list, false));
|
||||
}
|
||||
|
||||
@@ -96,7 +_,7 @@
|
||||
@@ -95,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/stats/ServerStatsCounter.java
|
||||
+++ b/net/minecraft/stats/ServerStatsCounter.java
|
||||
@@ -51,9 +_,21 @@
|
||||
@@ -70,9 +_,21 @@
|
||||
LOGGER.error("Couldn't parse statistics file {}", file, var5);
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
+ // Disables saving any forced stats, so it stays at the same value (without enabling disableStatSaving)
|
||||
+ // Fixes stat initialization to not cause a NullPointerException
|
||||
+ // Spigot start
|
||||
+ for (Map.Entry<ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet()) {
|
||||
+ Stat<ResourceLocation> wrapper = Stats.CUSTOM.get(java.util.Objects.requireNonNull(BuiltInRegistries.CUSTOM_STAT.getValue(entry.getKey()))); // Paper - ensured by SpigotConfig#stats
|
||||
+ for (Map.Entry<net.minecraft.resources.ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet()) {
|
||||
+ Stat<net.minecraft.resources.ResourceLocation> wrapper = Stats.CUSTOM.get(java.util.Objects.requireNonNull(BuiltInRegistries.CUSTOM_STAT.getValue(entry.getKey()))); // Paper - ensured by SpigotConfig#stats
|
||||
+ this.stats.put(wrapper, entry.getValue().intValue());
|
||||
+ }
|
||||
+ // Spigot end
|
||||
@@ -22,12 +22,12 @@
|
||||
try {
|
||||
FileUtils.writeStringToFile(this.file, this.toJson());
|
||||
} catch (IOException var2) {
|
||||
@@ -63,6 +_,8 @@
|
||||
@@ -82,6 +_,8 @@
|
||||
|
||||
@Override
|
||||
public void setValue(Player player, Stat<?> stat, int i) {
|
||||
+ if (org.spigotmc.SpigotConfig.disableStatSaving) return; // Spigot
|
||||
+ if (stat.getType() == Stats.CUSTOM && stat.getValue() instanceof final ResourceLocation resourceLocation && org.spigotmc.SpigotConfig.forcedStats.get(resourceLocation) != null) return; // Paper - disable saving forced stats
|
||||
+ if (stat.getType() == Stats.CUSTOM && stat.getValue() instanceof final net.minecraft.resources.ResourceLocation resourceLocation && org.spigotmc.SpigotConfig.forcedStats.get(resourceLocation) != null) return; // Paper - disable saving forced stats
|
||||
super.setValue(player, stat, i);
|
||||
this.dirty.add(stat);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
)) {
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ final com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(level, pos),
|
||||
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entityType),
|
||||
+ reason
|
||||
+ );
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
--- a/net/minecraft/util/datafix/DataFixers.java
|
||||
+++ b/net/minecraft/util/datafix/DataFixers.java
|
||||
@@ -505,6 +_,18 @@
|
||||
@@ -541,6 +_,18 @@
|
||||
Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED);
|
||||
builder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
|
||||
Schema schema45 = builder.addSchema(1458, SAME_NAMESPACED);
|
||||
Schema schema45 = builder.addSchema(1458, V1458::new);
|
||||
+ // CraftBukkit start
|
||||
+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) {
|
||||
+ @Override
|
||||
+ protected com.mojang.datafixers.TypeRewriteRule makeRule() {
|
||||
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), (typed) -> {
|
||||
+ return typed.update(DSL.remainderFinder(), (dynamic) -> {
|
||||
+ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic);
|
||||
+ return EntityCustomNameToComponentFix.fixCustomName(dynamic.getOps(), dynamic.get("CustomName").asString(""), "minecraft:player");
|
||||
+ });
|
||||
+ });
|
||||
+ }
|
||||
+ });
|
||||
+ // CraftBukkit end
|
||||
builder.addFixer(new EntityCustomNameToComponentFix(schema45, false));
|
||||
builder.addFixer(new ItemCustomNameToComponentFix(schema45, false));
|
||||
builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false));
|
||||
builder.addFixer(new EntityCustomNameToComponentFix(schema45));
|
||||
builder.addFixer(new ItemCustomNameToComponentFix(schema45));
|
||||
builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45));
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/net/minecraft/util/parsing/packrat/Scope.java
|
||||
+++ b/net/minecraft/util/parsing/packrat/Scope.java
|
||||
@@ -281,4 +_,36 @@
|
||||
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ // Paper start - track depth
|
||||
+ private int depth;
|
||||
+ @SuppressWarnings({"unchecked","rawtypes"})
|
||||
+ public static <S> Term<S> increaseDepth() {
|
||||
+ class IncreasingDepthTerm<W> implements Term<W> {
|
||||
+ public static final IncreasingDepthTerm INSTANCE = new IncreasingDepthTerm();
|
||||
+ @Override
|
||||
+ public boolean parse(final ParseState<W> parseState, final Scope scope, final Control control) {
|
||||
+ if (++scope.depth > 512) {
|
||||
+ parseState.errorCollector().store(parseState.mark(), new IllegalStateException("Too deep"));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return (Term<S>) IncreasingDepthTerm.INSTANCE;
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings({"unchecked","rawtypes"})
|
||||
+ public static <S> Term<S> decreaseDepth() {
|
||||
+ class DecreasingDepthTerm<W> implements Term<W> {
|
||||
+ public static final DecreasingDepthTerm INSTANCE = new DecreasingDepthTerm();
|
||||
+ @Override
|
||||
+ public boolean parse(final ParseState<W> parseState, final Scope scope, final Control control) {
|
||||
+ scope.depth--;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return (Term<S>) DecreasingDepthTerm.INSTANCE;
|
||||
+ }
|
||||
+ // Paper end - track depth
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
--- a/net/minecraft/util/random/WeightedList.java
|
||||
+++ b/net/minecraft/util/random/WeightedList.java
|
||||
@@ -13,14 +_,14 @@
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
-public final class WeightedList<E> {
|
||||
+public class WeightedList<E> { // Paper - non-final
|
||||
private static final int FLAT_THRESHOLD = 64;
|
||||
private final int totalWeight;
|
||||
private final List<Weighted<E>> items;
|
||||
@Nullable
|
||||
private final WeightedList.Selector<E> selector;
|
||||
|
||||
- WeightedList(List<? extends Weighted<E>> items) {
|
||||
+ protected WeightedList(List<? extends Weighted<E>> items) { // Paper - protected
|
||||
this.items = List.copyOf(items);
|
||||
this.totalWeight = WeightedRandom.getTotalWeight(items, Weighted::weight);
|
||||
if (this.totalWeight == 0) {
|
||||
@@ -122,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static class Builder<E> {
|
||||
- private final ImmutableList.Builder<Weighted<E>> result = ImmutableList.builder();
|
||||
+ protected final ImmutableList.Builder<Weighted<E>> result = ImmutableList.builder();
|
||||
|
||||
public WeightedList.Builder<E> add(E element) {
|
||||
return this.add(element, 1);
|
||||
@@ -1,7 +1,7 @@
|
||||
--- a/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
+++ b/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
@@ -79,7 +_,7 @@
|
||||
LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, RegistryAccess registryAccess, boolean eraseCache, boolean recreateRegionFiles
|
||||
@@ -87,7 +_,7 @@
|
||||
boolean recreateRegionFiles
|
||||
) {
|
||||
this.dimensions = registryAccess.lookupOrThrow(Registries.LEVEL_STEM);
|
||||
- this.levels = this.dimensions.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet());
|
||||
@@ -9,12 +9,12 @@
|
||||
this.eraseCache = eraseCache;
|
||||
this.dataFixer = dataFixer;
|
||||
this.levelStorage = levelStorage;
|
||||
@@ -358,7 +_,7 @@
|
||||
@@ -369,7 +_,7 @@
|
||||
int version = ChunkStorage.getVersion(compoundTag);
|
||||
ChunkGenerator chunkGenerator = WorldUpgrader.this.dimensions.getValueOrThrow(Registries.levelToLevelStem(dimension)).generator();
|
||||
CompoundTag compoundTag1 = chunkStorage.upgradeChunkTag(
|
||||
- dimension, () -> WorldUpgrader.this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer()
|
||||
+ Registries.levelToLevelStem(dimension), () -> WorldUpgrader.this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer(), chunkPos, null // CraftBukkit
|
||||
);
|
||||
ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getInt("xPos"), compoundTag1.getInt("zPos"));
|
||||
ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getIntOr("xPos", 0), compoundTag1.getIntOr("zPos", 0));
|
||||
if (!chunkPos1.equals(chunkPos)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/BossEvent.java
|
||||
+++ b/net/minecraft/world/BossEvent.java
|
||||
@@ -13,6 +_,7 @@
|
||||
@@ -15,6 +_,7 @@
|
||||
protected boolean darkenScreen;
|
||||
protected boolean playBossMusic;
|
||||
protected boolean createWorldFog;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public BossEvent(UUID id, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay overlay) {
|
||||
this.id = id;
|
||||
@@ -27,61 +_,75 @@
|
||||
@@ -29,61 +_,75 @@
|
||||
}
|
||||
|
||||
public Component getName() {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
--- a/net/minecraft/world/CompoundContainer.java
|
||||
+++ b/net/minecraft/world/CompoundContainer.java
|
||||
@@ -7,6 +_,48 @@
|
||||
@@ -7,6 +_,53 @@
|
||||
public final Container container1;
|
||||
public final Container container2;
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> getContents() {
|
||||
+ java.util.List<ItemStack> result = new java.util.ArrayList<>(this.getContainerSize());
|
||||
+ for (int i = 0; i < this.getContainerSize(); i++) {
|
||||
@@ -15,23 +16,27 @@
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
|
||||
+ this.container1.onOpen(player);
|
||||
+ this.container2.onOpen(player);
|
||||
+ this.transaction.add(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
|
||||
+ this.container1.onClose(player);
|
||||
+ this.container2.onClose(player);
|
||||
+ this.transaction.remove(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ @Override
|
||||
+ public @javax.annotation.Nullable org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -24,9 +_,7 @@
|
||||
@@ -26,9 +_,7 @@
|
||||
|
||||
void setItem(int slot, ItemStack stack);
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
default int getMaxStackSize(ItemStack stack) {
|
||||
return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
|
||||
@@ -87,4 +_,22 @@
|
||||
BlockPos blockPos = blockEntity.getBlockPos();
|
||||
return level != null && level.getBlockEntity(blockPos) == blockEntity && player.canInteractWithBlock(blockPos, distance);
|
||||
@@ -117,4 +_,22 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
@@ -25,11 +25,11 @@
|
||||
+
|
||||
+ java.util.List<org.bukkit.entity.HumanEntity> getViewers();
|
||||
+
|
||||
+ org.bukkit.inventory.@org.jetbrains.annotations.Nullable InventoryHolder getOwner();
|
||||
+ @javax.annotation.Nullable org.bukkit.inventory.InventoryHolder getOwner();
|
||||
+
|
||||
+ void setMaxStackSize(int size);
|
||||
+
|
||||
+ org.bukkit.Location getLocation();
|
||||
+ @javax.annotation.Nullable org.bukkit.Location getLocation();
|
||||
+
|
||||
+ int MAX_STACK = Item.ABSOLUTE_MAX_STACK_SIZE;
|
||||
+ // CraftBukkit end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/RandomizableContainer.java
|
||||
+++ b/net/minecraft/world/RandomizableContainer.java
|
||||
@@ -28,7 +_,7 @@
|
||||
@@ -26,7 +_,7 @@
|
||||
|
||||
void setLootTable(@Nullable ResourceKey<LootTable> lootTable);
|
||||
|
||||
@@ -9,30 +9,21 @@
|
||||
this.setLootTable(lootTable);
|
||||
this.setLootTableSeed(seed);
|
||||
}
|
||||
@@ -50,15 +_,17 @@
|
||||
|
||||
@@ -49,8 +_,9 @@
|
||||
default boolean tryLoadLootTable(CompoundTag tag) {
|
||||
if (tag.contains("LootTable", 8)) {
|
||||
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(tag.getString("LootTable"))));
|
||||
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(tag.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
|
||||
+ if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
|
||||
if (tag.contains("LootTableSeed", 4)) {
|
||||
this.setLootTableSeed(tag.getLong("LootTableSeed"));
|
||||
} else {
|
||||
this.setLootTableSeed(0L);
|
||||
}
|
||||
|
||||
- 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;
|
||||
}
|
||||
ResourceKey<LootTable> resourceKey = tag.read("LootTable", LootTable.KEY_CODEC).orElse(null);
|
||||
this.setLootTable(resourceKey);
|
||||
+ if (this.lootableData() != null && resourceKey != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
|
||||
this.setLootTableSeed(tag.getLongOr("LootTableSeed", 0L));
|
||||
- return resourceKey != null;
|
||||
+ return resourceKey != null && this.lootableData() == null; // Paper - only track the loot table if there is chance for replenish
|
||||
}
|
||||
@@ -69,26 +_,42 @@
|
||||
|
||||
default boolean trySaveLootTable(CompoundTag tag) {
|
||||
@@ -59,26 +_,42 @@
|
||||
return false;
|
||||
} else {
|
||||
tag.putString("LootTable", lootTable.location().toString());
|
||||
tag.store("LootTable", LootTable.KEY_CODEC, lootTable);
|
||||
+ if (this.lootableData() != null) this.lootableData().saveNbt(tag); // Paper - LootTable API
|
||||
long lootTableSeed = this.getLootTableSeed();
|
||||
if (lootTableSeed != 0L) {
|
||||
@@ -74,7 +65,7 @@
|
||||
LootParams.Builder builder = new LootParams.Builder((ServerLevel)level).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos));
|
||||
if (player != null) {
|
||||
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
|
||||
@@ -97,4 +_,17 @@
|
||||
@@ -87,4 +_,17 @@
|
||||
lootTable1.fill(this, builder.create(LootContextParamSets.CHEST), this.getLootTableSeed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/net/minecraft/world/SimpleContainer.java
|
||||
@@ -19,7 +_,84 @@
|
||||
@@ -19,7 +_,90 @@
|
||||
@Nullable
|
||||
private List<ContainerListener> listeners;
|
||||
|
||||
@@ -9,18 +9,22 @@
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+ protected @Nullable org.bukkit.inventory.InventoryHolder bukkitOwner; // Paper - annotation
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
|
||||
+ this.transaction.add(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
|
||||
+ this.transaction.remove(player);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
@@ -30,11 +34,13 @@
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int i) {
|
||||
+ this.maxStack = i;
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ @Override
|
||||
+ public @Nullable org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ // Paper start - Add missing InventoryHolders
|
||||
+ if (this.bukkitOwner == null && this.bukkitOwnerCreator != null) {
|
||||
+ this.bukkitOwner = this.bukkitOwnerCreator.get();
|
||||
@@ -44,7 +50,7 @@
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ public @Nullable org.bukkit.Location getLocation() {
|
||||
+ // Paper start - Fix inventories returning null Locations
|
||||
+ // When the block inventory does not have a tile state that implements getLocation, e. g. composters
|
||||
+ if (this.bukkitOwner instanceof org.bukkit.inventory.BlockInventoryHolder blockInventoryHolder) {
|
||||
@@ -79,7 +85,7 @@
|
||||
+ }
|
||||
+ // Paper end - Add missing InventoryHolders
|
||||
+
|
||||
+ public SimpleContainer(int size, org.bukkit.inventory.InventoryHolder owner) {
|
||||
+ public SimpleContainer(int size, @Nullable org.bukkit.inventory.InventoryHolder owner) {
|
||||
+ this.bukkitOwner = owner;
|
||||
+ // Paper end
|
||||
this.size = size;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
+ return this.eventBlockDamager;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource eventBlockDamager(final @Nullable net.minecraft.world.level.LevelAccessor level, final @Nullable net.minecraft.core.BlockPos pos) {
|
||||
+ public DamageSource eventBlockDamager(final net.minecraft.world.level.LevelAccessor level, final @Nullable net.minecraft.core.BlockPos pos) {
|
||||
+ if (pos == null) {
|
||||
+ return this;
|
||||
+ }
|
||||
@@ -60,7 +60,7 @@
|
||||
+ return this.fromBlockSnapshot;
|
||||
+ }
|
||||
+
|
||||
+ public DamageSource causingBlockSnapshot(final @Nullable org.bukkit.block.BlockState blockState) {
|
||||
+ public DamageSource causingBlockSnapshot(final 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)");
|
||||
+ }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
+++ b/net/minecraft/world/effect/InfestedMobEffect.java
|
||||
@@ -44,7 +_,11 @@
|
||||
Vector3f vector3f = entity.getLookAngle().toVector3f().mul(0.3F).mul(1.0F, 1.5F, 1.0F).rotateY(f1);
|
||||
silverfish.moveTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
|
||||
silverfish.snapTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
|
||||
silverfish.setDeltaMovement(new Vec3(vector3f));
|
||||
- level.addFreshEntity(silverfish);
|
||||
+ // CraftBukkit start
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/effect/MobEffect.java
|
||||
+++ b/net/minecraft/world/effect/MobEffect.java
|
||||
@@ -76,6 +_,7 @@
|
||||
@@ -86,6 +_,7 @@
|
||||
public void applyInstantenousEffect(
|
||||
ServerLevel level, @Nullable Entity source, @Nullable Entity indirectSource, LivingEntity entity, int amplifier, double health
|
||||
) {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
--- a/net/minecraft/world/effect/MobEffectInstance.java
|
||||
+++ b/net/minecraft/world/effect/MobEffectInstance.java
|
||||
@@ -216,6 +_,7 @@
|
||||
@@ -219,7 +_,7 @@
|
||||
return false;
|
||||
} else {
|
||||
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 @@
|
||||
- if (this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier) && !this.effect.value().applyEffectTick(level, entity, this.amplifier)) {
|
||||
+ if (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() && !this.effect.value().applyEffectTick(level, entity, this.amplifier)) { // Paper - Add EntityEffectTickEvent
|
||||
return false;
|
||||
} else {
|
||||
this.tickDownDuration();
|
||||
@@ -415,7 +_,7 @@
|
||||
.apply(instance, MobEffectInstance.Details::create)
|
||||
)
|
||||
);
|
||||
@@ -17,7 +18,7 @@
|
||||
codec -> StreamCodec.composite(
|
||||
ByteBufCodecs.VAR_INT,
|
||||
MobEffectInstance.Details::amplifier,
|
||||
@@ -420,7 +_,7 @@
|
||||
@@ -427,7 +_,7 @@
|
||||
MobEffectInstance.Details::showParticles,
|
||||
ByteBufCodecs.BOOL,
|
||||
MobEffectInstance.Details::showIcon,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@@ -49,7 +_,7 @@
|
||||
if (slime != null) {
|
||||
slime.setSize(2, true);
|
||||
slime.moveTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
|
||||
slime.snapTo(x, y, z, level.getRandom().nextFloat() * 360.0F, 0.0F);
|
||||
- level.addFreshEntity(slime);
|
||||
+ level.addFreshEntity(slime, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.POTION_EFFECT); // CraftBukkit
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user