bouquet o' patches

This commit is contained in:
Jake Potrebic 2022-06-07 23:25:32 -07:00
parent 2304bb3d6f
commit feca8d248c
No known key found for this signature in database
GPG key ID: ECE0B3C133C016C5
37 changed files with 112 additions and 103 deletions

View file

@ -1,92 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sun, 17 May 2020 23:47:33 -0700
Subject: [PATCH] Fix for large move vectors crashing server
Check movement distance also based on current position.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 3c4c6edc06e992543f7f1b190d662eb326550034..1d5edba8fa2da4c8c8075bd7c165062970353830 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -509,9 +509,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) {
ServerLevel worldserver = this.player.getLevel();
- double d0 = entity.getX();
- double d1 = entity.getY();
- double d2 = entity.getZ();
+ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER
+ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER
+ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER
double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); final double toX = d3; // Paper - OBFHELPER
double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); final double toY = d4; // Paper - OBFHELPER
double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); final double toZ = d5; // Paper - OBFHELPER
@@ -521,8 +521,19 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
double d7 = d4 - this.vehicleFirstGoodY;
double d8 = d5 - this.vehicleFirstGoodZ;
double d9 = entity.getDeltaMovement().lengthSqr();
- double d10 = d6 * d6 + d7 * d7 + d8 * d8;
-
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - fromX;
+ double currDeltaY = toY - fromY;
+ double currDeltaZ = toZ - fromZ;
+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d3 - this.vehicleLastGoodX;
+ double otherFieldY = d4 - this.vehicleLastGoodY - 1.0E-6D;
+ double otherFieldZ = d5 - this.vehicleLastGoodZ;
+ d10 = Math.max(d10, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
// CraftBukkit start - handle custom speeds and skipped ticks
this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
@@ -568,9 +579,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
- d6 = d3 - this.vehicleLastGoodX;
- d7 = d4 - this.vehicleLastGoodY - 1.0E-6D;
- d8 = d5 - this.vehicleLastGoodZ;
+ d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
+ d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag1 = entity.verticalCollisionBelow;
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
@@ -1253,7 +1264,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
double d8 = d1 - this.firstGoodY;
double d9 = d2 - this.firstGoodZ;
double d10 = this.player.getDeltaMovement().lengthSqr();
- double d11 = d7 * d7 + d8 * d8 + d9 * d9;
+ // Paper start - fix large move vectors killing the server
+ double currDeltaX = toX - prevX;
+ double currDeltaY = toY - prevY;
+ double currDeltaZ = toZ - prevZ;
+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1);
+ // Paper end - fix large move vectors killing the server
+ // Paper start - fix large move vectors killing the server
+ double otherFieldX = d0 - this.lastGoodX;
+ double otherFieldY = d1 - this.lastGoodY;
+ double otherFieldZ = d2 - this.lastGoodZ;
+ d11 = Math.max(d11, (otherFieldX * otherFieldX + otherFieldY * otherFieldY + otherFieldZ * otherFieldZ) - 1);
+ // Paper end - fix large move vectors killing the server
if (this.player.isSleeping()) {
if (d11 > 1.0D) {
@@ -1305,9 +1327,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
AABB axisalignedbb = this.player.getBoundingBox();
- d7 = d0 - this.lastGoodX;
- d8 = d1 - this.lastGoodY;
- d9 = d2 - this.lastGoodZ;
+ d7 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d8 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
+ d9 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag = d8 > 0.0D;
if (this.player.isOnGround() && !packet.isOnGround() && flag) {

View file

@ -1,94 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Wed, 3 Jun 2020 11:37:13 -0700
Subject: [PATCH] Optimise getType calls
Remove the map lookup for converting from Block->Bukkit Material
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
index 76133c77e8ebce7c9e5402e3e7cd50b30aa1c2e0..348a91a760bd728f8e732e1a35c86ab75d8fc0f1 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java
@@ -10,6 +10,17 @@ import net.minecraft.world.level.block.state.properties.Property;
public class BlockState extends BlockBehaviour.BlockStateBase {
public static final Codec<BlockState> CODEC = codec(Registry.BLOCK.byNameCodec(), Block::defaultBlockState).stable();
+ // Paper start - optimise getType calls
+ org.bukkit.Material cachedMaterial;
+
+ public final org.bukkit.Material getBukkitMaterial() {
+ if (this.cachedMaterial == null) {
+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock());
+ }
+
+ return this.cachedMaterial;
+ }
+ // Paper end - optimise getType calls
public BlockState(Block block, ImmutableMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
super(block, propertyMap, codec);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
index 8001245c4ba619cd357a194d60fdc2efe186efb3..07fa4e4ae5f2cfb4447a608dc645c0b7b0a217dd 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java
@@ -83,7 +83,7 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
public Material getBlockType(int x, int y, int z) {
this.validateChunkCoordinates(x, y, z);
- return CraftMagicNumbers.getMaterial(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock());
+ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 396fb96abed1e77893d8ee8a15cff18cad804475..2c1efaecf220588d8b74946194bf340871e57004 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -224,7 +224,7 @@ public class CraftBlock implements Block {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.world.getBlockState(position).getBlock());
+ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index 0a755f38fae9dc84440f43113920c5b4c6d8218b..7b9e943b391c061782fccd2b8d705ceec8db50fe 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -166,7 +166,7 @@ public class CraftBlockState implements BlockState {
@Override
public Material getType() {
- return CraftMagicNumbers.getMaterial(this.data.getBlock());
+ return this.data.getBukkitMaterial(); // Paper - optimise getType calls
}
public void setFlag(int flag) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index afc69b0077f180c3e7ace3db11aa0eccc602516f..4cc67caac2be8c75cd60be5ac63c9aefcc6e2c9c 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -44,7 +44,7 @@ public class CraftBlockData implements BlockData {
@Override
public Material getMaterial() {
- return CraftMagicNumbers.getMaterial(this.state.getBlock());
+ return this.state.getBukkitMaterial(); // Paper - optimise getType calls
}
public BlockState getState() {
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
index ee88ff2ee86bbd3ccf3e4a0b2310f020f137ef4f..5e15feb408b8a05ec5ee393a604c8d39a91ff106 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
@@ -96,7 +96,7 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData {
@Override
public Material getType(int x, int y, int z) {
- return CraftMagicNumbers.getMaterial(this.getTypeId(x, y, z).getBlock());
+ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls
}
@Override

View file

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 7 Oct 2019 00:15:37 -0500
Subject: [PATCH] Villager#resetOffers
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
index dddc84e233e9108f2304694e53990d0654225c5b..68bd3bb6fde77a65b5271631f6ef726dc613019b 100644
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
@@ -115,6 +115,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
return this.tradingPlayer != null;
}
+ // Paper start
+ public void resetOffers() {
+ this.offers = new MerchantOffers();
+ this.updateTrades();
+ }
+ // Paper end
+
@Override
public MerchantOffers getOffers() {
if (this.offers == null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
index 1467232779541a9e38420caabf273662f380794c..762354681315e4c74e414bf7d677b5422385161e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java
@@ -70,4 +70,11 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla
public HumanEntity getTrader() {
return this.getMerchant().getTrader();
}
+
+ // Paper start
+ @Override
+ public void resetOffers() {
+ getHandle().resetOffers();
+ }
+ // Paper end
}

View file

@ -1,96 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 6 Jul 2020 20:46:50 -0700
Subject: [PATCH] Improve inlinig for some hot IBlockData methods
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index e5e8de790b1ab546d35ddf48583461c0b8d91acd..471c4600c6663375eb340c190edaee330bf59ef2 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -702,8 +702,14 @@ public abstract class BlockBehaviour {
return this.shapeExceedsCube;
}
// Paper end
+ // Paper start
+ protected boolean isTicking;
+ protected FluidState fluid;
+ // Paper end
public void initCache() {
+ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid()
+ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking()
if (!this.getBlock().hasDynamicShape()) {
this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState());
}
@@ -747,15 +753,15 @@ public abstract class BlockBehaviour {
return this.shapeExceedsCube; // Paper - moved into shape cache init
}
- public boolean useShapeForLightOcclusion() {
+ public final boolean useShapeForLightOcclusion() { // Paper
return this.useShapeForLightOcclusion;
}
- public int getLightEmission() {
+ public final int getLightEmission() { // Paper
return this.lightEmission;
}
- public boolean isAir() {
+ public final boolean isAir() { // Paper
return this.isAir;
}
@@ -829,7 +835,7 @@ public abstract class BlockBehaviour {
}
}
- public boolean canOcclude() {
+ public final boolean canOcclude() { // Paper
return this.canOcclude;
}
@@ -1030,12 +1036,12 @@ public abstract class BlockBehaviour {
return this.getBlock() == block;
}
- public FluidState getFluidState() {
- return this.getBlock().getFluidState(this.asState());
+ public final FluidState getFluidState() { // Paper
+ return this.fluid; // Paper - moved into init
}
- public boolean isRandomlyTicking() {
- return this.getBlock().isRandomlyTicking(this.asState());
+ public final boolean isRandomlyTicking() { // Paper
+ return this.isTicking; // Paper - moved into init
}
public long getSeed(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java
index 2cad3a8ada797e0e8f3c24431eeca5b91740b009..3c3c873035908294a24c1e4f80d65f980c0f3db4 100644
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
@@ -26,8 +26,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
public static final int AMOUNT_MAX = 9;
public static final int AMOUNT_FULL = 8;
+ // Paper start
+ protected final boolean isEmpty;
+ // Paper end
public FluidState(Fluid fluid, ImmutableMap<Property<?>, Comparable<?>> propertiesMap, MapCodec<FluidState> codec) {
super(fluid, propertiesMap, codec);
+ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty()
}
public Fluid getType() {
@@ -43,7 +47,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isEmpty() {
- return this.getType().isEmpty();
+ return this.isEmpty; // Paper - moved into constructor
}
public float getHeight(BlockGetter world, BlockPos pos) {

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Fri, 7 Aug 2020 04:27:56 -0700
Subject: [PATCH] Retain block place order when capturing blockstates
Fixes twisted vines not connecting properly when grown via
bonemeal by a player.
In general, look at making this logic more robust (i.e properly handling
cases where a captured entry is overriden) - but for now this will do.
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 4095b3ebacb8a55744fa99fea7e08d31e42d8b47..7d7d6ac3ae38eda0aed9f52059fccd3970718890 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -149,7 +149,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
- public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>();
+ public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper
public List<ItemEntity> captureDrops;
public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
// Paper start

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sat, 25 Apr 2020 17:10:55 -0700
Subject: [PATCH] Reduce blockpos allocation from pathfinding
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index 2d42df635b1ce8d975278fb36f00fe9b8b8f060f..c7926d45c32a739b32d2b97b1ed2f8b89fb18620 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -475,7 +475,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
return BlockPathTypes.DANGER_FIRE;
}
- if (world.getFluidState(pos).is(FluidTags.WATER)) {
+ if (blockState.getFluidState().is(FluidTags.WATER)) {
return BlockPathTypes.WATER_BORDER;
}
} // Paper
@@ -506,7 +506,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
} else if (blockState.is(Blocks.COCOA)) {
return BlockPathTypes.COCOA;
} else {
- FluidState fluidState = world.getFluidState(pos);
+ FluidState fluidState = blockState.getFluidState(); // Paper - remove another get type call
if (fluidState.is(FluidTags.LAVA)) {
return BlockPathTypes.LAVA;
} else if (isBurningBlock(blockState)) {

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 3 Oct 2020 20:32:25 -0500
Subject: [PATCH] Fix item locations dropped from campfires
Fixes #4259 by not flooring the blockposition among other weirdness
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
index a365b60830c0e541b9a62fe2db06b8889c803fad..02cdd957e7f79f6c00ee015a0d382def8aa2aead 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
@@ -70,7 +70,11 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
result = blockCookEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result);
// CraftBukkit end
- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1);
+ // Paper start
+ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10));
+ droppedItem.setDeltaMovement(world.random.nextGaussian() * 0.05D, world.random.nextGaussian() * 0.05D + 0.2D, world.random.nextGaussian() * 0.05D);
+ world.addFreshEntity(droppedItem);
+ // Paper end
campfire.items.set(i, ItemStack.EMPTY);
world.sendBlockUpdated(pos, state, state, 3);
}

View file

@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trigary <trigary0@gmail.com>
Date: Tue, 14 Apr 2020 12:05:22 +0200
Subject: [PATCH] Player elytra boost API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0d771219023ecbe6ebc3729009eebb9a4da1e865..52e5b8561dd07078933beccfb95c5fdaca2e6126 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -595,6 +595,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
throw new RuntimeException("Unknown settings type");
}
+
+ @Override
+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) {
+ Validate.isTrue(isGliding(), "Player must be gliding");
+ Validate.isTrue(firework != null, "firework == null");
+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET");
+
+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework);
+ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle();
+ net.minecraft.world.entity.projectile.FireworkRocketEntity entity = new net.minecraft.world.entity.projectile.FireworkRocketEntity(world, item, getHandle());
+ return world.addFreshEntity(entity)
+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity()
+ : null;
+ }
// Paper end
@Override

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: giacomo <32515303+giacomozama@users.noreply.github.com>
Date: Sat, 10 Oct 2020 12:15:33 +0200
Subject: [PATCH] Fixed TileEntityBell memory leak
TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities.
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
index 4353ad2f67556feaa0fdd34e8e907b17ab697565..feaad48e9bbc1e658324ef9e1e7e73aca0b3bf48 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java
@@ -61,6 +61,11 @@ public class BellBlockEntity extends BlockEntity {
if (blockEntity.ticks >= 50) {
blockEntity.shaking = false;
+ // Paper start
+ if (!blockEntity.resonating) {
+ blockEntity.nearbyEntities.clear();
+ }
+ // Paper end
blockEntity.ticks = 0;
}
@@ -74,6 +79,7 @@ public class BellBlockEntity extends BlockEntity {
++blockEntity.resonationTicks;
} else {
bellEffect.run(world, pos, blockEntity.nearbyEntities);
+ blockEntity.nearbyEntities.clear(); // Paper
blockEntity.resonating = false;
}
}
@@ -116,6 +122,7 @@ public class BellBlockEntity extends BlockEntity {
}
}
+ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper
}
private static boolean areRaidersNearby(BlockPos pos, List<LivingEntity> hearingEntities) {

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Toon Schoenmakers <nighteyes1993@gmail.com>
Date: Fri, 23 Oct 2020 15:01:44 +0200
Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing
loot
This can realistically only happen if there's custom loot active on fishing
which can return 0 items. This would disconnect the player who's fishing.
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
index ce43f33ffd8726d3fb592348ac1b10f37645eb0e..3789a0db398766f0fbc9e5ac5bf4228a0a0dac88 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -494,9 +494,15 @@ public class FishingHook extends Projectile {
while (iterator.hasNext()) {
ItemStack itemstack1 = (ItemStack) iterator.next();
- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1);
+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty
+ // if the item stack is empty we instead just have our entityitem as null
+ ItemEntity entityitem = null;
+ if (!itemstack1.isEmpty()) {
+ entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), itemstack1);
+ }
+ // Paper end
// CraftBukkit start
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null
playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1);
this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent);
@@ -509,8 +515,12 @@ public class FishingHook extends Projectile {
double d2 = entityhuman.getZ() - this.getZ();
double d3 = 0.1D;
- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D);
- this.level.addFreshEntity(entityitem);
+ // Paper start, entity item can be null, so we need to check against this
+ if (entityitem != null) {
+ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D);
+ this.level.addFreshEntity(entityitem);
+ }
+ // Paper end
// CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
if (playerFishEvent.getExpToDrop() > 0) {
entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: oxygencraft <21054297+oxygencraft@users.noreply.github.com>
Date: Sun, 25 Oct 2020 18:34:50 +1100
Subject: [PATCH] Add getOfflinePlayerIfCached(String)
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index ce09a46ed430a80471af48b7a8ca1bf7726395c9..a4e34932e8fadf834545db6533219ecf2bf52921 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1800,6 +1800,28 @@ public final class CraftServer implements Server {
return result;
}
+ // Paper start
+ @Override
+ @Nullable
+ public OfflinePlayer getOfflinePlayerIfCached(String name) {
+ Validate.notNull(name, "Name cannot be null");
+ Validate.notEmpty(name, "Name cannot be empty");
+
+ OfflinePlayer result = getPlayerExact(name);
+ if (result == null) {
+ GameProfile profile = console.getProfileCache().getProfileIfCached(name);
+
+ if (profile != null) {
+ result = getOfflinePlayer(profile);
+ }
+ } else {
+ offlinePlayers.remove(result.getUniqueId());
+ }
+
+ return result;
+ }
+ // Paper end
+
@Override
public OfflinePlayer getOfflinePlayer(UUID id) {
Validate.notNull(id, "UUID cannot be null");

View file

@ -1,154 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Mon, 9 Nov 2020 20:44:51 +0100
Subject: [PATCH] Add ignore discounts API
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index f7b8804394ad55e3f6c7c8c3a8f0fe7894385c90..089fb4640cb4e74d7cc90088a8772743d5cbe0c4 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -489,6 +489,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
+ if (merchantrecipe.ignoreDiscounts) continue; // Paper
merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier()));
}
@@ -501,6 +502,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator1.hasNext()) {
MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next();
+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper
double d0 = 0.3D + 0.0625D * (double) j;
int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount());
diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
index f3cf16ce1e1d6c8f76ca5823f532925253ae64aa..c9cb0717c2793acd5b5870a6cc4d672d69a40026 100644
--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
@@ -19,6 +19,7 @@ public class MerchantOffer {
public int demand; // PAIL private -> public
public float priceMultiplier;
public int xp;
+ public boolean ignoreDiscounts; // Paper
// CraftBukkit start
private CraftMerchantRecipe bukkitHandle;
@@ -31,7 +32,15 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) {
- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand);
+ // Paper start - add ignoreDiscounts param
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand, false, bukkit);
+ }
+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) {
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, ignoreDiscounts, bukkit);
+ }
+ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) {
+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand, ignoreDiscounts);
+ // Paper end
this.bukkitHandle = bukkit;
}
// CraftBukkit end
@@ -63,6 +72,7 @@ public class MerchantOffer {
this.specialPriceDiff = nbt.getInt("specialPrice");
this.demand = nbt.getInt("demand");
+ this.ignoreDiscounts = nbt.getBoolean("Paper.IgnoreDiscounts"); // Paper
}
public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) {
@@ -74,10 +84,19 @@ public class MerchantOffer {
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier) {
- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0);
+ // Paper start - add ignoreDiscounts param
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0, ignoreDiscounts);
}
public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) {
+ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, demandBonus, false);
+ }
+ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus, boolean ignoreDiscounts) {
+ this.ignoreDiscounts = ignoreDiscounts;
+ // Paper end
this.rewardExp = true;
this.xp = 1;
this.baseCostA = firstBuyItem;
@@ -193,6 +212,7 @@ public class MerchantOffer {
nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier);
nbttagcompound.putInt("specialPrice", this.specialPriceDiff);
nbttagcompound.putInt("demand", this.demand);
+ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper
return nbttagcompound;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
index 07462b77107541aed2e29d04da33831ac113b450..0f038f6152c90e707cb633dffcab0a1c5b99d260 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java
@@ -18,11 +18,19 @@ public class CraftMerchantRecipe extends MerchantRecipe {
}
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) {
- this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0);
+ // Paper start - add ignoreDiscounts param
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) {
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, 0, 0, ignoreDiscounts);
}
public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice) {
- super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice);
+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, false);
+ }
+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, int demand, int specialPrice, boolean ignoreDiscounts) {
+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, demand, specialPrice, ignoreDiscounts);
+ // Paper end
this.handle = new net.minecraft.world.item.trading.MerchantOffer(
net.minecraft.world.item.ItemStack.EMPTY,
net.minecraft.world.item.ItemStack.EMPTY,
@@ -32,6 +40,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
experience,
priceMultiplier,
demand,
+ ignoreDiscounts, // Paper - add ignoreDiscounts param
this
);
this.setSpecialPrice(specialPrice);
@@ -108,6 +117,18 @@ public class CraftMerchantRecipe extends MerchantRecipe {
handle.priceMultiplier = priceMultiplier;
}
+ // Paper start
+ @Override
+ public boolean shouldIgnoreDiscounts() {
+ return this.handle.ignoreDiscounts;
+ }
+
+ @Override
+ public void setIgnoreDiscounts(boolean ignoreDiscounts) {
+ this.handle.ignoreDiscounts = ignoreDiscounts;
+ }
+ // Paper end
+
public net.minecraft.world.item.trading.MerchantOffer toMinecraft() {
List<ItemStack> ingredients = getIngredients();
Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients");
@@ -122,7 +143,7 @@ public class CraftMerchantRecipe extends MerchantRecipe {
if (recipe instanceof CraftMerchantRecipe) {
return (CraftMerchantRecipe) recipe;
} else {
- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier());
+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts
craft.setIngredients(recipe.getIngredients());
return craft;

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Wed, 30 Sep 2020 22:49:14 +0200
Subject: [PATCH] Toggle for removing existing dragon
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 34754f8d3cc03a93d148d026780eacc7dc0a20e0..6d89bc4804dc0b23ab86b93a6ad030e1e633d61c 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -107,6 +107,14 @@ public class PaperWorldConfig {
}
}
+ public boolean shouldRemoveDragon = false;
+ private void shouldRemoveDragon() {
+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon);
+ if (shouldRemoveDragon) {
+ log("The Ender Dragon will be removed if she already exists without a portal.");
+ }
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index b1a0654ba01c265385db877d528c1aa2103b2eb0..f59de70c4854b10ac39874838db33cdf784a45a1 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -216,7 +216,7 @@ public class EndDragonFight {
this.dragonUUID = enderDragon.getUUID();
LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon);
this.dragonKilled = false;
- if (!bl) {
+ if (!bl && this.level.paperConfig.shouldRemoveDragon) {
LOGGER.info("But we didn't have a portal, let's remove it.");
enderDragon.discard();
this.dragonUUID = null;

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Sat, 31 Oct 2020 11:49:01 -0700
Subject: [PATCH] Fix client lag on advancement loading
When new advancements are added via the UnsafeValues#loadAdvancement
API, it triggers a full datapack reload when this is not necessary. The
advancement is already loaded directly into the advancement registry,
and the point of saving the advancement to the Bukkit datapack seems to
be for persistence. By removing the call to reload datapacks when an
advancement is loaded, the client no longer completely freezes up when
adding a new advancement.
To ensure the client still receives the updated advancement data, we
manually reload the advancement data for all players, which
normally takes place as a part of the datapack reloading.
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index b2ead915b12830c68a21ae994f0c8b728431013f..5540c5a881a9d34a8c50d6b6f0694303c76aa610 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -340,7 +340,13 @@ public final class CraftMagicNumbers implements UnsafeValues {
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
}
- MinecraftServer.getServer().getPlayerList().reloadResources();
+ // Paper start
+ //MinecraftServer.getServer().getPlayerList().reload();
+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> {
+ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements());
+ player.getAdvancements().flushDirty(player);
+ });
+ // Paper end
return bukkit;
}

