mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-15 14:13:56 +01:00
Patched
This commit is contained in:
parent
644fa33eea
commit
a6f4f6e2c9
59 changed files with 97 additions and 516 deletions
|
@ -28,13 +28,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
}
|
||||
// Paper end - allow controlled flushing
|
||||
private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush");
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - packet limiter
|
||||
+ protected final Object PACKET_LIMIT_LOCK = new Object();
|
||||
+ protected final @Nullable io.papermc.paper.util.IntervalledCounter allPacketCounts = io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.isEnabled() ? new io.papermc.paper.util.IntervalledCounter(
|
||||
+ (long)(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.interval() * 1.0e9)
|
||||
+ (long)(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.interval() * 1.0e9)
|
||||
+ ) : null;
|
||||
+ protected final java.util.Map<Class<? extends net.minecraft.network.protocol.Packet<?>>, io.papermc.paper.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>();
|
||||
+
|
||||
|
@ -47,9 +47,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ this.stopReadingPackets = true;
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
|
||||
+
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet<?> packet) {
|
|
@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
|
||||
return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME), world); // Paper - Anti-Xray - Add parameters
|
||||
return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME));
|
||||
}
|
||||
|
||||
+ // Paper start
|
|
@ -14,6 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
public void setItem(ItemStack stack) {
|
||||
- if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) {
|
||||
+ if (true || !stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { // Paper - always allow item changing
|
||||
this.getEntityData().set(Fireball.DATA_ITEM_STACK, (ItemStack) Util.make(stack.copy(), (itemstack1) -> {
|
||||
itemstack1.setCount(1);
|
||||
}));
|
||||
this.getEntityData().set(Fireball.DATA_ITEM_STACK, stack.copyWithCount(1));
|
||||
}
|
||||
|
|
@ -48,8 +48,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
|
||||
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
|
||||
@@ -0,0 +0,0 @@ public final class CraftBlockStates {
|
||||
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
|
||||
@Override
|
||||
|
@ -271,12 +271,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
- register(Material.LECTERN, CraftLectern.class, CraftLectern::new, LecternBlockEntity::new);
|
||||
- register(Material.MOVING_PISTON, CraftMovingPiston.class, CraftMovingPiston::new, PistonMovingBlockEntity::new);
|
||||
- register(Material.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new, SculkCatalystBlockEntity::new);
|
||||
- register(Material.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new, CalibratedSculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new, SculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new, SculkShriekerBlockEntity::new);
|
||||
- register(Material.SMOKER, CraftSmoker.class, CraftSmoker::new, SmokerBlockEntity::new);
|
||||
- register(Material.SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new, SpawnerBlockEntity::new);
|
||||
- register(Material.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new, StructureBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new, SuspiciousSandBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new, BrushableBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_GRAVEL, CraftBrushableBlock.class, CraftBrushableBlock::new, BrushableBlockEntity::new);
|
||||
- register(Material.TRAPPED_CHEST, CraftChest.class, CraftChest::new, TrappedChestBlockEntity::new);
|
||||
+ // Paper start - simplify
|
||||
+ register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
|
||||
|
@ -317,7 +319,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
|
||||
+ register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
|
||||
+ register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
|
||||
+ register(BlockEntityType.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new);
|
||||
+ register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new); // TODO: HANDLE DIFFERENT MATERIALS....
|
||||
+ register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new);
|
||||
+ // Paper end
|
||||
}
|
|
@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
switch (enumitemslot.getType()) {
|
||||
case HAND:
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
((ServerLevel) this.level).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
|
||||
((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
|
||||
}
|
||||
|
||||
+ // Paper start - hide unnecessary item meta
|
|
@ -1214,198 +1214,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
float f2 = this.getBlockSpeedFactor();
|
||||
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply((double) f2, 1.0D, (double) f2));
|
||||
- if (this.level.getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((iblockdata1) -> {
|
||||
- return iblockdata1.is(BlockTags.FIRE) || iblockdata1.is(Blocks.LAVA);
|
||||
- })) {
|
||||
+ // Paper start - remove expensive streams from here
|
||||
+ boolean noneMatch = true;
|
||||
+ AABB fireSearchBox = this.getBoundingBox().deflate(1.0E-6D);
|
||||
+ {
|
||||
+ int minX = Mth.floor(fireSearchBox.minX);
|
||||
+ int minY = Mth.floor(fireSearchBox.minY);
|
||||
+ int minZ = Mth.floor(fireSearchBox.minZ);
|
||||
+ int maxX = Mth.floor(fireSearchBox.maxX);
|
||||
+ int maxY = Mth.floor(fireSearchBox.maxY);
|
||||
+ int maxZ = Mth.floor(fireSearchBox.maxZ);
|
||||
+ fire_search_loop:
|
||||
+ for (int fz = minZ; fz <= maxZ; ++fz) {
|
||||
+ for (int fx = minX; fx <= maxX; ++fx) {
|
||||
+ for (int fy = minY; fy <= maxY; ++fy) {
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)this.level.getChunkIfLoadedImmediately(fx >> 4, fz >> 4);
|
||||
+ if (chunk == null) {
|
||||
+ // Vanilla rets an empty stream if all the chunks are not loaded, so noneMatch will be true
|
||||
+ // even if we're in lava/fire
|
||||
+ noneMatch = true;
|
||||
+ break fire_search_loop;
|
||||
+ }
|
||||
+ if (!noneMatch) {
|
||||
+ // don't do get type, we already know we're in fire - we just need to check the chunks
|
||||
+ // loaded state
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ BlockState type = chunk.getBlockStateFinal(fx, fy, fz);
|
||||
+ if (type.is(BlockTags.FIRE) || type.is(Blocks.LAVA)) {
|
||||
+ noneMatch = false;
|
||||
+ // can't break, we need to retain vanilla behavior by ensuring ALL chunks are loaded
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (noneMatch) {
|
||||
+ // Paper end - remove expensive streams from here
|
||||
if (this.remainingFireTicks <= 0) {
|
||||
this.setRemainingFireTicks(-this.getFireImmuneTicks());
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
private Vec3 collide(Vec3 movement) {
|
||||
- AABB axisalignedbb = this.getBoundingBox();
|
||||
- List<VoxelShape> list = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement));
|
||||
- Vec3 vec3d1 = movement.lengthSqr() == 0.0D ? movement : Entity.collideBoundingBox(this, movement, axisalignedbb, this.level, list);
|
||||
- boolean flag = movement.x != vec3d1.x;
|
||||
- boolean flag1 = movement.y != vec3d1.y;
|
||||
- boolean flag2 = movement.z != vec3d1.z;
|
||||
- boolean flag3 = this.onGround || flag1 && movement.y < 0.0D;
|
||||
-
|
||||
- if (this.maxUpStep() > 0.0F && flag3 && (flag || flag2)) {
|
||||
- Vec3 vec3d2 = Entity.collideBoundingBox(this, new Vec3(movement.x, (double) this.maxUpStep(), movement.z), axisalignedbb, this.level, list);
|
||||
- Vec3 vec3d3 = Entity.collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), axisalignedbb.expandTowards(movement.x, 0.0D, movement.z), this.level, list);
|
||||
-
|
||||
- if (vec3d3.y < (double) this.maxUpStep()) {
|
||||
- Vec3 vec3d4 = Entity.collideBoundingBox(this, new Vec3(movement.x, 0.0D, movement.z), axisalignedbb.move(vec3d3), this.level, list).add(vec3d3);
|
||||
-
|
||||
- if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) {
|
||||
- vec3d2 = vec3d4;
|
||||
+ // Paper start - optimise collisions
|
||||
+ // This is a copy of vanilla's except that it uses strictly AABB math
|
||||
+ if (movement.x == 0.0 && movement.y == 0.0 && movement.z == 0.0) {
|
||||
+ return movement;
|
||||
+ }
|
||||
+
|
||||
+ final Level world = this.level;
|
||||
+ final AABB currBoundingBox = this.getBoundingBox();
|
||||
+
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isEmpty(currBoundingBox)) {
|
||||
+ return movement;
|
||||
+ }
|
||||
+
|
||||
+ final List<AABB> potentialCollisions = io.papermc.paper.util.CachedLists.getTempCollisionList();
|
||||
+ try {
|
||||
+ final double stepHeight = (double)this.maxUpStep();
|
||||
+ final AABB collisionBox;
|
||||
+
|
||||
+ if (movement.x == 0.0 && movement.z == 0.0 && movement.y != 0.0) {
|
||||
+ if (movement.y > 0.0) {
|
||||
+ collisionBox = io.papermc.paper.util.CollisionUtil.cutUpwards(currBoundingBox, movement.y);
|
||||
+ } else {
|
||||
+ collisionBox = io.papermc.paper.util.CollisionUtil.cutDownwards(currBoundingBox, movement.y);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (stepHeight > 0.0 && (this.onGround || (movement.y < 0.0)) && (movement.x != 0.0 || movement.z != 0.0)) {
|
||||
+ // don't bother getting the collisions if we don't need them.
|
||||
+ if (movement.y <= 0.0) {
|
||||
+ collisionBox = io.papermc.paper.util.CollisionUtil.expandUpwards(currBoundingBox.expandTowards(movement.x, movement.y, movement.z), stepHeight);
|
||||
+ } else {
|
||||
+ collisionBox = currBoundingBox.expandTowards(movement.x, Math.max(stepHeight, movement.y), movement.z);
|
||||
+ }
|
||||
+ } else {
|
||||
+ collisionBox = currBoundingBox.expandTowards(movement.x, movement.y, movement.z);
|
||||
}
|
||||
}
|
||||
|
||||
- if (vec3d2.horizontalDistanceSqr() > vec3d1.horizontalDistanceSqr()) {
|
||||
- return vec3d2.add(Entity.collideBoundingBox(this, new Vec3(0.0D, -vec3d2.y + movement.y, 0.0D), axisalignedbb.move(vec3d2), this.level, list));
|
||||
+ io.papermc.paper.util.CollisionUtil.getCollisions(world, this, collisionBox, potentialCollisions, false, this.level.paperConfig().chunks.preventMovingIntoUnloadedChunks,
|
||||
+ false, false, null, null);
|
||||
+
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) {
|
||||
+ io.papermc.paper.util.CollisionUtil.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions);
|
||||
}
|
||||
- }
|
||||
|
||||
- return vec3d1;
|
||||
+ final Vec3 limitedMoveVector = io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisions);
|
||||
+
|
||||
+ if (stepHeight > 0.0
|
||||
+ && (this.onGround || (limitedMoveVector.y != movement.y && movement.y < 0.0))
|
||||
+ && (limitedMoveVector.x != movement.x || limitedMoveVector.z != movement.z)) {
|
||||
+ Vec3 vec3d2 = io.papermc.paper.util.CollisionUtil.performCollisions(new Vec3(movement.x, stepHeight, movement.z), currBoundingBox, potentialCollisions);
|
||||
+ final Vec3 vec3d3 = io.papermc.paper.util.CollisionUtil.performCollisions(new Vec3(0.0, stepHeight, 0.0), currBoundingBox.expandTowards(movement.x, 0.0, movement.z), potentialCollisions);
|
||||
+
|
||||
+ if (vec3d3.y < stepHeight) {
|
||||
+ final Vec3 vec3d4 = io.papermc.paper.util.CollisionUtil.performCollisions(new Vec3(movement.x, 0.0D, movement.z), currBoundingBox.move(vec3d3), potentialCollisions).add(vec3d3);
|
||||
+
|
||||
+ if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) {
|
||||
+ vec3d2 = vec3d4;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (vec3d2.horizontalDistanceSqr() > limitedMoveVector.horizontalDistanceSqr()) {
|
||||
+ return vec3d2.add(io.papermc.paper.util.CollisionUtil.performCollisions(new Vec3(0.0D, -vec3d2.y + movement.y, 0.0D), currBoundingBox.move(vec3d2), potentialCollisions));
|
||||
+ }
|
||||
+
|
||||
+ return limitedMoveVector;
|
||||
+ } else {
|
||||
+ return limitedMoveVector;
|
||||
+ }
|
||||
+ } finally {
|
||||
+ io.papermc.paper.util.CachedLists.returnTempCollisionList(potentialCollisions);
|
||||
+ }
|
||||
+ // Paper end - optimise collisions
|
||||
}
|
||||
|
||||
public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 movement, AABB entityBoundingBox, Level world, List<VoxelShape> collisions) {
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
float f = this.dimensions.width * 0.8F;
|
||||
AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f);
|
||||
|
||||
- return BlockPos.betweenClosedStream(axisalignedbb).anyMatch((blockposition) -> {
|
||||
- BlockState iblockdata = this.level.getBlockState(blockposition);
|
||||
+ BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos();
|
||||
+ int minX = Mth.floor(axisalignedbb.minX);
|
||||
+ int minY = Mth.floor(axisalignedbb.minY);
|
||||
+ int minZ = Mth.floor(axisalignedbb.minZ);
|
||||
+ int maxX = Mth.floor(axisalignedbb.maxX);
|
||||
+ int maxY = Mth.floor(axisalignedbb.maxY);
|
||||
+ int maxZ = Mth.floor(axisalignedbb.maxZ);
|
||||
+ for (int fz = minZ; fz <= maxZ; ++fz) {
|
||||
+ for (int fx = minX; fx <= maxX; ++fx) {
|
||||
+ for (int fy = minY; fy <= maxY; ++fy) {
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)this.level.getChunkIfLoadedImmediately(fx >> 4, fz >> 4);
|
||||
+ if (chunk == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- return !iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND);
|
||||
- });
|
||||
+ BlockState iblockdata = chunk.getBlockStateFinal(fx, fy, fz);
|
||||
+ blockposition.set(fx, fy, fz);
|
||||
+ if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockCollisions.java b/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
||||
@@ -0,0 +0,0 @@ public class BlockCollisions extends AbstractIterator<VoxelShape> {
|
||||
@@ -0,0 +0,0 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
|
||||
|
||||
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
|
||||
if (voxelShape == Shapes.block()) {
|
||||
|
@ -1509,157 +1322,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
|
||||
public void initCache() {
|
||||
this.fluidState = ((Block) this.owner).getFluidState(this.asState());
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
|
||||
this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque() ? -1 : this.cache.lightBlock; // Paper - starlight - cache opacity for light
|
||||
|
||||
+ // Paper start
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(this)) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_SPECIAL_BLOCK;
|
||||
+ } else {
|
||||
+ try {
|
||||
+ // There is NOTHING HACKY ABOUT THIS AT ALLLLLLLLLLLLLLL
|
||||
+ VoxelShape constantShape = this.getCollisionShape(null, null, null);
|
||||
+ if (constantShape == null) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ } else {
|
||||
+ constantShape = constantShape.optimize();
|
||||
+ if (constantShape.isEmpty()) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_EMPTY_BLOCK;
|
||||
+ } else {
|
||||
+ final List<net.minecraft.world.phys.AABB> boxes = constantShape.toAabbs();
|
||||
+ if (constantShape == net.minecraft.world.phys.shapes.Shapes.getFullUnoptimisedCube() || (boxes.size() == 1 && boxes.get(0).equals(net.minecraft.world.phys.shapes.Shapes.BLOCK_OPTIMISED.aabb))) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_FULL_BLOCK;
|
||||
+ } else {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (final Error error) {
|
||||
+ throw error;
|
||||
+ } catch (final Throwable throwable) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -0,0 +0,0 @@ public class LevelChunkSection {
|
||||
this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ protected int specialCollidingBlocks;
|
||||
+ // blockIndex = x | (z << 4) | (y << 8)
|
||||
+ private long[] knownBlockCollisionData;
|
||||
+
|
||||
+ private long[] initKnownDataField() {
|
||||
+ return this.knownBlockCollisionData = new long[16 * 16 * 16 * 2 / Long.SIZE];
|
||||
+ }
|
||||
+
|
||||
+ public final boolean hasSpecialCollidingBlocks() {
|
||||
+ return this.specialCollidingBlocks != 0;
|
||||
+ }
|
||||
+
|
||||
+ public static long getKnownBlockInfo(final int blockIndex, final long value) {
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1));
|
||||
+
|
||||
+ return (value >>> (valueShift << 1)) & 0b11L;
|
||||
+ }
|
||||
+
|
||||
+ public final long getKnownBlockInfo(final int blockIndex) {
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ return 0L;
|
||||
+ }
|
||||
+
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1));
|
||||
+
|
||||
+ final long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ return (value >>> (valueShift << 1)) & 0b11L;
|
||||
+ }
|
||||
+
|
||||
+ // important detail: this returns 32 values, one for localZ = localZ & (~1) and one for localZ = localZ | 1
|
||||
+ // the even localZ is the lower 32 bits, the odd is the upper 32 bits
|
||||
+ public final long getKnownBlockInfoHorizontalRaw(final int localY, final int localZ) {
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ return 0L;
|
||||
+ }
|
||||
+
|
||||
+ final int horizontalIndex = (localZ << 4) | (localY << 8);
|
||||
+ return this.knownBlockCollisionData[horizontalIndex >>> (6 - 1)];
|
||||
+ }
|
||||
+
|
||||
+ private void initBlockCollisionData() {
|
||||
+ this.specialCollidingBlocks = 0;
|
||||
+ // In 1.18 all sections will be initialised, whether or not they have blocks (fucking stupid btw)
|
||||
+ // This means we can't aggressively initialise the backing long[], or else memory usage will just skyrocket.
|
||||
+ // So only init if we contain non-empty blocks.
|
||||
+ if (this.nonEmptyBlockCount == 0) {
|
||||
+ this.knownBlockCollisionData = null;
|
||||
+ return;
|
||||
+ }
|
||||
+ this.initKnownDataField();
|
||||
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
|
||||
+ final BlockState state = this.states.get(index);
|
||||
+ this.setKnownBlockInfo(index, state);
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(state)) {
|
||||
+ ++this.specialCollidingBlocks;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // only use for initBlockCollisionData
|
||||
+ private void setKnownBlockInfo(final int blockIndex, final BlockState blockState) {
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1)) << 1;
|
||||
+
|
||||
+ long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ value &= ~(0b11L << valueShift);
|
||||
+ value |= blockState.getBlockCollisionBehavior() << valueShift;
|
||||
+
|
||||
+ this.knownBlockCollisionData[arrayIndex] = value;
|
||||
+ }
|
||||
+
|
||||
+ public void updateKnownBlockInfo(final int blockIndex, final BlockState from, final BlockState to) {
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(from)) {
|
||||
+ --this.specialCollidingBlocks;
|
||||
+ }
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(to)) {
|
||||
+ ++this.specialCollidingBlocks;
|
||||
+ }
|
||||
+
|
||||
+ if (this.nonEmptyBlockCount == 0) {
|
||||
+ this.knownBlockCollisionData = null;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ this.initKnownDataField();
|
||||
+ }
|
||||
+
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1)) << 1;
|
||||
+
|
||||
+ long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ value &= ~(0b11L << valueShift);
|
||||
+ value |= to.getBlockCollisionBehavior() << valueShift;
|
||||
+
|
||||
+ this.knownBlockCollisionData[arrayIndex] = value;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static int getBottomBlockY(int chunkPos) {
|
||||
return chunkPos << 4;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class LevelChunkSection {
|
||||
return this.setBlockState(x, y, z, state, true);
|
||||
}
|
|
@ -79,8 +79,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
- }
|
||||
+ // Paper - move into try block to only write if successfully serialized
|
||||
}
|
||||
// Paper start
|
||||
return;
|
||||
|
||||
} finally { // Paper start
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
|
|||
|
||||
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
||||
|
||||
CHECK ME
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
|
@ -19,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
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
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
boolean flag1 = entity.verticalCollisionBelow;
|
||||
}
|
||||
|
||||
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
||||
+ boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
||||
|
@ -58,7 +60,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
}
|
||||
|
||||
private boolean noBlocksAround(Entity entity) {
|
||||
- return entity.level.getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir);
|
||||
- return entity.level().getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir);
|
||||
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
|
||||
+ AABB box = entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D);
|
||||
+ int minX = Mth.floor(box.minX);
|
||||
|
@ -68,7 +70,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ int maxY = Mth.floor(box.maxY);
|
||||
+ int maxZ = Mth.floor(box.maxZ);
|
||||
+
|
||||
+ Level world = entity.level;
|
||||
+ Level world = entity.level();
|
||||
+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
+
|
||||
+ for (int y = minY; y <= maxY; ++y) {
|
||||
|
@ -104,27 +106,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
- AABB axisalignedbb = this.player.getBoundingBox();
|
||||
+ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
|
||||
|
||||
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
|
||||
d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
||||
d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
boolean flag1 = this.player.verticalCollisionBelow;
|
||||
|
||||
this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9));
|
||||
+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
||||
this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
||||
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
||||
+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
||||
// Paper start - prevent position desync
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
boolean flag2 = false;
|
||||
|
||||
if (!this.player.isChangingDimension() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
|
||||
if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
|
||||
- flag2 = true;
|
||||
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
|
||||
}
|
||||
|
||||
this.player.absMoveTo(d0, d1, d2, f, f1);
|
||||
- if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) {
|
||||
- if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) {
|
||||
+ // Paper start - optimise out extra getCubes
|
||||
+ // Original for reference:
|
||||
+ // boolean teleportBack = flag2 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb));
|
||||
|
@ -138,7 +139,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ if (!this.player.noPhysics && !this.player.isSleeping() && teleportBack) { // Paper end - optimise out extra getCubes
|
||||
this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
|
||||
this.player.doCheckFallDamage(this.player.getY() - d6, packet.isOnGround());
|
||||
this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround());
|
||||
} else {
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
}
|
||||
|
@ -164,7 +165,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise out extra getCubes
|
||||
+
|
||||
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box) {
|
||||
Iterable<VoxelShape> iterable = world.getCollisions(this.player, this.player.getBoundingBox().deflate(9.999999747378752E-6D));
|
||||
VoxelShape voxelshape = Shapes.create(box.deflate(9.999999747378752E-6D));
|
||||
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) {
|
||||
AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ());
|
||||
Iterable<VoxelShape> iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D));
|
|
@ -56,9 +56,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
// Paper start - distance maps
|
||||
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player)));
|
||||
this.playerMobDistanceMap.add(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
||||
}
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
// Paper end - per player mob spawning
|
||||
+ this.playerGeneralAreaMap.add(player, chunkX, chunkZ, GENERAL_AREA_MAP_SQUARE_RADIUS); // Paper - optimise checkDespawn
|
||||
}
|
||||
|
||||
|
@ -72,9 +72,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
if (this.playerMobDistanceMap != null) {
|
||||
this.playerMobDistanceMap.remove(player);
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player)));
|
||||
this.playerMobDistanceMap.update(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
||||
}
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
// Paper end - per player mob spawning
|
||||
+ this.playerGeneralAreaMap.update(player, chunkX, chunkZ, GENERAL_AREA_MAP_SQUARE_RADIUS); // Paper - optimise checkDespawn
|
||||
}
|
||||
// Paper end
|
||||
|
@ -190,7 +190,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ // Paper end - optimise get nearest players for entity AI
|
||||
+
|
||||
// Add env and gen to constructor, IWorldDataServer -> WorldDataServer
|
||||
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
||||
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
||||
// IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
}
|
||||
|
@ -212,14 +212,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements Targeting {
|
||||
if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
|
||||
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
|
||||
this.discard();
|
||||
} else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
|
||||
- Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
|
||||
- Player entityhuman = this.level().findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
|
||||
+ // Paper start - optimise checkDespawn
|
||||
+ Player entityhuman = this.level.findNearbyPlayer(this, level.paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).hard() + 1, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
|
||||
+ Player entityhuman = this.level().findNearbyPlayer(this, level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).hard() + 1, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper
|
||||
+ if (entityhuman == null) {
|
||||
+ entityhuman = ((ServerLevel)this.level).playersAffectingSpawning.isEmpty() ? null : ((ServerLevel)this.level).playersAffectingSpawning.get(0);
|
||||
+ entityhuman = ((ServerLevel)this.level()).playersAffectingSpawning.isEmpty() ? null : ((ServerLevel)this.level()).playersAffectingSpawning.get(0);
|
||||
+ }
|
||||
+ // Paper end - optimise checkDespawn
|
||||
|
|
@ -118,7 +118,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
|
||||
boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01D) && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
int l;
|
||||
int i1;
|
||||
|
||||
if (!this.paperConfig().environment.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow
|
||||
- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15));
|
||||
|
@ -141,10 +141,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
}
|
||||
|
||||
if (flag) {
|
||||
int i1 = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT);
|
||||
|
||||
l = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT);
|
||||
+
|
||||
+ blockposition.setY(normalY); // Paper
|
||||
if (i1 > 0 && biomebase.shouldSnow(this, blockposition)) {
|
||||
if (l > 0 && biomebase.shouldSnow(this, blockposition)) {
|
||||
BlockState iblockdata = this.getBlockState(blockposition);
|
||||
|
||||
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
@ -172,19 +172,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
timings.chunkTicksBlocks.startTiming(); // Paper
|
||||
if (randomTickSpeed > 0) {
|
||||
- LevelChunkSection[] achunksection = chunk.getSections();
|
||||
- int j1 = achunksection.length;
|
||||
-
|
||||
- for (int k1 = 0; k1 < j1; ++k1) {
|
||||
- LevelChunkSection chunksection = achunksection[k1];
|
||||
- for (int j1 = 0; j1 < achunksection.length; ++j1) {
|
||||
- LevelChunkSection chunksection = achunksection[j1];
|
||||
-
|
||||
- if (chunksection.isRandomlyTicking()) {
|
||||
- int l1 = chunksection.bottomBlockY();
|
||||
- l = chunk.getSectionYFromSectionIndex(j1);
|
||||
- int k1 = SectionPos.sectionToBlockCoord(l);
|
||||
-
|
||||
- for (l = 0; l < randomTickSpeed; ++l) {
|
||||
- BlockPos blockposition2 = this.getBlockRandomPos(j, l1, k, 15);
|
||||
- for (i1 = 0; i1 < randomTickSpeed; ++i1) {
|
||||
- BlockPos blockposition2 = this.getBlockRandomPos(j, k1, k, 15);
|
||||
-
|
||||
- gameprofilerfiller.push("randomTick");
|
||||
- BlockState iblockdata3 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - l1, blockposition2.getZ() - k);
|
||||
- BlockState iblockdata3 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - k1, blockposition2.getZ() - k);
|
||||
+ LevelChunkSection[] sections = chunk.getSections();
|
||||
+ int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this);
|
||||
+ for (int sectionIndex = 0; sectionIndex < sections.length; ++sectionIndex) {
|
||||
|
@ -235,7 +235,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/util/BitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/BitStorage.java
|
||||
@@ -0,0 +0,0 @@ public interface BitStorage {
|
||||
void unpack(int[] is);
|
||||
void unpack(int[] out);
|
||||
|
||||
BitStorage copy();
|
||||
+
|
||||
|
@ -350,7 +350,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
private PalettedContainer<Holder<Biome>> biomes;
|
||||
+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper
|
||||
|
||||
public LevelChunkSection(int i, PalettedContainer<BlockState> datapaletteblock, PalettedContainer<Holder<Biome>> palettedcontainerro) {
|
||||
public LevelChunkSection(PalettedContainer<BlockState> datapaletteblock, PalettedContainer<Holder<Biome>> palettedcontainerro) {
|
||||
// CraftBukkit end
|
||||
@@ -0,0 +0,0 @@ public class LevelChunkSection {
|
||||
--this.nonEmptyBlockCount;
|
||||
|
@ -421,9 +421,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
-
|
||||
}
|
||||
- }
|
||||
|
||||
- a a0 = new a();
|
||||
-
|
||||
- a a0 = new a();
|
||||
|
||||
- this.states.count(a0);
|
||||
- this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount;
|
||||
- this.tickingBlockCount = (short) a0.tickingBlockCount;
|
27
patches/server/Preserve-overstacked-loot.patch
Normal file
27
patches/server/Preserve-overstacked-loot.patch
Normal file
|
@ -0,0 +1,27 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lexikiq <noellekiq@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 23:21:58 -0400
|
||||
Subject: [PATCH] Preserve overstacked loot
|
||||
|
||||
Preserves overstacked items in loot tables, such as shulker box drops, to prevent the items
|
||||
from being deleted (as they'd overflow past the bounds of the container)-- or worse, causing
|
||||
chunk bans via the large amount of NBT created by unstacking the items.
|
||||
|
||||
Fixes GH-5140 and GH-4748.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
@@ -0,0 +0,0 @@ public class LootTable {
|
||||
}
|
||||
|
||||
public static Consumer<ItemStack> createStackSplitter(ServerLevel world, Consumer<ItemStack> consumer) {
|
||||
+ boolean skipSplitter = world != null && !world.paperConfig().fixes.splitOverstackedLoot; // Paper - preserve overstacked items
|
||||
return (itemstack) -> {
|
||||
if (itemstack.isItemEnabled(world.enabledFeatures())) {
|
||||
- if (itemstack.getCount() < itemstack.getMaxStackSize()) {
|
||||
+ if (skipSplitter || itemstack.getCount() < itemstack.getMaxStackSize()) { // Paper - preserve overstacked items
|
||||
consumer.accept(itemstack);
|
||||
} else {
|
||||
int i = itemstack.getCount();
|
|
@ -9,12 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return this.hasEffect(MobEffects.JUMP) ? (double) (0.1F * (float) (this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D;
|
||||
return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F;
|
||||
}
|
||||
|
||||
+ protected long lastJumpTime = 0L; // Paper
|
||||
protected void jumpFromGround() {
|
||||
double d0 = (double) this.getJumpPower() + this.getJumpBoostPower();
|
||||
Vec3 vec3d = this.getDeltaMovement();
|
||||
+ // Paper start
|
||||
+ long time = System.nanoTime();
|
||||
|
@ -28,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ // Paper end
|
||||
|
||||
this.setDeltaMovement(vec3d.x, d0, vec3d.z);
|
||||
this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z);
|
||||
if (this.isSprinting()) {
|
||||
float f = this.getYRot() * 0.017453292F;
|
||||
|
|
@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
case HAND:
|
||||
this.setLastHandItem(enumitemslot, itemstack1);
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
((ServerLevel) this.level).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
|
||||
((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
|
||||
}
|
||||
|
||||
+ // Paper start - prevent oversized data
|
|
@ -16,8 +16,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
long i1 = this.positionCodec.encodeZ(vec3d);
|
||||
boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L;
|
||||
|
||||
- if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) {
|
||||
+ if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround() && !(io.papermc.paper.configuration.GlobalConfiguration.get().collisions.sendFullPosForHardCollidingEntities && this.entity.hardCollides())) { // Paper - send full pos for hard colliding entities to prevent collision problems due to desync
|
||||
- if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) {
|
||||
+ if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()&& !(io.papermc.paper.configuration.GlobalConfiguration.get().collisions.sendFullPosForHardCollidingEntities && this.entity.hardCollides())) { // Paper - send full pos for hard colliding entities to prevent collision problems due to desync
|
||||
if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) {
|
||||
if (flag2) {
|
||||
packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.isOnGround());
|
||||
packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.onGround());
|
|
@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -0,0 +0,0 @@ dependencies {
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.41.2.2")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:8.0.32")
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.0")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:8.0.33")
|
||||
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
||||
+ // Paper start - Use Velocity cipher
|
||||
+ implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") {
|
||||
|
@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ // Paper end
|
||||
|
||||
runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
||||
runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
|
||||
runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.2")
|
||||
runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.10")
|
||||
diff --git a/src/main/java/net/minecraft/network/CipherDecoder.java b/src/main/java/net/minecraft/network/CipherDecoder.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/network/CipherDecoder.java
|
|
@ -1,53 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 23 Aug 2021 04:50:05 -0700
|
||||
Subject: [PATCH] Always parse protochunk light sources unless it is marked as
|
||||
non-lit
|
||||
|
||||
Chunks not marked as lit will always go through the light engine,
|
||||
so they should always have their block sources parsed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
BelowZeroRetrogen belowzeroretrogen = protochunk.getBelowZeroRetrogen();
|
||||
boolean flag5 = chunkstatus.isOrAfter(ChunkStatus.LIGHT) || belowzeroretrogen != null && belowzeroretrogen.targetStatus().isOrAfter(ChunkStatus.LIGHT);
|
||||
|
||||
- if (!flag && flag5) {
|
||||
- Iterator iterator = BlockPos.betweenClosed(chunkPos.getMinBlockX(), world.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), world.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ()).iterator();
|
||||
+ if (!flag) { // Paper - fix incorrect parsing of blocks that emit light - it should always parse it, unless the chunk is marked as lit
|
||||
+ // Paper start - let's make sure the implementation isn't as slow as possible
|
||||
+ int offX = chunkPos.x << 4;
|
||||
+ int offZ = chunkPos.z << 4;
|
||||
+
|
||||
+ int minChunkSection = io.papermc.paper.util.WorldUtil.getMinSection(world);
|
||||
+ int maxChunkSection = io.papermc.paper.util.WorldUtil.getMaxSection(world);
|
||||
+
|
||||
+ LevelChunkSection[] sections = achunksection;
|
||||
+ for (int sectionY = minChunkSection; sectionY <= maxChunkSection; ++sectionY) {
|
||||
+ LevelChunkSection section = sections[sectionY - minChunkSection];
|
||||
+ if (section == null || section.hasOnlyAir()) {
|
||||
+ // no sources in empty sections
|
||||
+ continue;
|
||||
+ }
|
||||
+ int offY = sectionY << 4;
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- BlockPos blockposition = (BlockPos) iterator.next();
|
||||
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
|
||||
+ if (section.states.get(index).getLightEmission() <= 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (((ChunkAccess) object1).getBlockState(blockposition).getLightEmission() != 0) {
|
||||
- protochunk.addLight(blockposition);
|
||||
+ // index = x | (z << 4) | (y << 8)
|
||||
+ protochunk.addLight(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lexikiq <noellekiq@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 23:21:58 -0400
|
||||
Subject: [PATCH] Preserve overstacked loot
|
||||
|
||||
Preserves overstacked items in loot tables, such as shulker box drops, to prevent the items
|
||||
from being deleted (as they'd overflow past the bounds of the container)-- or worse, causing
|
||||
chunk bans via the large amount of NBT created by unstacking the items.
|
||||
|
||||
Fixes GH-5140 and GH-4748.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
@@ -0,0 +0,0 @@ public class LootTable {
|
||||
this.compositeFunction = LootItemFunctions.compose(functions);
|
||||
}
|
||||
|
||||
+ // Paper start - preserve overstacked items
|
||||
+ @Deprecated
|
||||
public static Consumer<ItemStack> createStackSplitter(LootContext context, Consumer<ItemStack> consumer) {
|
||||
+ return createStackSplitter(context, consumer, null);
|
||||
+ }
|
||||
+ public static Consumer<ItemStack> createStackSplitter(LootContext context, Consumer<ItemStack> consumer, @org.jetbrains.annotations.Nullable net.minecraft.server.level.ServerLevel level) {
|
||||
+ boolean skipSplitter = level != null && !level.paperConfig().fixes.splitOverstackedLoot;
|
||||
+ // Paper end
|
||||
return (itemstack) -> {
|
||||
if (itemstack.isItemEnabled(context.getLevel().enabledFeatures())) {
|
||||
- if (itemstack.getCount() < itemstack.getMaxStackSize()) {
|
||||
+ if (skipSplitter || itemstack.getCount() < itemstack.getMaxStackSize()) { // Paper - preserve overstacked items
|
||||
consumer.accept(itemstack);
|
||||
} else {
|
||||
int i = itemstack.getCount();
|
||||
|
||||
+
|
||||
while (i > 0) {
|
||||
ItemStack itemstack1 = itemstack.copy();
|
||||
|
||||
@@ -0,0 +0,0 @@ public class LootTable {
|
||||
}
|
||||
|
||||
public void getRandomItems(LootContext context, Consumer<ItemStack> lootConsumer) {
|
||||
- this.getRandomItemsRaw(context, LootTable.createStackSplitter(context, lootConsumer));
|
||||
+ this.getRandomItemsRaw(context, LootTable.createStackSplitter(context, lootConsumer, context.getLevel())); // Paper - preserve overstacked items
|
||||
}
|
||||
|
||||
public ObjectArrayList<ItemStack> getRandomItems(LootContext context) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/SetContainerContents.java
|
||||
@@ -0,0 +0,0 @@ public class SetContainerContents extends LootItemConditionalFunction {
|
||||
NonNullList<ItemStack> nonNullList = NonNullList.create();
|
||||
this.entries.forEach((entry) -> {
|
||||
entry.expand(context, (choice) -> {
|
||||
- choice.createItemStack(LootTable.createStackSplitter(context, nonNullList::add), context);
|
||||
+ choice.createItemStack(LootTable.createStackSplitter(context, nonNullList::add, context.getLevel()), context); // Paper - preserve overstacked items
|
||||
});
|
||||
});
|
||||
CompoundTag compoundTag = new CompoundTag();
|
Loading…
Reference in a new issue