Update more feature patches

This commit is contained in:
Nassim Jahnke 2024-12-16 10:43:57 +01:00
parent 797abd11dd
commit 901cf13d01
No known key found for this signature in database
GPG key ID: EF6771C01F6EF02F
5 changed files with 170 additions and 186 deletions

View file

@ -30,36 +30,23 @@ This fix also maintains compatability if someone switches server jars to one wit
this fix, as the data will remain in the oversized file. Once the server returns this fix, as the data will remain in the oversized file. Once the server returns
to a jar with this fix, the data will be restored. to a jar with this fix, the data will be restored.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 2b4fa89f15a42ddd627983fbd1377fb7c9864896..7491644233d52dc56d83de5ad3373f6a9a455378 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java --- a/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -0,0 +0,0 @@ import java.nio.file.LinkOption; @@ -54,6 +54,7 @@ public class RegionFile implements AutoCloseable {
import java.nio.file.Path; this.info = info;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
+import java.util.zip.InflaterInputStream; // Paper
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.profiling.jfr.JvmProfiler;
+import net.minecraft.nbt.CompoundTag; // Paper
+import net.minecraft.nbt.NbtIo; // Paper
import net.minecraft.world.level.ChunkPos;
import org.slf4j.Logger;
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
this.usedSectors = new RegionBitmap();
this.info = storageKey;
this.path = path; this.path = path;
+ initOversizedState(); // Paper this.version = version;
this.version = compressionFormat; + this.initOversizedState(); // Paper
if (!Files.isDirectory(directory, new LinkOption[0])) { if (!Files.isDirectory(externalFileDir)) {
throw new IllegalArgumentException("Expected directory, got " + String.valueOf(directory.toAbsolutePath())); throw new IllegalArgumentException("Expected directory, got " + externalFileDir.toAbsolutePath());
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } else {
@@ -424,4 +425,75 @@ public class RegionFile implements AutoCloseable {
interface CommitOp {
void run() throws IOException;
} }
+
+ // Paper start + // Paper start
+ private final byte[] oversized = new byte[1024]; + private final byte[] oversized = new byte[1024];
+ private int oversizedCount; + private int oversizedCount;
@ -78,9 +65,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private static int getChunkIndex(int x, int z) { + private static int getChunkIndex(int x, int z) {
+ return (x & 31) + (z & 31) * 32; + return (x & 31) + (z & 31) * 32;
+ } + }
+
+ synchronized boolean isOversized(int x, int z) { + synchronized boolean isOversized(int x, int z) {
+ return this.oversized[getChunkIndex(x, z)] == 1; + return this.oversized[getChunkIndex(x, z)] == 1;
+ } + }
+
+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { + synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
+ final int offset = getChunkIndex(x, z); + final int offset = getChunkIndex(x, z);
+ boolean previous = this.oversized[offset] == 1; + boolean previous = this.oversized[offset] == 1;
@ -120,22 +109,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); + return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
+ } + }
+ +
+ synchronized CompoundTag getOversizedData(int x, int z) throws IOException { + synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException {
+ Path file = getOversizedFile(x, z); + Path file = getOversizedFile(x, z);
+ try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new InflaterInputStream(Files.newInputStream(file))))) { + try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new java.util.zip.InflaterInputStream(Files.newInputStream(file))))) {
+ return NbtIo.read((java.io.DataInput) out); + return net.minecraft.nbt.NbtIo.read((java.io.DataInput) out);
+ } + }
+ +
+ } + }
+ // Paper end + // Paper end
private class ChunkBuffer extends ByteArrayOutputStream { }
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
private final ChunkPos pos; index 5ac84d6b47e7fdc16e1c09b739829de3d316bf5b..51bf310423013d0ae9d3202d66e36a053a767197 100644
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java --- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -47,6 +47,43 @@ public final class RegionFileStorage implements AutoCloseable {
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable {
} }
} }
@ -148,7 +135,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ synchronized (regionfile) { + synchronized (regionfile) {
+ try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) { + try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
+ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); + CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
+ CompoundTag chunk = NbtIo.read((DataInput) datainputstream); + CompoundTag chunk = NbtIo.read(datainputstream);
+ if (oversizedData == null) { + if (oversizedData == null) {
+ return chunk; + return chunk;
+ } + }
@ -177,26 +164,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
+ +
@Nullable @Nullable
public CompoundTag read(ChunkPos pos) throws IOException { public CompoundTag read(ChunkPos chunkPos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable { @@ -55,6 +92,12 @@ public final class RegionFileStorage implements AutoCloseable {
return null;
}
// CraftBukkit end // CraftBukkit end
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
+ // Paper start + // Paper start
+ if (regionfile.isOversized(pos.x, pos.z)) { + if (regionFile.isOversized(chunkPos.x, chunkPos.z)) {
+ printOversizedLog("Loading Oversized Chunk!", regionfile.getPath(), pos.x, pos.z); + printOversizedLog("Loading Oversized Chunk!", regionFile.getPath(), chunkPos.x, chunkPos.z);
+ return readOversizedChunk(regionfile, pos); + return readOversizedChunk(regionFile, chunkPos);
+ } + }
+ // Paper end + // Paper end
CompoundTag nbttagcompound;
label43:
{
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable {
try { CompoundTag var4;
NbtIo.write(nbt, (DataOutput) dataoutputstream); try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) {
+ regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone @@ -90,6 +133,7 @@ public final class RegionFileStorage implements AutoCloseable {
} catch (Throwable throwable) { } else {
if (dataoutputstream != null) { try (DataOutputStream chunkDataOutputStream = regionFile.getChunkDataOutputStream(chunkPos)) {
try { NbtIo.write(chunkData, chunkDataOutputStream);
+ regionFile.setOversized(chunkPos.x, chunkPos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone
}
}
}

View file

@ -8,49 +8,49 @@ creating too large of a packet to sed.
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com> Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 5d1943d37dfad0c12e77179f0866851532d983e9..0a7e6c639d5125a135a43476bbb2ef2d682f743c 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java --- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java +++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacketData { @@ -27,6 +27,14 @@ public class ClientboundLevelChunkPacketData {
private final CompoundTag heightmaps; private final CompoundTag heightmaps;
private final byte[] buffer; private final byte[] buffer;
private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData; private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
+ // Paper start - Handle oversized block entities in chunks + // Paper start - Handle oversized block entities in chunks
+ private final java.util.List<net.minecraft.network.protocol.Packet<?>> extraPackets = new java.util.ArrayList<>(); + private final java.util.List<net.minecraft.network.protocol.Packet<?>> extraPackets = new java.util.ArrayList<>();
+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); + private static final int BLOCK_ENTITY_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
+ +
+ public List<net.minecraft.network.protocol.Packet<?>> getExtraPackets() { + public List<net.minecraft.network.protocol.Packet<?>> getExtraPackets() {
+ return this.extraPackets; + return this.extraPackets;
+ } + }
+ // Paper end - Handle oversized block entities in chunks + // Paper end - Handle oversized block entities in chunks
// Paper start - Anti-Xray - Add chunk packet info public ClientboundLevelChunkPacketData(LevelChunk levelChunk) {
@Deprecated @io.papermc.paper.annotation.DoNotUse public ClientboundLevelChunkPacketData(LevelChunk chunk) { this(chunk, null); } this.heightmaps = new CompoundTag();
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacketData { @@ -40,8 +48,18 @@ public class ClientboundLevelChunkPacketData {
extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk, chunkPacketInfo); this.buffer = new byte[calculateChunkSize(levelChunk)];
// Paper end extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk);
this.blockEntitiesData = Lists.newArrayList(); this.blockEntitiesData = Lists.newArrayList();
+ int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks + int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
for (Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) { for (Entry<BlockPos, BlockEntity> entryx : levelChunk.getBlockEntities().entrySet()) {
+ // Paper start - Handle oversized block entities in chunks + // Paper start - Handle oversized block entities in chunks
+ if (++totalTileEntities > TE_LIMIT) { + if (++totalTileEntities > BLOCK_ENTITY_LIMIT) {
+ var packet = entry2.getValue().getUpdatePacket(); + net.minecraft.network.protocol.Packet<ClientGamePacketListener> packet = entryx.getValue().getUpdatePacket();
+ if (packet != null) { + if (packet != null) {
+ this.extraPackets.add(packet); + this.extraPackets.add(packet);
+ continue; + continue;
+ } + }
+ } + }
+ // Paper end - Handle oversized block entities in chunks + // Paper end - Handle oversized block entities in chunks
this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entry2.getValue())); this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(entryx.getValue()));
} }
} }
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index aadf2dccb996e422cacf8bb510cc642e69ee4972..5288de783481b7e932017c679b9eaa715b8826c6 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java --- a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java +++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkWithLightPacket implements Packet<ClientGamePa @@ -66,4 +66,11 @@ public class ClientboundLevelChunkWithLightPacket implements Packet<ClientGamePa
public ClientboundLightUpdatePacketData getLightData() { public ClientboundLightUpdatePacketData getLightData() {
return this.lightData; return this.lightData;
} }

View file

@ -4,65 +4,65 @@ Date: Mon, 2 Aug 2021 10:10:40 +0200
Subject: [PATCH] Check distance in entity interactions Subject: [PATCH] Check distance in entity interactions
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java diff --git a/net/minecraft/Util.java b/net/minecraft/Util.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 60952bd49a89b8d6247d0c8bac837e5b3d586a76..fe84fe69a2a9ed95ec45a9e5af6e6f5a5a74edda 100644
--- a/src/main/java/net/minecraft/Util.java --- a/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java +++ b/net/minecraft/Util.java
@@ -0,0 +0,0 @@ public class Util { @@ -130,6 +130,7 @@ public class Util {
.filter(fileSystemProvider -> fileSystemProvider.getScheme().equalsIgnoreCase("jar"))
.findFirst() .findFirst()
.orElseThrow(() -> new IllegalStateException("No jar file system provider found")); .orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
private static Consumer<String> thePauser = string -> {};
+ public static final double COLLISION_EPSILON = 1.0E-7; // Paper - Check distance in entity interactions + public static final double COLLISION_EPSILON = 1.0E-7; // Paper - Check distance in entity interactions
private static Consumer<String> thePauser = message -> {
};
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 return Collectors.toMap(Entry::getKey, Entry::getValue);
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 88f8d462728231627c3ee7557518a2e04b4fd199..e118fd567427064c6ad6637f874ed146e67b2ee8 100644
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { --- a/net/minecraft/world/entity/LivingEntity.java
if (!source.is(DamageTypeTags.IS_PROJECTILE)) { +++ b/net/minecraft/world/entity/LivingEntity.java
Entity entity = source.getDirectEntity(); @@ -1392,7 +1392,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.hurtCurrentlyUsedShield(amount);
f1 = amount;
amount = 0.0F;
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity) {
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && damageSource.getDirectEntity() instanceof LivingEntity livingEntity && livingEntity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Check distance in entity interactions
this.blockUsingShield(livingEntity);
}
- if (entity instanceof LivingEntity) { @@ -1477,6 +1477,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ if (entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Check distance in entity interactions d = damageSource.getSourcePosition().x() - this.getX();
LivingEntity entityliving = (LivingEntity) entity; d1 = damageSource.getSourcePosition().z() - this.getZ();
this.blockUsingShield(entityliving);
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
d0 = source.getSourcePosition().x() - this.getX();
d1 = source.getSourcePosition().z() - this.getZ();
} }
+ // Paper start - Check distance in entity interactions; see for loop in knockback method + // Paper start - Check distance in entity interactions; see for loop in knockback method
+ if (Math.abs(d0) > 200) { + if (Math.abs(d) > 200) {
+ d0 = Math.random() - Math.random(); + d = Math.random() - Math.random();
+ } + }
+ if (Math.abs(d1) > 200) { + if (Math.abs(d1) > 200) {
+ d1 = Math.random() - Math.random(); + d1 = Math.random() - Math.random();
+ } + }
+ // Paper end - Check distance in entity interactions + // Paper end - Check distance in entity interactions
this.knockback(0.4000000059604645D, d0, d1, entity1, entity1 == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events this.knockback(0.4F, d, d1, damageSource.getDirectEntity(), damageSource.getDirectEntity() == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
if (!flag) { if (!flag) {
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -2352,7 +2360,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING));
Entity entity = damagesource.getDirectEntity(); Entity entity = damageSource.getDirectEntity();
- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity) { // Paper - Fix shield disable inconsistency - if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity) { // Paper - Fix shield disable inconsistency
+ if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Fix shield disable inconsistency & Check distance in entity interactions + if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Fix shield disable inconsistency & Check distance in entity interactions
this.blockUsingShield((LivingEntity) entity); this.blockUsingShield((LivingEntity) entity);
} }
} }
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 5cd65e94ac7830aaa2a64057fc2a81478b55ea41..b9cb86717d7e6c05eb97f3b1bbf1d0111a0ba6ed 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java --- a/net/minecraft/world/entity/vehicle/AbstractBoat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java +++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java
@@ -0,0 +0,0 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { @@ -641,7 +641,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
double d2 = (double) (this.getWaterLevelAbove() - this.getBbHeight()) + 0.101D; this.waterLevel = this.getY(1.0);
double d2 = this.getWaterLevelAbove() - this.getBbHeight() + 0.101;
if (this.level().noCollision(this, this.getBoundingBox().move(0.0D, d2 - this.getY(), 0.0D))) { if (this.level().noCollision(this, this.getBoundingBox().move(0.0, d2 - this.getY(), 0.0))) {
- this.setPos(this.getX(), d2, this.getZ()); - this.setPos(this.getX(), d2, this.getZ());
+ this.move(MoverType.SELF, new Vec3(0.0D, d2 - this.getY(), 0.0D)); // Paper - Check distance in entity interactions // TODO Still needed?? + this.move(MoverType.SELF, new Vec3(0.0D, d2 - this.getY(), 0.0D)); // Paper - Check distance in entity interactions // TODO Still needed??
this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0));
this.lastYd = 0.0D; this.lastYd = 0.0;
} }

View file

@ -4,75 +4,75 @@ Date: Fri, 22 Jan 2021 21:50:18 +0100
Subject: [PATCH] optimize dirt and snow spreading Subject: [PATCH] optimize dirt and snow spreading
diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java diff --git a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 11937aa74efe08bdbd66a619c7a825f91d971afd..722f2b9a24679e0fc67aae2cd27051f96f962efe 100644
--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java --- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
@@ -0,0 +0,0 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { @@ -17,8 +17,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
} }
private static boolean canBeGrass(BlockState state, LevelReader world, BlockPos pos) { private static boolean canBeGrass(BlockState state, LevelReader levelReader, BlockPos pos) {
+ // Paper start - Perf: optimize dirt and snow spreading + // Paper start - Perf: optimize dirt and snow spreading
+ return canBeGrass(world.getChunk(pos), state, world, pos); + return canBeGrass(levelReader.getChunk(pos), state, levelReader, pos);
+ } + }
+ private static boolean canBeGrass(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) { + private static boolean canBeGrass(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader levelReader, BlockPos pos) {
+ // Paper end - Perf: optimize dirt and snow spreading + // Paper end - Perf: optimize dirt and snow spreading
BlockPos blockposition1 = pos.above(); BlockPos blockPos = pos.above();
- BlockState iblockdata1 = world.getBlockState(blockposition1); - BlockState blockState = levelReader.getBlockState(blockPos);
+ BlockState iblockdata1 = chunk.getBlockState(blockposition1); // Paper - Perf: optimize dirt and snow spreading + BlockState blockState = chunk.getBlockState(blockPos); // Paper - Perf: optimize dirt and snow spreading
if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) {
if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) {
return true; return true;
@@ -0,0 +0,0 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { } else if (blockState.getFluidState().getAmount() == 8) {
@@ -33,14 +38,27 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
protected abstract MapCodec<? extends SpreadingSnowyDirtBlock> codec(); protected abstract MapCodec<? extends SpreadingSnowyDirtBlock> codec();
private static boolean canPropagate(BlockState state, LevelReader world, BlockPos pos) { private static boolean canPropagate(BlockState state, LevelReader level, BlockPos pos) {
+ // Paper start - Perf: optimize dirt and snow spreading + // Paper start - Perf: optimize dirt and snow spreading
+ return canPropagate(world.getChunk(pos), state, world, pos); + return canPropagate(level.getChunk(pos), state, level, pos);
+ } + }
+ +
+ private static boolean canPropagate(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) { + private static boolean canPropagate(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader level, BlockPos pos) {
+ // Paper end - Perf: optimize dirt and snow spreading + // Paper end - Perf: optimize dirt and snow spreading
BlockPos blockposition1 = pos.above(); BlockPos blockPos = pos.above();
- return canBeGrass(state, level, pos) && !level.getFluidState(blockPos).is(FluidTags.WATER);
- return SpreadingSnowyDirtBlock.canBeGrass(state, world, pos) && !world.getFluidState(blockposition1).is(FluidTags.WATER); + return canBeGrass(chunk, state, level, pos) && !chunk.getFluidState(blockPos).is(FluidTags.WATER); // Paper - Perf: optimize dirt and snow spreading
+ return SpreadingSnowyDirtBlock.canBeGrass(chunk, state, world, pos) && !chunk.getFluidState(blockposition1).is(FluidTags.WATER); // Paper - Perf: optimize dirt and snow spreading
} }
@Override @Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks if (this instanceof GrassBlock && level.paperConfig().tickRates.grassSpread != 1 && (level.paperConfig().tickRates.grassSpread < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % level.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks
- if (!SpreadingSnowyDirtBlock.canBeGrass(state, world, pos)) { - if (!canBeGrass(state, level, pos)) {
+ // Paper start - Perf: optimize dirt and snow spreading + // Paper start - Perf: optimize dirt and snow spreading
+ final net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos); + final net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = level.getChunkIfLoaded(pos);
+ if (cachedBlockChunk == null) { // Is this needed? + if (cachedBlockChunk == null) { // Is this needed?
+ return; + return;
+ } + }
+ if (!SpreadingSnowyDirtBlock.canBeGrass(cachedBlockChunk, state, world, pos)) { +
+ if (!canBeGrass(cachedBlockChunk, state, level, pos)) {
+ // Paper end - Perf: optimize dirt and snow spreading + // Paper end - Perf: optimize dirt and snow spreading
// CraftBukkit start // CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
return; return;
@@ -0,0 +0,0 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { @@ -53,8 +71,20 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
for (int i = 0; i < 4; ++i) {
BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
- if (world.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(iblockdata1, world, blockposition1)) { for (int i = 0; i < 4; i++) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, isSnowySetting(world.getBlockState(blockposition1.above())))); // CraftBukkit BlockPos blockPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
- if (level.getBlockState(blockPos).is(Blocks.DIRT) && canPropagate(blockState, level, blockPos)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState.setValue(SNOWY, Boolean.valueOf(isSnowySetting(level.getBlockState(blockPos.above()))))); // CraftBukkit
+ // Paper start - Perf: optimize dirt and snow spreading + // Paper start - Perf: optimize dirt and snow spreading
+ if (pos.getX() == blockposition1.getX() && pos.getY() == blockposition1.getY() && pos.getZ() == blockposition1.getZ()) { + if (pos.getX() == blockPos.getX() && pos.getY() == blockPos.getY() && pos.getZ() == blockPos.getZ()) {
+ continue; + continue;
+ } + }
+ +
+ final net.minecraft.world.level.chunk.ChunkAccess access; + final net.minecraft.world.level.chunk.ChunkAccess access;
+ if (cachedBlockChunk.locX == blockposition1.getX() >> 4 && cachedBlockChunk.locZ == blockposition1.getZ() >> 4) { + if (cachedBlockChunk.locX == blockPos.getX() >> 4 && cachedBlockChunk.locZ == blockPos.getZ() >> 4) {
+ access = cachedBlockChunk; + access = cachedBlockChunk;
+ } else { + } else {
+ access = world.getChunkAt(blockposition1); + access = level.getChunkAt(blockPos);
+ } + }
+ if (access.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(access, iblockdata1, world, blockposition1)) { + if (access.getBlockState(blockPos).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(access, blockState, level, blockPos)) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, isSnowySetting(access.getBlockState(blockposition1.above())))); // CraftBukkit + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, (BlockState) blockState.setValue(SpreadingSnowyDirtBlock.SNOWY, isSnowySetting(access.getBlockState(blockPos.above())))); // CraftBukkit
+ // Paper end - Perf: optimize dirt and snow spreading + // Paper end - Perf: optimize dirt and snow spreading
} }
} }
} }

View file

@ -6,13 +6,13 @@ Subject: [PATCH] Optimise getChunkAt calls for loaded chunks
bypass the need to get a player chunk, then get the either, bypass the need to get a player chunk, then get the either,
then unwrap it... then unwrap it...
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index d310e7489fc4ecede8deef59241444769d87b0a1..f268808cb250e374f2d5652b20eece011e87dcfb 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { @@ -218,6 +218,12 @@ public class ServerChunkCache extends ChunkSource {
return this.getChunk(x, z, leastStatus, create); if (Thread.currentThread() != this.mainThread) {
}, this.mainThreadProcessor).join(); return CompletableFuture.<ChunkAccess>supplyAsync(() -> this.getChunk(x, z, chunkStatus, requireChunk), this.mainThreadProcessor).join();
} else { } else {
+ // Paper start - Perf: Optimise getChunkAt calls for loaded chunks + // Paper start - Perf: Optimise getChunkAt calls for loaded chunks
+ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z); + LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z);
@ -20,41 +20,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return ifLoaded; + return ifLoaded;
+ } + }
+ // Paper end - Perf: Optimise getChunkAt calls for loaded chunks + // Paper end - Perf: Optimise getChunkAt calls for loaded chunks
ProfilerFiller gameprofilerfiller = Profiler.get(); ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.incrementCounter("getChunk");
gameprofilerfiller.incrementCounter("getChunk"); long packedChunkPos = ChunkPos.asLong(x, z);
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { @@ -252,30 +258,7 @@ public class ServerChunkCache extends ChunkSource {
if (Thread.currentThread() != this.mainThread) { if (Thread.currentThread() != this.mainThread) {
return null; return null;
} else { } else {
- Profiler.get().incrementCounter("getChunkNow"); - Profiler.get().incrementCounter("getChunkNow");
- long k = ChunkPos.asLong(chunkX, chunkZ); - long packedChunkPos = ChunkPos.asLong(chunkX, chunkZ);
- -
- ChunkAccess ichunkaccess; - for (int i = 0; i < 4; i++) {
- - if (packedChunkPos == this.lastChunkPos[i] && this.lastChunkStatus[i] == ChunkStatus.FULL) {
- for (int l = 0; l < 4; ++l) { - ChunkAccess chunkAccess = this.lastChunk[i];
- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { - return chunkAccess instanceof LevelChunk ? (LevelChunk)chunkAccess : null;
- ichunkaccess = this.lastChunk[l];
- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null;
- } - }
- } - }
- -
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); - ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(packedChunkPos);
- - if (visibleChunkIfPresent == null) {
- if (playerchunk == null) {
- return null; - return null;
- } else { - } else {
- ichunkaccess = playerchunk.getChunkIfPresent(ChunkStatus.FULL); - ChunkAccess chunkAccess = visibleChunkIfPresent.getChunkIfPresent(ChunkStatus.FULL);
- if (ichunkaccess != null) { - if (chunkAccess != null) {
- this.storeInCache(k, ichunkaccess, ChunkStatus.FULL); - this.storeInCache(packedChunkPos, chunkAccess, ChunkStatus.FULL);
- if (ichunkaccess instanceof LevelChunk) { - if (chunkAccess instanceof LevelChunk) {
- return (LevelChunk) ichunkaccess; - return (LevelChunk)chunkAccess;
- } - }
- } - }
- -
- return null; - return null;
- } - }
+ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - Perf: Optimise getChunkAt calls for loaded chunks + return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - Perf: Optimise getChunkAt calls for loaded chunk
} }
} }