View file

@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alfie Smith <alfie@alfiesmith.net>
Date: Sat, 7 Nov 2020 01:20:33 +0000
Subject: [PATCH] Item no age & no player pickup
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index 30c954efba587d69ff55df509339f03e7d5a476e..1d90219c3a0e86786a9497d4c078c2d4077ab6cd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -10,6 +10,12 @@ import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
public class CraftItem extends CraftEntity implements Item {
+
+ // Paper start
+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE;
+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE;
+ // Paper end
+
private final ItemEntity item;
public CraftItem(CraftServer server, Entity entity, ItemEntity item) {
@@ -76,6 +82,26 @@ public class CraftItem extends CraftEntity implements Item {
public void setCanMobPickup(boolean canMobPickup) {
item.canMobPickup = canMobPickup;
}
+
+ @Override
+ public boolean canPlayerPickup() {
+ return item.pickupDelay != NO_PICKUP_TIME;
+ }
+
+ @Override
+ public void setCanPlayerPickup(boolean canPlayerPickup) {
+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME;
+ }
+
+ @Override
+ public boolean willAge() {
+ return item.age != NO_AGE_TIME;
+ }
+
+ @Override
+ public void setWillAge(boolean willAge) {
+ item.age = willAge ? 0 : NO_AGE_TIME;
+ }
// Paper End
@Override

View file

@ -1,130 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 4 Aug 2020 22:24:15 +0200
Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections
1.17 Update: Please do this k thx bb
I utilized the IDE to convert streams to non streams code, so shouldn't
be any risk of behavior change. Only did minor optimization of the
generated code set to remove unnecessary things.
I expect us to just drop this patch on next major update and re-apply
it with the IDE again and re-apply the collections optimization.
Optimize collection by creating a list instead of a set of the key and value.
This lets us get faster foreach iteration, as well as avoids map lookups on
the values when needed.
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
index 118cc040f156b96a2b6357ad8817808823595629..3dc896a7ded8d5d109100a393c8299e308954d99 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -35,27 +35,31 @@ public class PathFinder {
this.openSet.clear();
this.nodeEvaluator.prepare(world, mob);
Node node = this.nodeEvaluator.getStart();
- Map<Target, BlockPos> map = positions.stream().collect(Collectors.toMap((pos) -> {
- return this.nodeEvaluator.getGoal((double)pos.getX(), (double)pos.getY(), (double)pos.getZ());
- }, Function.identity()));
+ // Paper start - remove streams - and optimize collection
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
+ for (BlockPos blockPos : positions) {
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(blockPos.getX(), blockPos.getY(), blockPos.getZ()), blockPos));
+ }
+ // Paper end
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
this.nodeEvaluator.done();
return path;
}
@Nullable
- private Path findPath(ProfilerFiller profiler, Node startNode, Map<Target, BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
+ // Paper start - optimize collection
+ private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
profiler.push("find_path");
profiler.markForCharting(MetricCategory.PATH_FINDING);
- Set<Target> set = positions.keySet();
+ //Set<Target> set = positions.keySet();
startNode.g = 0.0F;
- startNode.h = this.getBestH(startNode, set);
+ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection
startNode.f = startNode.h;
this.openSet.clear();
this.openSet.insert(startNode);
- Set<Node> set2 = ImmutableSet.of();
+ //Set<Node> set2 = ImmutableSet.of(); // Paper - unused - diff on change
int i = 0;
- Set<Target> set3 = Sets.newHashSetWithExpectedSize(set.size());
+ List<Map.Entry<Target, BlockPos>> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection
int j = (int)((float)this.maxVisitedNodes * rangeMultiplier);
while(!this.openSet.isEmpty()) {
@@ -67,14 +71,18 @@ public class PathFinder {
Node node = this.openSet.pop();
node.closed = true;
- for(Target target : set) {
+ // Paper start - optimize collection
+ for(int i1 = 0; i1 < positions.size(); i1++) {
+ final Map.Entry<Target, BlockPos> entry = positions.get(i1);
+ Target target = entry.getKey();
if (node.distanceManhattan(target) <= (float)distance) {
target.setReached();
- set3.add(target);
+ entryList.add(entry);
+ // Paper end
}
}
- if (!set3.isEmpty()) {
+ if (!entryList.isEmpty()) { // Paper - rename variable
break;
}
@@ -89,7 +97,7 @@ public class PathFinder {
if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) {
node2.cameFrom = node;
node2.g = g;
- node2.h = this.getBestH(node2, set) * 1.5F;
+ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set
if (node2.inOpenSet()) {
this.openSet.changeCost(node2, node2.g + node2.h);
} else {
@@ -101,19 +109,27 @@ public class PathFinder {
}
}
- Optional<Path> optional = !set3.isEmpty() ? set3.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), true);
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> {
- return this.reconstructPath(target.getBestNode(), positions.get(target), false);
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
- profiler.pop();
- return !optional.isPresent() ? null : optional.get();
+ // Paper start - remove streams - and optimize collection
+ Path best = null;
+ boolean entryListIsEmpty = entryList.isEmpty();
+ Comparator<Path> comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount)
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
+ for (Map.Entry<Target, BlockPos> entry : entryListIsEmpty ? positions : entryList) {
+ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty);
+ if (best == null || comparator.compare(path, best) < 0)
+ best = path;
+ }
+ return best;
+ // Paper end
}
- private float getBestH(Node node, Set<Target> targets) {
+ private float getBestH(Node node, List<Map.Entry<Target, BlockPos>> targets) { // Paper - optimize collection - Set<Target> -> List<Map.Entry<Target, BlockPos>>
float f = Float.MAX_VALUE;
- for(Target target : targets) {
+ // Paper start - optimize collection
+ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) {
+ final Target target = targets.get(i).getKey();
+ // Paper end
float g = node.distanceTo(target);
target.updateBest(g, node);
f = Math.min(g, f);

View file

@ -1,131 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 24 Jun 2020 12:39:08 -0600
Subject: [PATCH] Beacon API - custom effect ranges
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 4b7da0df927f669845c7d4c9b4a0acfab8efe657..82976b3675f581a9f3ccb9e23048bd44864203f8 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -77,6 +77,26 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
}
// CraftBukkit end
+ // Paper start - add field/methods for custom range
+ private final String PAPER_RANGE_TAG = "Paper.Range";
+ private double effectRange = -1;
+
+ public double getEffectRange() {
+ if (this.effectRange < 0) {
+ return this.levels * 10 + 10;
+ } else {
+ return effectRange;
+ }
+ }
+
+ public void setEffectRange(double range) {
+ this.effectRange = range;
+ }
+
+ public void resetEffectRange() {
+ this.effectRange = -1;
+ }
+ // Paper end
public BeaconBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.BEACON, pos, state);
@@ -180,7 +200,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
- BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
+ BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
}
@@ -266,8 +286,13 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
public static List getHumansInRange(Level world, BlockPos blockposition, int i) {
+ // Paper start
+ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null);
+ }
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
{
- double d0 = (double) (i * 10 + 10);
+ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10);// Paper - custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
@@ -308,12 +333,17 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect) {
+ // Paper start
+ BeaconBlockEntity.applyEffects(world, pos, beaconLevel, primaryEffect, secondaryEffect, null);
+ }
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable MobEffect primaryEffect, @Nullable MobEffect secondaryEffect, @Nullable BeaconBlockEntity blockEntity) {
+ // Paper end
if (!world.isClientSide && primaryEffect != null) {
double d0 = (double) (beaconLevel * 10 + 10);
byte b0 = BeaconBlockEntity.getAmplification(beaconLevel, primaryEffect, secondaryEffect);
int j = BeaconBlockEntity.getLevel(beaconLevel);
- List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel);
+ List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel, blockEntity); // Paper
BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
@@ -363,6 +393,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
this.lockKey = LockCode.fromTag(nbt);
+ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper
}
@Override
@@ -376,6 +407,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider {
}
this.lockKey.addToTag(nbt);
+ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper
}
public void setCustomName(@Nullable Component customName) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
index c186a44b927188ed222f8b2f8f76aaef35d9c654..c47e613cae3d9252a8364ccc4d717e410bb0fc0c 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
@@ -29,7 +29,7 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
if (tileEntity instanceof BeaconBlockEntity) {
BeaconBlockEntity beacon = (BeaconBlockEntity) tileEntity;
- Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels);
+ Collection<Player> nms = BeaconBlockEntity.getHumansInRange(beacon.getLevel(), beacon.getBlockPos(), beacon.levels, beacon); // Paper
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
for (Player human : nms) {
@@ -106,4 +106,21 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
public void setLock(String key) {
this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key);
}
+
+ // Paper start
+ @Override
+ public double getEffectRange() {
+ return this.getSnapshot().getEffectRange();
+ }
+
+ @Override
+ public void setEffectRange(double range) {
+ this.getSnapshot().setEffectRange(range);
+ }
+
+ @Override
+ public void resetEffectRange() {
+ this.getSnapshot().resetEffectRange();
+ }
+ // Paper end
}

View file

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 14 Nov 2020 16:19:52 +0100
Subject: [PATCH] Add API for quit reason
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 1c63947958d202d00593e2b76d113c8b327706d7..932b494ea2a5e849b233c73bd2472d5c85f5ba52 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -152,12 +152,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.handlingFault = true;
if (this.channel.isOpen()) {
+ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper
if (throwable instanceof TimeoutException) {
Connection.LOGGER.debug("Timeout", throwable);
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper
this.disconnect(new TranslatableComponent("disconnect.timeout"));
} else {
TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable});
+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper
if (flag) {
Connection.LOGGER.debug("Failed to sent packet", throwable);
ConnectionProtocol enumprotocol = this.getCurrentProtocol();
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index c363b5f48253cd77c6b986b85f068a38df5319b8..8003ede966f760d660575c56d6f949dda900cf21 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -257,6 +257,7 @@ public class ServerPlayer extends Player {
public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1d5edba8fa2da4c8c8075bd7c165062970353830..c1a21932f54b86a9824bf510d9a2a07aa058457b 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -442,6 +442,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure
// CraftBukkit end
+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper
this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> {
this.connection.disconnect(ichatbasecomponent);
});
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index f9ef6e64b95f90d69a897dd996a587749776350d..8443938a2aa6e6fdbba1f9bcf4e5c5afd883140e 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -600,7 +600,7 @@ public abstract class PlayerList {
entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper
}
- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())));
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason
if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());

View file

@ -1,111 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Thu, 20 Aug 2020 11:20:12 -0700
Subject: [PATCH] Add Wandering Trader spawn rate config options
Adds config options for modifying the spawn rates of Wandering Traders.
These values are all easy to understand and configure after a quick read of this
page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning
Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values
in IWorldServerData are removed as they were only used in certain places, with hardcoded
values used in other places.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 6d89bc4804dc0b23ab86b93a6ad030e1e633d61c..9147b408b35b7d15ced3749e34706087d2cdffd8 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -115,6 +115,19 @@ public class PaperWorldConfig {
}
}
+ public int wanderingTraderSpawnMinuteTicks = 1200;
+ public int wanderingTraderSpawnDayTicks = 24000;
+ public int wanderingTraderSpawnChanceFailureIncrement = 25;
+ public int wanderingTraderSpawnChanceMin = 25;
+ public int wanderingTraderSpawnChanceMax = 75;
+ private void wanderingTraderSettings() {
+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks);
+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks);
+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement);
+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin);
+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
index 7215501f554f88c49fa35a063743caa8af46369c..0eddd793fa590a68bd094d417ffb90941532522c 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
@@ -43,43 +43,53 @@ public class WanderingTraderSpawner implements CustomSpawner {
public WanderingTraderSpawner(ServerLevelData properties) {
this.serverLevelData = properties;
- this.tickDelay = 1200;
- this.spawnDelay = properties.getWanderingTraderSpawnDelay();
- this.spawnChance = properties.getWanderingTraderSpawnChance();
- if (this.spawnDelay == 0 && this.spawnChance == 0) {
- this.spawnDelay = 24000;
- properties.setWanderingTraderSpawnDelay(this.spawnDelay);
- this.spawnChance = 25;
- properties.setWanderingTraderSpawnChance(this.spawnChance);
- }
+ // Paper start
+ this.tickDelay = Integer.MIN_VALUE;
+ //this.spawnDelay = properties.getWanderingTraderSpawnDelay(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //this.spawnChance = properties.getWanderingTraderSpawnChance(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value
+ //if (this.spawnDelay == 0 && this.spawnChance == 0) {
+ // this.spawnDelay = 24000;
+ // properties.setWanderingTraderSpawnDelay(this.spawnDelay);
+ // this.spawnChance = 25;
+ // properties.setWanderingTraderSpawnChance(this.spawnChance);
+ //}
+ // Paper end
}
@Override
public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) {
+ // Paper start
+ if (this.tickDelay == Integer.MIN_VALUE) {
+ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks;
+ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin;
+ }
if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) {
return 0;
- } else if (--this.tickDelay > 0) {
+ } else if (this.tickDelay - 1 > 0) {
+ this.tickDelay = this.tickDelay - 1;
return 0;
} else {
- this.tickDelay = 1200;
- this.spawnDelay -= 1200;
- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay);
+ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ this.spawnDelay = this.spawnDelay - world.paperConfig.wanderingTraderSpawnMinuteTicks;
+ //this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
if (this.spawnDelay > 0) {
return 0;
} else {
- this.spawnDelay = 24000;
+ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks;
if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
return 0;
} else {
int i = this.spawnChance;
- this.spawnChance = Mth.clamp(this.spawnChance + 25, (int) 25, (int) 75);
- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance);
+ this.spawnChance = Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax);
+ //this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways
if (this.random.nextInt(100) > i) {
return 0;
} else if (this.spawn(world)) {
- this.spawnChance = 25;
+ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin;
+ // Paper end
return 1;
} else {
return 0;

View file

@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
Date: Tue, 3 Nov 2020 23:48:05 -0600
Subject: [PATCH] Significantly improve performance of the end generation
This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement.
Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric)
Co-authored-by: Gegy <gegy1000@gmail.com>
Co-authored-by: Dylan Xaldin <Puremin0rez515@gmail.com>
Co-authored-by: pop4959 <pop4959@gmail.com>
diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java
index 3f9127f93c9720c89b578d36a1bcdb89fc01222a..9004d9d7dcb1466047da62d0a6d01e7b4ac6a216 100644
--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java
+++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java
@@ -29,6 +29,16 @@ public class TheEndBiomeSource extends BiomeSource {
private final Holder<Biome> midlands;
private final Holder<Biome> islands;
private final Holder<Biome> barrens;
+ // Paper start
+ private static final class NoiseCache {
+ public long[] keys = new long[8192];
+ public float[] values = new float[8192];
+ public NoiseCache() {
+ java.util.Arrays.fill(keys, Long.MIN_VALUE);
+ }
+ }
+ private static final ThreadLocal<java.util.Map<SimplexNoise, NoiseCache>> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new);
+ // Paper end
public TheEndBiomeSource(Registry<Biome> biomeRegistry, long seed) {
this(seed, biomeRegistry.getOrCreateHolder(Biomes.THE_END), biomeRegistry.getOrCreateHolder(Biomes.END_HIGHLANDS), biomeRegistry.getOrCreateHolder(Biomes.END_MIDLANDS), biomeRegistry.getOrCreateHolder(Biomes.SMALL_END_ISLANDS), biomeRegistry.getOrCreateHolder(Biomes.END_BARRENS));
@@ -87,12 +97,26 @@ public class TheEndBiomeSource extends BiomeSource {
float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow
f = Mth.clamp(f, -100.0F, 80.0F);
+ NoiseCache cache = noiseCache.get().computeIfAbsent(simplexNoise, noiseKey -> new NoiseCache()); // Paper
for(int o = -12; o <= 12; ++o) {
for(int p = -12; p <= 12; ++p) {
long q = (long)(k + o);
long r = (long)(l + p);
- if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) {
- float g = (Mth.abs((float)q) * 3439.0F + Mth.abs((float)r) * 147.0F) % 13.0F + 9.0F;
+ // Paper start - Significantly improve end generation performance by using a noise cache
+ long key = net.minecraft.world.level.ChunkPos.asLong((int) q, (int) r);
+ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191;
+ float g = Float.MIN_VALUE;
+ if (cache.keys[index] == key) {
+ g = cache.values[index];
+ } else {
+ if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) {
+ g = (Mth.abs((float) q) * 3439.0F + Mth.abs((float) r) * 147.0F) % 13.0F + 9.0F;
+ }
+ cache.keys[index] = key;
+ cache.values[index] = g;
+ }
+ if (g != Float.MIN_VALUE) {
+ // Paper end
float h = (float)(m - o * 2);
float s = (float)(n - p * 2);
float t = 100.0F - Mth.sqrt(h * h + s * s) * g;

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
Date: Tue, 17 Nov 2020 19:13:09 +0200
Subject: [PATCH] Expose world spawn angle
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 8443938a2aa6e6fdbba1f9bcf4e5c5afd883140e..8d5154cad319d7762db696cd9cd2bf8ab69f632e 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -878,7 +878,7 @@ public abstract class PlayerList {
if (location == null) {
worldserver1 = this.server.getLevel(Level.OVERWORLD);
blockposition = entityplayer1.getSpawnPoint(worldserver1);
- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F));
+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle
}
Player respawnPlayer = entityplayer1.getBukkitEntity();

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ineusia <ineusia@yahoo.com>
Date: Mon, 26 Oct 2020 11:48:06 -0500
Subject: [PATCH] Add Destroy Speed API
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 2c1efaecf220588d8b74946194bf340871e57004..653dcec33f83ab490af424faa6ede7df07d41742 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -678,5 +678,26 @@ public class CraftBlock implements Block {
public String translationKey() {
return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this);
}
+
+ @Override
+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) {
+ net.minecraft.world.item.ItemStack nmsItemStack;
+ if (itemStack instanceof CraftItemStack) {
+ nmsItemStack = ((CraftItemStack) itemStack).handle;
+ if (nmsItemStack == null) {
+ nmsItemStack = net.minecraft.world.item.ItemStack.EMPTY;
+ }
+ } else {
+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
+ }
+ float speed = nmsItemStack.getDestroySpeed(this.getNMS().getBlock().defaultBlockState());
+ if (speed > 1.0F && considerEnchants) {
+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack);
+ if (enchantLevel > 0) {
+ speed += enchantLevel * enchantLevel + 1;
+ }
+ }
+ return speed;
+ }
// Paper end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Esophose <esophose@gmail.com>
Date: Sat, 3 Oct 2020 18:57:47 -0600
Subject: [PATCH] Fix Player spawnParticle x/y/z precision loss
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 52e5b8561dd07078933beccfb95c5fdaca2e6126..a55dc36244c7a60300c988504d214eef546dfa36 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2257,7 +2257,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
if (data != null && !particle.getDataType().isInstance(data)) {
throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass());
}
- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count);
+ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss
this.getHandle().connection.send(packetplayoutworldparticles);
}

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anrza <andrzejrzeczycki314@gmail.com>
Date: Wed, 15 Jul 2020 12:08:49 +0200
Subject: [PATCH] Add LivingEntity#clearActiveItem
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 537d1a6dcf8add34e8dac8aee2fa50c50ce7e5d0..24ffc967391c9ba175f41396a90007ecdc32f55c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -805,6 +805,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return getHandle().getUseItem().asBukkitMirror();
}
+ // Paper start
+ @Override
+ public void clearActiveItem() {
+ getHandle().stopUsingItem();
+ }
+ // Paper end
+
@Override
public int getItemUseRemainingTime() {
return getHandle().getUseItemRemainingTicks();

View file

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <jahnke.nassim@gmail.com>
Date: Tue, 25 Aug 2020 13:48:33 +0200
Subject: [PATCH] Add PlayerItemCooldownEvent
diff --git a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
index 47283d2a49209839002212e663a503a82ea86587..ce026600b3b5c846d991a0dfe599708caf2a2962 100644
--- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
+++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java
@@ -10,6 +10,16 @@ public class ServerItemCooldowns extends ItemCooldowns {
this.player = player;
}
+ // Paper start
+ @Override
+ public void addCooldown(Item item, int duration) {
+ io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent(this.player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration);
+ if (event.callEvent()) {
+ super.addCooldown(item, event.getCooldown());
+ }
+ }
+ // Paper end
+
@Override
protected void onCooldownStarted(Item item, int duration) {
super.onCooldownStarted(item, duration);

View file

@ -1,49 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <jahnke.nassim@gmail.com>
Date: Sun, 26 Jul 2020 14:44:09 +0200
Subject: [PATCH] More lightning API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
index f7991ff14ef9cda0327b8621bf615b49cffd7ac5..e515e819774bfb31ec03f05a5502921e66f2b0e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
@@ -45,4 +45,38 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike
return this.spigot;
}
// Spigot end
+
+ // Paper start
+ @Override
+ public int getFlashCount() {
+ return getHandle().flashes;
+ }
+
+ @Override
+ public void setFlashCount(int flashes) {
+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!");
+ getHandle().flashes = flashes;
+ }
+
+ @Override
+ public int getLifeTicks() {
+ return getHandle().life;
+ }
+
+ @Override
+ public void setLifeTicks(int lifeTicks) {
+ getHandle().life = lifeTicks;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable org.bukkit.entity.Entity getCausingEntity() {
+ final var cause = this.getHandle().getCause();
+ return cause == null ? null : cause.getBukkitEntity();
+ }
+
+ @Override
+ public void setCausingPlayer(@org.jetbrains.annotations.Nullable org.bukkit.entity.Player causingPlayer) {
+ this.getHandle().setCause(causingPlayer == null ? null : ((CraftPlayer) causingPlayer).getHandle());
+ }
+ // Paper end
}

View file

@ -1,173 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 23 Aug 2020 20:59:00 +0200
Subject: [PATCH] Climbing should not bypass cramming gamerule
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 9147b408b35b7d15ced3749e34706087d2cdffd8..340e610b6af2dab7d916c530d3cce9aac003aa4d 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -128,6 +128,11 @@ public class PaperWorldConfig {
wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax);
}
+ public boolean fixClimbingBypassingCrammingRule = false;
+ private void fixClimbingBypassingCrammingRule() {
+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index f8876446fe73681d0a4ed72759ae4080f85c572a..78dbc89bb247b2765bd2d7d81013d18dfe35539f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1748,6 +1748,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public boolean isPushable() {
+ // Paper start
+ return isCollidable(false);
+ }
+
+ public boolean isCollidable(boolean ignoreClimbing) {
+ // Paper end
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index 22f36cd3df49160f1b6668befdd05c2268edaa49..e39965c2e50bc8ee424ea07819346e0611398e28 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -45,11 +45,17 @@ public final class EntitySelector {
}
public static Predicate<Entity> pushableBy(Entity entity) {
+ // Paper start - ignoreClimbing param
+ return pushable(entity, false);
+ }
+
+ public static Predicate<Entity> pushable(Entity entity, boolean ignoreClimbing) {
+ // Paper end
Team scoreboardteambase = entity.getTeam();
Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule();
return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> {
- if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API
+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable
return false;
} else if (entity.level.isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) {
return false;
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 795b24ff5357a52624abc994bcfcc772ca7f5e7b..f47b278ab6c4d88fabb9b6ff6f2a42c1e45f70a8 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3300,7 +3300,7 @@ public abstract class LivingEntity extends Entity {
return;
}
// Paper end - don't run getEntities if we're not going to use its result
- List<Entity> list = this.level.getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this));
+ List<Entity> list = this.level.getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule
if (!list.isEmpty()) {
// Paper - move up
@@ -3463,9 +3463,16 @@ public abstract class LivingEntity extends Entity {
return !this.isRemoved() && this.collides; // CraftBukkit
}
+ // Paper start
@Override
public boolean isPushable() {
- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit
+ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule);
+ }
+
+ @Override
+ public boolean isCollidable(boolean ignoreClimbing) {
+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit
+ // Paper end
}
// CraftBukkit start - collidable API
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
index f37f9118ff3305d688f55ba978b6fd5f3a428fc7..ed617223942b410fb6f799be7db2001909db67ed 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
@@ -82,7 +82,7 @@ public class Bat extends AmbientCreature {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
index 5f690ffab2a8305ee1229e552ba9d282fcb479a2..eb66cfebce7e8bb9ebce066e5aabff256a8a518d 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
@@ -381,8 +381,8 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
}
@Override
- public boolean isPushable() {
- return super.isPushable(); // CraftBukkit - collidable API
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index e63f55df91d301b18c63ba94dc19966155916b65..cd278a859c87fc89c421378ffab1bd36a45bd65d 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -241,7 +241,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return !this.isVehicle();
}
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index 0d468631b9c260091e732925da43c177ebda892f..e5ef24d92de21c4c0e6a98e06985e52d47bfdce0 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -344,7 +344,7 @@ public class ArmorStand extends LivingEntity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return false;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
index 46ceed03caed9015acfcc45a5afc0d0c9521c9df..110006087af3f87457031dad7756235363af0506 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -147,7 +147,7 @@ public abstract class AbstractMinecart extends Entity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return true;
}
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
index a7f248394d11f0e4a9d5056ffb6fc66cac53cd02..c75e45bcb8cd6da154c7ca1719711622c009f463 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
@@ -157,7 +157,7 @@ public class Boat extends Entity {
}
@Override
- public boolean isPushable() {
+ public boolean isCollidable(boolean ignoreClimbing) { // Paper
return true;
}

View file

@ -1,205 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 16 Nov 2020 12:01:52 -0800
Subject: [PATCH] Added missing default perms for commands
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
index ca30f9c590f792caa8f1b76d7219e9121d932673..045ebc5533de7486d1975efe9d51ab368969178a 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
@@ -25,12 +25,68 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands);
- DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "seed", "Allows the user to view the seed of the world", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands);
+ // Paper start
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display the ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "jfr", "Allows a user to use the vanilla Java FlightRecorder profiling system", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the player ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon-ip", "Allows the user to remove entries from the ip address ban list", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "perf", "Allows the user to start/stop the vanilla performance metrics capture", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "placefeature", "Allows the user to place features with the command", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item)
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands);
+ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands);
+ // Paper end
DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands);
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e80f8a32c82f89a2f898db1d869daadee735176f
--- /dev/null
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
@@ -0,0 +1,84 @@
+package io.papermc.paper.permissions;
+
+import com.mojang.brigadier.tree.CommandNode;
+import com.mojang.brigadier.tree.RootCommandNode;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.server.Bootstrap;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
+import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions;
+import org.bukkit.permissions.Permission;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.junit.Assert.assertTrue;
+
+public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
+
+ private static PrintStream old;
+ @BeforeClass
+ public static void before() {
+ old = System.out;
+ System.setOut(Bootstrap.STDOUT);
+ }
+
+ @Test
+ public void test() {
+ CraftDefaultPermissions.registerCorePermissions();
+ Set<String> perms = collectMinecraftCommandPerms();
+
+ Commands commands = new Commands(Commands.CommandSelection.DEDICATED);
+ RootCommandNode<CommandSourceStack> root = commands.getDispatcher().getRoot();
+ Set<String> missing = new LinkedHashSet<>();
+ Set<String> foundPerms = new HashSet<>();
+ for (CommandNode<CommandSourceStack> child : root.getChildren()) {
+ final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
+ if (!perms.contains(vanillaPerm)) {
+ missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
+ } else {
+ foundPerms.add(vanillaPerm);
+ }
+ }
+ assertTrue("Commands missing permissions: \n" + String.join("\n", missing), missing.isEmpty());
+ perms.removeAll(foundPerms);
+ assertTrue("Extra permissions not associated with a command: \n" + String.join("\n", perms), perms.isEmpty());
+ }
+
+ private static final List<String> TO_SKIP = List.of(
+ "minecraft.command.selector"
+ );
+
+ private static Set<String> collectMinecraftCommandPerms() {
+ Set<String> perms = new TreeSet<>();
+ for (Permission perm : Bukkit.getPluginManager().getPermissions()) {
+ if (perm.getName().startsWith("minecraft.command.")) {
+ if (TO_SKIP.contains(perm.getName())) {
+ continue;
+ }
+ if (perm.getName().endsWith(".xp")) {
+ perms.add("minecraft.command.experience"); // for the "experience" command, craftbukkit perm is "minecraft.command.xp"
+ continue;
+ }
+ perms.add(perm.getName());
+ }
+ }
+ return perms;
+ }
+
+ @AfterClass
+ public static void after() {
+ if (old != null) {
+ System.setOut(old);
+ }
+ }
+}
diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java
index 2d95215657fffe77165a2fa5f6c8d31ba44a958d..1f3705543353adc6e6d4c4a9dd06032255bf5089 100644
--- a/src/test/java/org/bukkit/support/DummyServer.java
+++ b/src/test/java/org/bukkit/support/DummyServer.java
@@ -97,7 +97,21 @@ public final class DummyServer implements InvocationHandler {
}
}
);
- Bukkit.setServer(Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(new DummyServer()));
+ // Paper start - modeled off of TestServer in the API tests module
+ methods.put(
+ Server.class.getMethod("getPluginManager"),
+ new MethodHandler() {
+ @Override
+ public Object handle(DummyServer server, Object[] args) {
+ return server.pluginManager;
+ }
+ }
+ );
+ DummyServer server = new DummyServer();
+ Server instance = Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(server);
+ Bukkit.setServer(instance);
+ server.pluginManager = new org.bukkit.plugin.SimplePluginManager(instance, new org.bukkit.command.SimpleCommandMap(instance));
+ // Paper end
} catch (Throwable t) {
throw new Error(t);
}
@@ -107,6 +121,7 @@ public final class DummyServer implements InvocationHandler {
private DummyServer() {};
+ private org.bukkit.plugin.PluginManager pluginManager; // Paper
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
MethodHandler handler = DummyServer.methods.get(method);

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JRoy <joshroy126@gmail.com>
Date: Thu, 27 Aug 2020 15:02:48 -0400
Subject: [PATCH] Add PlayerShearBlockEvent
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index e5a544dee741bf0df9b4be8b7cef6fe74938f6a2..e9974415e8f016f50a93a5eea117afe25a6b735d 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -113,7 +113,7 @@ public class BeehiveBlock extends BaseEntityBlock {
}
public static void dropHoneycomb(Level world, BlockPos pos) {
- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3));
+ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - conflict on change, item needs to be set below
}
@Override
@@ -126,8 +126,19 @@ public class BeehiveBlock extends BaseEntityBlock {
Item item = itemstack.getItem();
if (itemstack.is(Items.SHEARS)) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F);
- BeehiveBlock.dropHoneycomb(world, pos);
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) {
+ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop));
+ }
+ // Paper end
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
entityhuman1.broadcastBreakEvent(hand);
});
diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
index 0e8cbe7a465edc31b78b7e47a928435f9c2b6bd9..f998598a34315389dd74b82e4b9c8448f0aae253 100644
--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java
@@ -27,13 +27,24 @@ public class PumpkinBlock extends StemGrownBlock {
ItemStack itemStack = player.getItemInHand(hand);
if (itemStack.is(Items.SHEARS)) {
if (!world.isClientSide) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (hand == InteractionHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
Direction direction = hit.getDirection();
Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction;
world.playSound((Player)null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11);
- ItemEntity itemEntity = new ItemEntity(world, (double)pos.getX() + 0.5D + (double)direction2.getStepX() * 0.65D, (double)pos.getY() + 0.1D, (double)pos.getZ() + 0.5D + (double)direction2.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4));
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) {
+ ItemEntity itemEntity = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) direction2.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) direction2.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item));
+ // Paper end
itemEntity.setDeltaMovement(0.05D * (double)direction2.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02D);
world.addFreshEntity(itemEntity);
+ } // Paper - Add PlayerShearBlockEvent
itemStack.hurtAndBreak(1, player, (playerx) -> {
playerx.broadcastBreakEvent(hand);
});

View file

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 8 Dec 2020 20:14:20 -0600
Subject: [PATCH] Fix curing zombie villager discount exploit
This fixes the exploit used to gain absurd trading discounts with infecting
and curing a villager on repeat by simply resetting the relevant part of
the reputation when it is cured.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 340e610b6af2dab7d916c530d3cce9aac003aa4d..d6cbd9ea2eb70e25a5e37e0bdda2396a99b3342e 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -133,6 +133,11 @@ public class PaperWorldConfig {
fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule);
}
+ public boolean fixCuringZombieVillagerDiscountExploit = true;
+ private void fixCuringExploit() {
+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit);
+ }
+
public short keepLoadedRange;
private void keepLoadedRange() {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 089fb4640cb4e74d7cc90088a8772743d5cbe0c4..268524e256a034520438d5c825e5e419d72d29ce 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -1066,6 +1066,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public void onReputationEventFrom(ReputationEventType interaction, Entity entity) {
if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) {
+ // Paper start - fix MC-181190
+ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) {
+ final GossipContainer.EntityGossips playerReputation = this.getGossips().getReputations().get(entity.getUUID());
+ if (playerReputation != null) {
+ playerReputation.remove(GossipType.MAJOR_POSITIVE);
+ playerReputation.remove(GossipType.MINOR_POSITIVE);
+ }
+ }
+ // Paper end
this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20);
this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25);
} else if (interaction == ReputationEventType.TRADE) {

View file

@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sat, 12 Dec 2020 23:45:28 +0000
Subject: [PATCH] Limit recipe packets
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 4bd335699f5f53b8303a86758a9dedae75bf8464..ccc60a5465efa2b71fc2593d75af62c0b64fe66c 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -366,6 +366,13 @@ public class PaperConfig {
tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit);
}
+ public static int autoRecipeIncrement = 1;
+ public static int autoRecipeLimit = 20;
+ private static void autoRecipieLimiters() {
+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement);
+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit);
+ }
+
public static boolean velocitySupport;
public static boolean velocityOnlineMode;
public static byte[] velocitySecretKey;
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index c1a21932f54b86a9824bf510d9a2a07aa058457b..2a5eb98c6e0f54f098c24ec09c68c3a4dda21aa8 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -230,6 +230,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit start - multithreaded fields
private final AtomicInteger chatSpamTickCount = new AtomicInteger();
private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits
+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit
// CraftBukkit end
private int dropSpamTickCount;
private double firstGoodX;
@@ -374,6 +375,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
// CraftBukkit start
for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ;
if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable
+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper
/* Use thread-safe field access instead
if (this.chatSpamTickCount > 0) {
--this.chatSpamTickCount;
@@ -2847,6 +2849,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
@Override
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
+ // Paper start
+ if (!org.bukkit.Bukkit.isPrimaryThread()) {
+ if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) {
+ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper
+ return;
+ }
+ }
+ // Paper end
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
this.player.resetLastActionTime();
if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) {

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 17 Dec 2020 15:25:49 -0600
Subject: [PATCH] Fix CraftSound backwards compatibility
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
index 266563e72b563fd9db85f17bca710bbe45e8a22d..b2667c5f0794d521766203fea3299f12e21f5c76 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
@@ -26,4 +26,10 @@ public class CraftSound {
public static Sound getBukkit(SoundEvent soundEffect) {
return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.SOUND_EVENT.getKey(soundEffect)));
}
+
+ // Paper start
+ public static String getSound(Sound sound) {
+ return sound.getKey().getKey();
+ }
+ // Paper end
}

View file

@ -1,65 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 8 Dec 2020 20:24:52 -0600
Subject: [PATCH] MC-4: Fix item position desync
This fixes item position desync (MC-4) by running the item coordinates
through the encode/decode methods of the packet that causes the precision
loss, which forces the server to lose the same precision as the client
keeping them in sync.
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index ccc60a5465efa2b71fc2593d75af62c0b64fe66c..1adbceadd5df96e17796561a40eb7b760493440e 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -101,6 +101,11 @@ public class PaperConfig {
trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false);
}
+ public static boolean fixEntityPositionDesync = true;
+ private static void fixEntityPositionDesync() {
+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync);
+ }
+
public static void registerCommands() {
for (Map.Entry<String, Command> entry : commands.entrySet()) {
MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue());
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java
index b30c08bfb8c55161543a4ef09f2e462e0a1fe4ae..ec93f5300cc7d423ec0d292f0f8443f900d72dab 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java
@@ -21,11 +21,11 @@ public abstract class ClientboundMoveEntityPacket implements Packet<ClientGamePa
protected final boolean hasPos;
public static long entityToPacket(double coord) {
- return Mth.lfloor(coord * 4096.0D);
+ return Mth.lfloor(coord * 4096.0D); // Paper - check ItemEntity#setPosRaw on update
}
public static double packetToEntity(long coord) {
- return (double)coord / 4096.0D;
+ return (double)coord / 4096.0D; // Paper - check ItemEntity#setPosRaw on update
}
public Vec3 updateEntityPosition(Vec3 orig) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 78dbc89bb247b2765bd2d7d81013d18dfe35539f..e53d8fe713a4c9920f40bf91d6453d36520b45f7 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3802,6 +3802,16 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
// Paper end
+ // Paper start - fix MC-4
+ if (this instanceof ItemEntity) {
+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) {
+ // encode/decode from PacketPlayOutEntity
+ x = Mth.lfloor(x * 4096.0D) * (1 / 4096.0D);
+ y = Mth.lfloor(y * 4096.0D) * (1 / 4096.0D);
+ z = Mth.lfloor(z * 4096.0D) * (1 / 4096.0D);
+ }
+ }
+ // Paper end - fix MC-4
if (this.position.x != x || this.position.y != y || this.position.z != z) {
this.position = new Vec3(x, y, z);
int i = Mth.floor(x);

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ysl3000 <yannicklamprecht@live.de>
Date: Mon, 5 Oct 2020 21:25:16 +0200
Subject: [PATCH] Player Chunk Load/Unload Events
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 8003ede966f760d660575c56d6f949dda900cf21..8d9cfbc171c51830f5005c6604333c7ff54298d7 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -2113,11 +2113,21 @@ public class ServerPlayer extends Player {
public void trackChunk(ChunkPos chunkPos, Packet<?> chunkDataPacket) {
this.connection.send(chunkDataPacket);
+ // Paper start
+ if(io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkPos.longKey), this.getBukkitEntity()).callEvent();
+ }
+ // Paper end
}
public void untrackChunk(ChunkPos chunkPos) {
if (this.isAlive()) {
this.connection.send(new ClientboundForgetLevelChunkPacket(chunkPos.x, chunkPos.z));
+ // Paper start
+ if(io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){
+ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkPos.longKey), this.getBukkitEntity()).callEvent();
+ }
+ // Paper end
}
}

View file

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 21 Dec 2020 11:01:42 -0500
Subject: [PATCH] Optimize Dynamic#get Missing Keys
get was calling toString() on every NBT object that was ever asked for an optional
key from the object to build a string for the error text.
When done on large NBT objects, this was using a ton of computation time building the
JSON representation of the NBT object.
Now we will just skip the value when 99.9999% of the time the text is never even printed.
diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java
index a75d3db046dc985a03b4b870c91f41de1bd66bad..044facc9de9e8e582d7953d681c0c051578979c3 100644
--- a/src/main/java/com/mojang/serialization/Dynamic.java
+++ b/src/main/java/com/mojang/serialization/Dynamic.java
@@ -17,6 +17,7 @@ import java.util.stream.Stream;
@SuppressWarnings("unused")
public class Dynamic<T> extends DynamicLike<T> {
+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper
private final T value;
public Dynamic(final DynamicOps<T> ops) {
@@ -113,7 +114,7 @@ public class Dynamic<T> extends DynamicLike<T> {
return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> {
final T value = m.get(key);
if (value == null) {
- return DataResult.error("key missing: " + key + " in " + this.value);
+ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper
}
return DataResult.success(new Dynamic<>(ops, value));
}));

View file

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
Date: Sun, 13 Dec 2020 05:32:05 +0200
Subject: [PATCH] Expose LivingEntity hurt direction
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 24ffc967391c9ba175f41396a90007ecdc32f55c..0293d6fd1bb29f75fa1fa1cdfa36b3f679c1bc45 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -850,5 +850,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) {
getHandle().take(((CraftItem) item).getHandle(), quantity);
}
+
+ @Override
+ public float getHurtDirection() {
+ return getHandle().hurtDir;
+ }
+
+ @Override
+ public void setHurtDirection(float hurtDirection) {
+ getHandle().hurtDir = hurtDirection;
+ }
// Paper end
}

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 24 Dec 2020 12:43:39 -0800
Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 9a2f0c109181fc45c7388a2a622c4e6cf63cc771..c5fd069085efa57f99698930640198c6fcaa4bfb 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -263,6 +263,10 @@ public class CraftEventFactory {
return BedEnterResult.TOO_FAR_AWAY;
case NOT_SAFE:
return BedEnterResult.NOT_SAFE;
+ // Paper start
+ case OBSTRUCTED:
+ return BedEnterResult.OBSTRUCTED;
+ // Paper end
default:
return BedEnterResult.OTHER_PROBLEM;
}