more patches

This commit is contained in:
Jake Potrebic 2021-06-13 12:29:58 -07:00
parent 6358589ae3
commit 7dd2ea0897
30 changed files with 615 additions and 995 deletions

View file

@ -1,89 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 02:17:54 -0600
Subject: [PATCH] Generator Settings
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
private void perPlayerMobSpawns() {
perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false);
}
+
+ public boolean generateFlatBedrock;
+ private void generatorSettings() {
+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false);
+ }
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
public interface ChunkAccess extends BlockGetter, FeatureAccess {
+ // Paper start
+ default boolean generateFlatBedrock() {
+ if (this instanceof ProtoChunk) {
+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock;
+ } else if (this instanceof LevelChunk) {
+ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock;
+ } else {
+ return false;
+ }
+ }
+ // Paper end
+
BlockState getType(final int x, final int y, final int z); // Paper
@Nullable
BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess {
private long inhabitedTime;
private final Map<GenerationStep.Carving, BitSet> carvingMasks;
private volatile boolean isLightCorrect;
- private final Level world; // Paper - Anti-Xray - Add world
+ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default
// Paper start - Anti-Xray - Add world
@Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
int i = chunk.getPos().getMinBlockX();
int j = chunk.getPos().getMinBlockZ();
NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get();
- int k = generatorsettingbase.getBedrockFloorPosition();
- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition();
+ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper
+ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper
boolean flag = true;
boolean flag1 = l + 4 >= 0 && l < this.height;
boolean flag2 = k + 4 >= 0 && k < this.height;
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
if (flag1) {
for (i1 = 0; i1 < 5; ++i1) {
- if (i1 <= random.nextInt(5)) {
+ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof
chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
}
}
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
if (flag2) {
for (i1 = 4; i1 >= 0; --i1) {
- if (i1 <= random.nextInt(5)) {
+ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor
chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
}
}

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wea_ondara <wea_ondara@alpenblock.net>
Date: Thu, 10 Oct 2019 11:29:42 +0200
Subject: [PATCH] Performance improvement for Chunk.getEntities
This patch aims to reduce performance cost used by collecting the
entities of a chunk. Previously the entitySlices were copied into an
extra array with List.toArray() with is a costly and unneccessary
operation. This patch will reduce the load of plugins which for example
implement custom moblimits and depend on Chunk.getEntities().
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk {
Entity[] entities = new Entity[count];
for (int i = 0; i < 16; i++) {
-
- for (Object obj : chunk.entitySlices[i].toArray()) {
- if (!(obj instanceof net.minecraft.world.entity.Entity)) {
+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often)
+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) {
+ if (entity == null) {
continue;
}
-
- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity();
+ entities[index++] = entity.getBukkitEntity();
}
+ // Paper end
}
return entities;

View file

@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class CraftBlock implements Block {
// Modelled off EntityHuman#hasBlock
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem);
net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), position, this.world.getBlockEntity(position), null, nmsItem);
+ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper
result = true;
}

View file

@ -18,6 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols);
+ }
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java

View file

@ -17,16 +17,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java
+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java
@@ -0,0 +0,0 @@ public class DoubleBlockCombiner {
return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0);
return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
} else {
BlockPos blockposition1 = pos.relative((Direction) function1.apply(state));
- BlockState iblockdata1 = world.getBlockState(blockposition1);
BlockPos blockPos = pos.relative(function.apply(state));
- BlockState blockState = world.getBlockState(blockPos);
+ // Paper start
+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1);
+ if (iblockdata1 == null) {
+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0);
+ BlockState blockState = world.getTypeIfLoaded(blockPos);
+ if (blockState == null) {
+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
+ }
+ // Paper end
if (iblockdata1.is(state.getBlock())) {
DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1);
if (blockState.is(state.getBlock())) {
DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState);
if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE && blockType != blockType2 && blockState.getValue(directionProperty) == state.getValue(directionProperty)) {

View file

@ -17,108 +17,117 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/mai
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
++TimingHistory.entityTicks; // Paper - timings
// Spigot start
co.aikar.timings.Timing timer; // Paper
- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) {
- entity.tickCount++;
- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings
+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below
+ entity.ticksLived++;
+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings
entity.inactiveTick();
} finally { timer.stopTiming(); } // Paper
return;
- }
+ }*/ // Paper - comment out EAR 2
// Spigot end
// Paper start- timings
- TimingHistory.activatedEntityTicks++;
- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming();
+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity);
+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper
try {
// Paper end - timings
entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ());
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
return Registry.ENTITY_TYPE.getKey(entity.getType()).toString();
});
gameprofilerfiller.incrementCounter("tickNonPassenger");
+ if (isActive) { // Paper - EAR 2
+ TimingHistory.activatedEntityTicks++; // Paper
entity.tick();
entity.postTick(); // CraftBukkit
+ } else { entity.inactiveTick(); } // Paper - EAR 2
gameprofilerfiller.pop();
}
this.updateChunkPos(entity);
+ } finally { timer.stopTiming(); } // Paper - timings
if (entity.inChunk) {
Iterator iterator = entity.getPassengers().iterator();
@@ -0,0 +0,0 @@ package net.minecraft.server.level;
import com.google.common.annotations.VisibleForTesting;
import co.aikar.timings.TimingHistory; // Paper
-import co.aikar.timings.Timings; // Paper
import com.google.common.collect.Lists;
import com.mojang.datafixers.DataFixer;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.longs.LongSets;
import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.storage.EntityStorage;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.end.EndDragonFight;
-import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntityPersistentStorage;
import net.minecraft.world.level.entity.EntityTickList;
import net.minecraft.world.level.entity.EntityTypeTest;
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.tickPassenger(entity, entity1);
}
}
- } finally { timer.stopTiming(); } // Paper - timings
+ //} finally { timer.stopTiming(); } // Paper - timings - move up
++TimingHistory.entityTicks; // Paper - timings
// Spigot start
co.aikar.timings.Timing timer; // Paper
- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) {
+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below
entity.tickCount++;
timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings
entity.inactiveTick();
} finally { timer.stopTiming(); } // Paper
return;
- }
+ }*/ // Paper - comment out EAR 2
// Spigot end
// Paper start- timings
- TimingHistory.activatedEntityTicks++;
- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming();
+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity);
+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper
try {
// Paper end - timings
entity.isInLava();
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
return Registry.ENTITY_TYPE.getKey(entity.getType()).toString();
});
gameprofilerfiller.incrementCounter("tickNonPassenger");
+ if (isActive) { // Paper - EAR 2
+ TimingHistory.activatedEntityTicks++;
entity.tick();
entity.postTick(); // CraftBukkit
+ } else { entity.inactiveTick(); } // Paper - EAR 2
this.getProfiler().pop();
+ } finally { timer.stopTiming(); } // Paper - timings
Iterator iterator = entity.getPassengers().iterator();
while (iterator.hasNext()) {
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.tickPassenger(entity, entity1);
}
- } finally { timer.stopTiming(); } // Paper - timings
+ // } finally { timer.stopTiming(); } // Paper - timings - move up
}
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
public void tickPassenger(Entity vehicle, Entity passenger) {
if (!passenger.removed && passenger.getVehicle() == vehicle) {
if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) {
private void tickPassenger(Entity vehicle, Entity passenger) {
if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) {
if (passenger instanceof Player || this.entityTickList.contains(passenger)) {
+ // Paper - EAR 2
+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger);
+ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper
+ try {
+ // Paper end
passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ());
passenger.yRotO = passenger.yRot;
passenger.xRotO = passenger.xRot;
passenger.setOldPosAndRot();
++passenger.tickCount;
ProfilerFiller gameprofilerfiller = this.getProfiler();
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString();
});
gameprofilerfiller.incrementCounter("tickPassenger");
+ // Paper start - EAR 2
+ if (isActive) {
passenger.rideTick();
passenger.postTick(); // CraftBukkit
+ } else {
+ passenger.setDeltaMovement(Vec3.ZERO);
+ passenger.inactiveTick();
+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary
+ vehicle.syncPositionOf(passenger);
+ }
+ // Paper end - EAR 2
gameprofilerfiller.pop();
return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString();
});
gameprofilerfiller.incrementCounter("tickPassenger");
+ // Paper start - EAR 2
+ if (isActive) {
passenger.rideTick();
passenger.postTick(); // CraftBukkit
+ } else {
+ passenger.setDeltaMovement(Vec3.ZERO);
+ passenger.inactiveTick();
+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary
+ vehicle.positionRider(passenger);
+ }
+ // Paper end - EAR 2
gameprofilerfiller.pop();
Iterator iterator = passenger.getPassengers().iterator();
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.tickPassenger(passenger, entity2);
}
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.tickPassenger(passenger, entity2);
}
- }
+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings
+ } finally { timer.stopTiming(); }// Paper - EAR2 timings
}
} else {
passenger.stopRiding();
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 @@ import net.minecraft.world.entity.animal.AbstractFish;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
public boolean noCulling;
public boolean hasImpulse;
public int portalCooldown;
@ -127,7 +136,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected int portalTime;
protected BlockPos portalEntrancePos;
private boolean invulnerable;
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this);
public final boolean defaultActivationState;
public long activatedTick = Integer.MIN_VALUE;
@ -135,51 +144,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
protected int numCollisions = 0; // Paper
public void inactiveTick() { }
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
this.setLocationFromBoundingbox();
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
} else {
if (type == MoverType.PISTON) {
this.wasOnFire = this.isOnFire();
if (movementType == MoverType.PISTON) {
+ this.activatedTick = MinecraftServer.currentTick + 20; // Paper
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
this.stuckSpeedMultiplier = Vec3.ZERO;
this.setDeltaMovement(Vec3.ZERO);
}
+ // Paper start - ignore movement changes while inactive.
+ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) {
+ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) {
+ setDeltaMovement(Vec3.ZERO);
+ this.level.getProfiler().pop();
+ return;
+ }
+ // Paper end
movement = this.maybeBackOffFromEdge(movement, type);
movement = this.maybeBackOffFromEdge(movement, movementType);
Vec3 vec3d1 = this.collide(movement);
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
}
}
+ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER
public void positionRider(Entity passenger) {
this.positionRider(passenger, Entity::setPos);
}
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
return this.stringUUID;
}
+ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it!
public boolean isPushedByFluid() {
// Paper start
return this.pushedByWater();
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- 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 {
protected float rotOffs;
protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER
protected int deathScore;
public float lastHurt;
- protected boolean jumping;
+ public boolean jumping; // Paper protected -> public
@ -231,51 +224,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected PathfinderMob(EntityType<? extends PathfinderMob> type, Level world) {
super(type, world);
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
@@ -0,0 +0,0 @@ public abstract class Goal {
public void start() {}
- public void stop() {}
+ public void stop() {
+ onTaskReset(); // Paper
+ }
+ public void onTaskReset() {} // Paper
public void tick() {}
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -0,0 +0,0 @@ public class GoalSelector {
}
};
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap(Goal.Flag.class);
- private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet();
+ private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet(); private Set<WrappedGoal> getTasks() { return availableGoals; }// Paper - OBFHELPER
private final Supplier<ProfilerFiller> profiler;
private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
- private int newGoalRate = 3;
+ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER
+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO
private int tickCount;
private int newGoalRate = 3;
+ private int curRate;
public GoalSelector(Supplier<ProfilerFiller> profiler) {
this.profiler = profiler;
@@ -0,0 +0,0 @@ public class GoalSelector {
this.availableGoals.add(new WrappedGoal(priority, goal));
this.availableGoals.clear();
}
+ // Paper start
+ public boolean inactiveTick() {
+ incRate();
+ return getCurRate() % getTickRate() == 0;
+ this.curRate++;
+ return this.curRate % this.newGoalRate == 0;
+ }
+ public boolean hasTasks() {
+ for (WrappedGoal task : getTasks()) {
+ for (WrappedGoal task : this.availableGoals) {
+ if (task.isRunning()) {
+ return true;
+ }
@ -283,26 +254,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return false;
+ }
+ // Paper end
+
public void removeGoal(Goal goal) {
this.availableGoals.stream().filter((pathfindergoalwrapped) -> {
return pathfindergoalwrapped.getGoal() == goal;
this.availableGoals.stream().filter((wrappedGoal) -> {
return wrappedGoal.getGoal() == goal;
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelReader;
public abstract class MoveToBlockGoal extends Goal {
- protected final PathfinderMob mob;
+ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER
public final double speedModifier;
@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal {
protected int nextStartTick;
protected int tryTicks;
private int maxStayTicks;
- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER
+ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER
- protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER
+ protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; mob.movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER
private boolean reachedTarget;
private final int searchRange;
private final int verticalSearchRange;
@ -312,63 +276,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ // Paper start - activation range improvements
+ @Override
+ public void onTaskReset() {
+ super.onTaskReset();
+ public void stop() {
+ super.stop();
+ setTargetPosition(BlockPos.ZERO);
+ }
+ // Paper end
public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) {
this.blockPos = BlockPos.ZERO;
this.mob = mob;
@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal {
blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1);
if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) {
this.blockPos = blockposition_mutableblockposition;
+ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper
mutableBlockPos.setWithOffset(blockPos, m, k - 1, n);
if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level, mutableBlockPos)) {
this.blockPos = mutableBlockPos;
+ setTargetPosition(mutableBlockPos.immutable()); // Paper
return true;
}
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
@@ -0,0 +0,0 @@ public class WrappedGoal extends Goal {
return this.goal.getFlags();
}
+ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER
public boolean isRunning() {
return this.isRunning;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
@@ -0,0 +0,0 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
return this.caravanTail != null;
}
+ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER
public boolean inCaravan() {
return this.caravanHead != null;
}
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
@@ -0,0 +0,0 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan
return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag);
}
+ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER
public int getUnhappyCounter() {
return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER);
}
+ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER
public void setUnhappyCounter(int ticks) {
this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks);
}
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
@ -380,17 +303,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) {
- this.customServerAiStep();
+ // Paper start
+ if (this.getUnhappy() > 0) {
+ this.setUnhappy(this.getUnhappy() - 1);
}
+ if (this.getUnhappyCounter() > 0) {
+ this.setUnhappyCounter(this.getUnhappyCounter() - 1);
+ }
+ if (this.isEffectiveAi()) {
+ if (level.spigotConfig.tickInactiveVillagers) {
+ this.customServerAiStep();
+ } else {
+ this.mobTick(true);
+ }
+ }
+ doReputationTick();
}
+ maybeDecayGossip();
+ // Paper end
+
super.inactiveTick();
@ -424,14 +347,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
super.customServerAiStep();
}
@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
}
+ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER
private void maybeDecayGossip() {
long i = this.level.getGameTime();
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
@ -456,11 +371,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@
package org.spigotmc;
import java.util.Collection;
-import java.util.Collection;
+import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.FlyingMob;
import net.minecraft.world.entity.LightningBolt;
@ -478,7 +392,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.boss.wither.WitherBoss;
+import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.entity.monster.Creeper;
-import net.minecraft.world.entity.monster.Monster;
@ -497,7 +410,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import co.aikar.timings.MinecraftTimings;
+import net.minecraft.world.entity.schedule.Activity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.phys.AABB;
-import co.aikar.timings.MinecraftTimings;
@ -590,15 +502,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|| entity instanceof Player
|| entity instanceof ThrowableProjectile
|| entity instanceof EnderDragon
@@ -0,0 +0,0 @@ public class ActivationRange
|| entity instanceof AbstractHurtingProjectile
|| entity instanceof LightningBolt
|| entity instanceof PrimedTnt
- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks
+ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks
|| entity instanceof EndCrystal
|| entity instanceof FireworkRocketEntity
|| entity instanceof ThrownTrident )
@@ -0,0 +0,0 @@ public class ActivationRange
final int raiderActivationRange = world.spigotConfig.raiderActivationRange;
final int animalActivationRange = world.spigotConfig.animalActivationRange;
@ -635,45 +538,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange );
+ // Paper end
int i = Mth.floor( maxBB.minX / 16.0D );
int j = Mth.floor( maxBB.maxX / 16.0D );
@@ -0,0 +0,0 @@ public class ActivationRange
{
for ( int j1 = k; j1 <= l; ++j1 )
{
- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 );
+ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper
if ( chunk != null )
{
activateChunkEntities( chunk );
@@ -0,0 +0,0 @@ public class ActivationRange
*/
private static void activateChunkEntities(LevelChunk chunk)
{
- for ( java.util.List<Entity> slice : chunk.entitySlices )
- {
- for ( Entity entity : (Collection<Entity>) slice )
+ // Paper start
+ Entity[] rawData = chunk.entities.getRawData();
+ for (int i = 0; i < chunk.entities.size(); i++) {
+ Entity entity = rawData[i];
+ //for ( Entity entity : (Collection<Entity>) slice )
+ // Paper end
{
- if ( MinecraftServer.currentTick > entity.activatedTick )
- {
- if ( entity.defaultActivationState )
- {
- entity.activatedTick = MinecraftServer.currentTick;
- continue;
- }
- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) )
- {
+ if (MinecraftServer.currentTick > entity.activatedTick) {
+ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper
entity.activatedTick = MinecraftServer.currentTick;
}
}
world.getEntities().get(maxBB, ActivationRange::activateEntity);
}
@@ -0,0 +0,0 @@ public class ActivationRange
* @param entity
* @return
@ -694,7 +560,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
// quick checks.
- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 )
+ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper
+ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper
{
- return true;
+ return 100; // Paper
@ -780,7 +646,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive
- return true;
+ return 20; // Paper
}
+ }
+ // Paper start
+ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) {
+ return 0;
@ -788,7 +654,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (entity instanceof Pillager) {
+ Pillager pillager = (Pillager) entity;
+ // TODO:?
+ }
}
+ // Paper end
}
- return false;
@ -797,7 +663,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
/**
@@ -0,0 +0,0 @@ public class ActivationRange
if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) {
if ( entity instanceof FireworkRocketEntity ) {
return true;
}
+ // Paper start - special case always immunities
@ -821,7 +687,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 )
{
// Check immunities every 20 ticks.
- if ( checkEntityImmunities( entity ) )
- if ( ActivationRange.checkEntityImmunities( entity ) )
- {
- // Triggered some sort of immunity, give 20 full ticks before we check again.
- entity.activatedTick = MinecraftServer.currentTick + 20;
@ -837,8 +703,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
}
// Add a little performance juice to active entities. Skip 1/4 if not immune.
- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) )
+ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper
- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) )
+ } else if ( entity.tickCount % 4 == 0 && ActivationRange.checkEntityImmunities( entity ) < 0 ) // Paper
{
isActive = false;
}
@ -873,36 +739,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean tickInactiveVillagers = true;
private void activationRange()
{
+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper
animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange );
monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange );
raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange );
miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange );
+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", this.animalActivationRange) != this.animalActivationRange; // Paper
this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange );
this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange );
this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange );
this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange );
+ // Paper start
+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange );
+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange );
+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange );
+ this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange );
+ this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange );
+ this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange );
+
+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals);
+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery);
+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor);
+ this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals);
+ this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery);
+ this.wakeUpInactiveAnimalsFor = this.getInt("entity-activation-range.wake-up-inactive.animals-for", this.wakeUpInactiveAnimalsFor);
+
+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters);
+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery);
+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor);
+ this.wakeUpInactiveMonsters = this.getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", this.wakeUpInactiveMonsters);
+ this.wakeUpInactiveMonstersEvery = this.getInt("entity-activation-range.wake-up-inactive.monsters-every", this.wakeUpInactiveMonstersEvery);
+ this.wakeUpInactiveMonstersFor = this.getInt("entity-activation-range.wake-up-inactive.monsters-for", this.wakeUpInactiveMonstersFor);
+
+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers);
+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery);
+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor);
+ this.wakeUpInactiveVillagers = this.getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", this.wakeUpInactiveVillagers);
+ this.wakeUpInactiveVillagersEvery = this.getInt("entity-activation-range.wake-up-inactive.villagers-every", this.wakeUpInactiveVillagersEvery);
+ this.wakeUpInactiveVillagersFor = this.getInt("entity-activation-range.wake-up-inactive.villagers-for", this.wakeUpInactiveVillagersFor);
+
+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying);
+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery);
+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor);
+ this.wakeUpInactiveFlying = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", this.wakeUpInactiveFlying);
+ this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery);
+ this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor);
+
+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter );
+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor );
+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic );
+ this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter );
+ this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor );
+ this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic );
+ // Paper end
tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers );
log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers );
this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers );
this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers );
}

View file

@ -10,7 +10,7 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524
return;
}
@ -21,15 +21,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand);
if (enuminteractionresult.shouldSwing()) {
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- 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 {
return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem());
}
+ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER
public ItemStack getItemInHand(InteractionHand hand) {
if (hand == InteractionHand.MAIN_HAND) {
return this.getItemBySlot(EquipmentSlot.MAINHAND);

View file

@ -10,28 +10,16 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -0,0 +0,0 @@ import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonWriter;
+import net.minecraft.core.BlockPos;
+import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
-import net.minecraft.world.entity.Entity;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.ChunkPos;
-import net.minecraft.server.MCUtil;
+import net.minecraft.world.level.chunk.LevelChunk;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Bukkit;
import net.minecraft.resources.ResourceLocation;
@@ -0,0 +0,0 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.CraftServer;
@ -40,8 +28,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.entity.Player;
import java.io.File;
@@ -0,0 +0,0 @@ import java.io.PrintStream;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.ArrayDeque;
@ -57,14 +43,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public class PaperCommand extends Command {
private static final String BASE_PERM = "bukkit.command.paper.";
- private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build();
+ private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build();
- private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build();
+ private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build();
public PaperCommand(String name) {
super(name);
@@ -0,0 +0,0 @@ public class PaperCommand extends Command {
case "syncloadinfo":
this.doSyncLoadInfo(sender, args);
case "chunkinfo":
doChunkInfo(sender, args);
break;
+ case "fixlight":
+ this.doFixLight(sender, args);
@ -73,9 +59,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set)
case "version":
@@ -0,0 +0,0 @@ public class PaperCommand extends Command {
return true;
}
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete.");
}
+ private void doFixLight(CommandSender sender, String[] args) {
+ if (!(sender instanceof Player)) {
+ sender.sendMessage("Only players can use this command");
@ -97,7 +83,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ServerLevel world = (ServerLevel) handle.level;
+ ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine();
+
+ BlockPos center = MCUtil.toBlockPosition(player.getLocation());
+ net.minecraft.core.BlockPos center = MCUtil.toBlockPosition(player.getLocation());
+ Deque<ChunkPos> queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius));
+ updateLight(sender, world, lightengine, queue);
+ }
@ -114,7 +100,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ updateLight(sender, world, lightengine, queue);
+ return;
+ }
+ LevelChunk chunk = (LevelChunk) either.left().orElse(null);
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null);
+ if (chunk == null) {
+ updateLight(sender, world, lightengine, queue);
+ return;
@ -126,7 +112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int y = 0; y < world.getHeight(); y++) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ BlockPos pos = new BlockPos(cx + x, y, cz + z);
+ net.minecraft.core.BlockPos pos = new net.minecraft.core.BlockPos(cx + x, y, cz + z);
+ lightengine.checkBlock(pos);
+ }
+ }
@ -136,7 +122,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (visibleChunk != null) {
+ world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> {
+ MinecraftServer.getServer().processQueue.add(() -> {
+ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false);
+ visibleChunk.broadcast(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(chunk.getPos(), lightengine, null, null, true), false);
+ updateLight(sender, world, lightengine, queue);
+ });
+ });
@ -146,10 +132,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize);
+ }, MinecraftServer.getServer());
+ }
+
private void doSyncLoadInfo(CommandSender sender, String[] args) {
if (!SyncLoadFinder.ENABLED) {
sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set.");
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
@ -158,25 +141,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ public void sendPacketToTrackedPlayers(Packet<?> packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER
private void broadcast(Packet<?> packet, boolean onlyOnWatchDistanceEdge) {
// Paper start - per player view distance
// there can be potential desync with player's last mapped section and the view distance map, so use the
- private void broadcast(Packet<?> packet, boolean onlyOnWatchDistanceEdge) {
+ public void broadcast(Packet<?> packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public
this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> {
entityplayer.connection.send(packet);
});
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ProcessorHandle<Runnable> mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell);
private final ChunkTaskPriorityQueueSorter queueSorter;
private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> worldgenMailbox;
private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mainThreadMailbox;
+ // Paper start
+ final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mailboxLight;
+ public void addLightTask(ChunkHolder playerchunk, Runnable run) {
+ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run));
+ }
+ // Paper end
public final ChunkProgressListener progressListener;
private final ChunkStatusUpdateListener chunkStatusListener;
public final ChunkMap.ChunkDistanceManager distanceManager;
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.progressListener = worldGenerationProgressListener;
- ProcessorMailbox<Runnable> threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light");
+ ProcessorMailbox<Runnable> lightthreaded; ProcessorMailbox<Runnable> threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper
this.chunkStatusListener = chunkStatusChangeListener;
- ProcessorMailbox<Runnable> threadedmailbox1 = ProcessorMailbox.create(executor, "light");
+ ProcessorMailbox<Runnable> lightthreaded; ProcessorMailbox<Runnable> threadedmailbox1 = lightthreaded = ProcessorMailbox.create(executor, "light"); // Paper
this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE);
this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE);
this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false);
this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false);
+ this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper
this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false));
this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper
this.overworldDataStorage = supplier;
this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor);
this.overworldDataStorage = persistentStateManagerFactory;

View file

@ -16,8 +16,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public boolean stillValid(Player player) {
- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F;
+ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754
- return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F;
+ return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754
}
@Override
private boolean hasChest(AbstractHorse entityhorseabstract) {

View file

@ -22,8 +22,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) {
+ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check
- if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) {
+ if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check
this.move(MoverType.SELF, this.getDeltaMovement());
float f1 = 0.98F;

View file

@ -22,4 +22,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
final BlockPos pos = new BlockPos(x, y, z);
for (BlockFace dir : faces) {
net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir)));
net.minecraft.world.level.block.state.BlockState nmsBlock = this.world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir)));

View file

@ -8,11 +8,11 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
+ setShiftKeyDown(false); // Paper - fix MC-10657
+ setShiftKeyDown(false); // Paper - fix MC-10657
+
// CraftBukkit start
PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld());

View file

@ -0,0 +1,165 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 02:17:54 -0600
Subject: [PATCH] Generator Settings
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
private void disableRelativeProjectileVelocity() {
disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false);
}
+
+ public boolean generateFlatBedrock;
+ private void generatorSettings() {
+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false);
+ }
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
this.markPositionReplaceable(pos);
- return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level));
+ return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level)); // Paper - add level
// Paper start - Async chunk io
};
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> ret = new CompletableFuture<>();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess {
return GameEventDispatcher.NOOP;
}
+ // Paper start
+ default boolean generateFlatBedrock() {
+ if (this instanceof ProtoChunk) {
+ return ((ProtoChunk)this).level.paperConfig.generateFlatBedrock;
+ } else if (this instanceof LevelChunk) {
+ return ((LevelChunk)this).level.paperConfig.generateFlatBedrock;
+ } else {
+ return false;
+ }
+ }
+ // Paper end
+
BlockState getType(final int x, final int y, final int z); // Paper
@Nullable
BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -0,0 +0,0 @@ public class ImposterProtoChunk extends ProtoChunk {
private final LevelChunk wrapped;
public ImposterProtoChunk(LevelChunk wrapped) {
- super(wrapped.getPos(), UpgradeData.EMPTY, wrapped);
+ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped, wrapped.level); // Paper - add level
this.wrapped = wrapped;
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess {
private long inhabitedTime;
private final Map<GenerationStep.Carving, BitSet> carvingMasks = new Object2ObjectArrayMap<>();
private volatile boolean isLightCorrect;
+ final net.minecraft.world.level.Level level; // Paper - Add level
- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) {
+ // Paper start - add level
+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); }
+ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) {
+ // Paper end
this(pos, upgradeData, (LevelChunkSection[])null, new ProtoTickList<>((block) -> {
return block == null || block.defaultBlockState().isAir();
}, pos, world), new ProtoTickList<>((fluid) -> {
return fluid == null || fluid == Fluids.EMPTY;
- }, pos, world), world);
+ }, pos, world), world, level); // Paper - add level
}
- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world) {
+ // Paper start - add level
+ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world) { this(pos, upgradeData, levelChunkSections, blockTickScheduler, fluidTickScheduler, world, null); }
+ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) {
+ this.level = level;
+ // Paper end
this.chunkPos = pos;
this.upgradeData = upgradeData;
this.blockTicks = blockTickScheduler;
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 {
// CraftBukkit end
});
} else {
- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world);
+ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level
protochunk.setBiomes(biomestorage);
object = protochunk;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
int j = chunk.getPos().getMinBlockZ();
NoiseGeneratorSettings noiseGeneratorSettings = this.settings.get();
int k = noiseGeneratorSettings.noiseSettings().minY();
- int l = k + noiseGeneratorSettings.getBedrockFloorPosition();
- int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition();
+ int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); final int floorHeight = k; // Paper
+ int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); final int roofHeight = l; // Paper
int n = 5;
int o = chunk.getMinBuildHeight();
int p = chunk.getMaxBuildHeight();
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
for(BlockPos blockPos : BlockPos.betweenClosed(i, 0, j, i + 15, 0, j + 15)) {
if (bl) {
for(int q = 0; q < 5; ++q) {
- if (q <= random.nextInt(5)) {
+ if (q <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof
chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), m - q, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
}
}
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
if (bl2) {
for(int r = 4; r >= 0; --r) {
- if (r <= random.nextInt(5)) {
+ if (r <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor
chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), l + r, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
}
}
@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
if (l <= 0) {
return CompletableFuture.completedFuture(chunk);
} else {
- int m = chunk.getSectionIndex(l * this.cellHeight - 1 + i);
+ int mStart = chunk.getSectionIndex(l * this.cellHeight - 1 + i); // Paper - decompile fix
int n = chunk.getSectionIndex(i);
return CompletableFuture.supplyAsync(() -> {
Set<LevelChunkSection> set = Sets.newHashSet();
ChunkAccess var16;
try {
- for(int m = m; m >= n; --m) {
+ for(int m = mStart; m >= n; --m) { // Paper - decompile fix
LevelChunkSection levelChunkSection = chunk.getOrCreateSection(m);
levelChunkSection.acquire();
set.add(levelChunkSection);

View file

@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -0,0 +0,0 @@ public class ChunkSerializer {
private static final Logger LOGGER = LogManager.getLogger();
public ChunkSerializer() {}
+ // Paper start - guard against serializing mismatching coordinates
+ // TODO Note: This needs to be re-checked each update
@ -25,38 +25,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ChunkSerializer {
// Paper end
ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator();
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level");
- CompoundTag nbttagcompound1 = nbt.getCompound("Level");
- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos"));
+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate
+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate
+ CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate
+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate
if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) {
ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1);
if (!Objects.equals(pos, chunkcoordintpair1)) {
ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1);
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -0,0 +0,0 @@ import net.minecraft.SharedConstants;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.datafix.DataFixTypes;
@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable {
public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
// Paper start - async chunk io
public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException {
+ // Paper start
+ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) {
+ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null;
+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString()
+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world)));
+ if (!chunkPos.equals(ChunkSerializer.getChunkCoordinate(nbt))) {
+ String world = (this instanceof net.minecraft.server.level.ChunkMap) ? ((net.minecraft.server.level.ChunkMap)this).level.getWorld().getName() : null;
+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkPos.toString()
+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbt).toString() + (world == null ? " for an unknown world" : (" for world: " + world)));
+ }
+ // Paper end
this.regionFileCache.write(chunkcoordintpair, nbttagcompound);
this.regionFileCache.write(chunkPos, nbt);
// Paper end - Async chunk loading
if (this.legacyStructureHandler != null) {
synchronized (this.persistentDataLock) { // Paper - Async chunk loading

View file

@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
private void zombieVillagerInfectionChance() {
zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance);
disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents);
log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled"));
}
+
+ public int lightQueueSize = 20;
@ -27,6 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ lightQueueSize = getInt("light-queue-size", lightQueueSize);
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java

View file

@ -10,15 +10,6 @@ diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/ma
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- 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 {
private int noJumpDelay;
private float absorptionAmount;
public ItemStack useItem; // Paper - public
- protected int useItemRemaining;
+ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER
protected int fallFlyTicks;
private BlockPos lastPos;
private Optional<BlockPos> lastClimbablePos;
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
}
@ -32,19 +23,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.isUsingItem()) {
if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
this.triggerItemUseEffects(this.useItem, 5);
}
if (this.shouldTriggerItemUseEffects()) {
this.triggerItemUseEffects(stack, 5);
}
-
- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !stack.useOnRelease()) {
+ // Paper start - lag compensate eating
+ // we add 1 to the expected time to avoid lag compensating when we should not
+ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000));
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) {
+ this.useItemRemaining = 0;
+ // Paper end
this.completeUsingItem();
}
- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) {
+ // Paper start - lag compensate eating
+ // we add 1 to the expected time to avoid lag compensating when we should not
+ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000));
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) {
+ this.setEatTimeTicks(0);
+ // Paper end
this.completeUsingItem();
}
} else {
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag

View file

@ -18,6 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange);
+ }
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java
@ -25,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class NearestAttackableTargetGoal<T extends LivingEntity> extends TargetG
this.randomInterval = reciprocalChance;
this.setFlags(EnumSet.of(Goal.Flag.TARGET));
this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate);
this.targetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(targetPredicate);
+ if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper
}
@ -34,24 +35,15 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingCond
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
@@ -0,0 +0,0 @@ import java.util.function.Predicate;
import javax.annotation.Nullable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
+import net.minecraft.world.entity.ai.attributes.AttributeInstance;
+import net.minecraft.world.entity.ai.attributes.Attributes;
public class TargetingConditions {
@@ -0,0 +0,0 @@ public class TargetingConditions {
if (this.range > 0.0D) {
double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
- double d1 = Math.max(this.range * d0, 2.0D);
+ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper
double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
if (d2 > d1 * d1) {
double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
- double e = Math.max(this.range * d, 2.0D);
+ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper
double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
if (f > e * e) {
return false;
@@ -0,0 +0,0 @@ public class TargetingConditions {
return true;
}
@ -66,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ private double getFollowRange(LivingEntity entityliving) {
+ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE);
+ net.minecraft.world.entity.ai.attributes.AttributeInstance attributeinstance = entityliving.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE);
+ return attributeinstance == null ? 16.0D : attributeinstance.getValue();
+ }
+ // Paper end

View file

@ -16,9 +16,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> {
return pair(rule, world.getWorld().getGameRuleValue(rule));
})),
- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance())
+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()),
+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance())
- pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance())
+ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()),
+ pair("notick-viewdistance", world.getChunkSource().chunkMap.getEffectiveNoTickViewDistance())
));
}));
@ -27,8 +27,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative);
phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs);
private void lightQueueSize() {
lightQueueSize = getInt("light-queue-size", lightQueueSize);
}
+
+ public int noTickViewDistance;
@ -36,6 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1);
+ }
}
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
@ -55,9 +56,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -0,0 +0,0 @@ public class ChunkHolder {
}
// Paper end - optimise isOutsideOfRange
boolean isUpdateQueued = false; // Paper
private final ChunkMap chunkMap; // Paper
+ // Paper start - no-tick view distance
+ public final LevelChunk getSendingChunk() {
+ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used
@ -69,23 +70,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return null;
+ }
+ // Paper end - no-tick view distance
+
public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
@@ -0,0 +0,0 @@ public class ChunkHolder {
}
public void blockChanged(BlockPos blockposition) {
public void blockChanged(BlockPos pos) {
- LevelChunk chunk = this.getTickingChunk();
+ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
if (chunk != null) {
byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY());
int i = this.levelHeightAccessor.getSectionIndex(pos.getY());
@@ -0,0 +0,0 @@ public class ChunkHolder {
}
public void sectionLightChanged(LightLayer type, int y) {
public void sectionLightChanged(LightLayer lightType, int y) {
- LevelChunk chunk = this.getTickingChunk();
+ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ChunkHolder {
}
private void broadcast(Packet<?> packet, boolean onlyOnWatchDistanceEdge) {
public void broadcast(Packet<?> packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public
- this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> {
- entityplayer.connection.send(packet);
- });
@ -119,8 +119,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ int viewDistance = viewDistanceMap.getLastViewDistance(player);
+ long lastPosition = viewDistanceMap.getLastCoordinate(player);
+
+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x);
+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z);
+ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - this.pos.x);
+ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - this.pos.z);
+
+ if (Math.max(distX, distZ) == viewDistance) {
+ player.connection.send(packet);
@ -147,40 +147,19 @@ diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/j
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket;
+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
import net.minecraft.network.protocol.game.DebugPackets;
import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.progress.ChunkProgressListener;
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.util.CsvOutput;
import net.minecraft.util.Mth;
import net.minecraft.util.profiling.ProfilerFiller;
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private boolean modified;
private final ChunkTaskPriorityQueueSorter queueSorter;
private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> worldgenMailbox;
- private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mainThreadMailbox;
+ public final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mainThreadMailbox; // Paper - private -> public
+ // Paper start
+ final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mailboxLight;
+ public void addLightTask(ChunkHolder playerchunk, Runnable run) {
+ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run));
+ }
+ // Paper end
public final ChunkProgressListener progressListener;
public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER
private final AtomicInteger tickingGenerated;
// Paper start
final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mailboxLight;
public void addLightTask(ChunkHolder playerchunk, Runnable run) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap;
// Paper end - optimise PlayerChunkMap#isOutsideRange
// Paper start - distance maps
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
+ // Paper start - no-tick view distance
+ int noTickViewDistance;
+ public final int getRawNoTickViewDistance() {
@ -200,15 +179,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
void addPlayerToDistanceMaps(ServerPlayer player) {
int chunkX = MCUtil.getChunkCoordinate(player.getX());
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start - optimise PlayerChunkMap#isOutsideRange
this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE);
// Paper end - optimise PlayerChunkMap#isOutsideRange
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
// Note: players need to be explicitly added to distance maps before they can be updated
+ // Paper start - no-tick view distance
+ int effectiveTickViewDistance = this.getEffectiveViewDistance();
+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
+
+ if (!this.cannotLoadChunks(player)) {
+ if (!this.skipPlayer(player)) {
+ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance);
+ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send)
+ }
@ -220,10 +197,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
void removePlayerFromDistanceMaps(ServerPlayer player) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.playerMobSpawnMap.remove(player);
this.playerChunkTickRangeMap.remove(player);
// Paper end - optimise PlayerChunkMap#isOutsideRange
+ // Paper start - no-tick view distance
+ this.playerViewDistanceBroadcastMap.remove(player);
+ this.playerViewDistanceTickMap.remove(player);
@ -232,15 +206,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
void updateMaps(ServerPlayer player) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start - optimise PlayerChunkMap#isOutsideRange
this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE);
// Paper end - optimise PlayerChunkMap#isOutsideRange
int chunkX = MCUtil.getChunkCoordinate(player.getX());
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
// Note: players need to be explicitly added to distance maps before they can be updated
+ // Paper start - no-tick view distance
+ int effectiveTickViewDistance = this.getEffectiveViewDistance();
+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
+
+ if (!this.cannotLoadChunks(player)) {
+ if (!this.skipPlayer(player)) {
+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance);
+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send)
+ }
@ -253,9 +226,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Paper end
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
});
// Paper end - optimise PlayerChunkMap#isOutsideRange
this.overworldDataStorage = persistentStateManagerFactory;
this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world);
this.setViewDistance(viewDistance);
+ // Paper start - no-tick view distance
+ this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance);
+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
@ -297,10 +270,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - no-tick view distance
}
public void updatePlayerMobTypeMap(Entity entity) {
private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
completablefuture1.thenAcceptAsync((either) -> {
either.mapLeft((chunk) -> {
either.ifLeft((chunk) -> {
this.tickingGenerated.getAndIncrement();
- Packet<?>[] apacket = new Packet[2];
-
@ -308,7 +281,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.playerLoadedChunk(entityplayer, apacket, chunk);
- });
+ // Paper - no-tick view distance - moved to Chunk neighbour update
return Either.left(chunk);
});
}, (runnable) -> {
- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
@ -341,7 +313,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> {
- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true);
- int l = ChunkMap.checkerboardDistance(chunkcoordintpair, entityplayer, true);
- boolean flag = l <= k;
- boolean flag1 = l <= this.viewDistance;
+ // Paper start - no-tick view distance
@ -356,20 +328,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set
+ for (ServerPlayer player : this.level.players) {
+ ServerGamePacketListenerImpl connection = player.connection;
+ net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection;
+ if (connection != null) {
+ // moved in from PlayerList
+ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance));
+ connection.send(new net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket(loadViewDistance));
+ }
+ this.updateMaps(player);
+ // Paper end - no-tick view distance
}
}
-
}
+ // Paper end - no-tick view distance
protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet<?>[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) {
if (player.level == this.level) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong());
@ -379,14 +347,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (chunk != null) {
this.playerLoadedChunk(player, packets, chunk);
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// Paper end - optimise isOutsideOfRange
+ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER
private boolean skipPlayer(ServerPlayer player) {
return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS);
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.removePlayerFromDistanceMaps(player); // Paper - distance maps
}
@ -403,11 +363,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
SectionPos sectionposition = SectionPos.of((Entity) entityplayer);
SectionPos sectionposition = SectionPos.of((Entity) player);
entityplayer.setLastSectionPos(sectionposition);
- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z()));
+ // Paper - distance map handles this now
player.setLastSectionPos(sectionposition);
- player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z()));
+ // player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); // Paper - distance map handles this now
return sectionposition;
}
@ -420,49 +380,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
k1 = Math.min(i, i1) - this.viewDistance;
l1 = Math.min(j, j1) - this.viewDistance;
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
for (int k2 = k1; k2 <= i2; ++k2) {
for (int l2 = l1; l2 <= j2; ++l2) {
- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2);
- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance;
- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance;
+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2);
+ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance;
+ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance;
- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4);
+ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4);
}
}
} else {
- ChunkPos chunkcoordintpair1;
+ ChunkCoordIntPair chunkcoordintpair1;
boolean flag5;
boolean flag6;
for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) {
for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) {
- chunkcoordintpair1 = new ChunkPos(k1, l1);
+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1);
flag5 = true;
flag6 = false;
- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false);
+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false);
}
}
for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) {
for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) {
- chunkcoordintpair1 = new ChunkPos(k1, l1);
+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1);
flag5 = false;
flag6 = true;
- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true);
+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true);
}
}
- }
+ }*/ // Paper end - replaced by distance map
}
+ */ // Paper end - replaced by distance map
this.updateMaps(player); // Paper - distance maps
@ -470,14 +391,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public Stream<ServerPlayer> getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) {
- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> {
- int i = b(chunkcoordintpair, entityplayer, true);
- return this.playerMap.getPlayers(chunkPos.toLong()).filter((entityplayer) -> {
- int i = ChunkMap.checkerboardDistance(chunkPos, entityplayer, true);
+ // Paper start - per player view distance
+ // there can be potential desync with player's last mapped section and the view distance map, so use the
+ // view distance map here.
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos);
- return i > this.viewDistance ? false : !flag || i == this.viewDistance;
- return i > this.viewDistance ? false : !onlyOnWatchDistanceEdge || i == this.viewDistance;
- });
+ if (inRange == null) {
+ return Stream.empty();
@ -516,15 +437,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - per player view distance
}
public void addEntity(Entity entity) { // Paper - protected -> public
protected void addEntity(Entity entity) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
- private final void sendChunk(ServerPlayer entityplayer, Packet<?>[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER
- private void playerLoadedChunk(ServerPlayer player, Packet<?>[] packets, LevelChunk chunk) {
+ // Paper start
+ private static int getLightMask(final LevelChunk chunk) {
+ final ChunkSection[] chunkSections = chunk.getSections();
+ final net.minecraft.world.level.chunk.LevelChunkSection[] chunkSections = chunk.getSections();
+ int mask = 0;
+
+ for (int i = 0; i < chunkSections.length; ++i) {
@ -535,7 +456,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d.
+
+ */
+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i;
+ mask |= (net.minecraft.world.level.chunk.LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i;
+ }
+
+ return mask;
@ -563,19 +484,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end
+
+ public final void sendChunk(ServerPlayer entityplayer, Packet<?>[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER
private void playerLoadedChunk(ServerPlayer player, Packet<?>[] packets, LevelChunk chunk) {
+ public void playerLoadedChunk(ServerPlayer player, Packet<?>[] packets, LevelChunk chunk) { // Paper - private -> public
if (packets[0] == null) {
packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk);
ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong());
- if (playerchunk != null && playerchunk.getTickingChunk() != null) {
+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance
flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance;
}
}
packets[0] = new ClientboundLevelChunkPacket(chunk);
packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true);
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
@ -604,15 +516,14 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
+ boolean needsChunkCenterUpdate; // Paper - no-tick view distance
+
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) {
super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile);
this.respawnDimension = Level.OVERWORLD;
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
@ -633,8 +544,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot
+ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance
entityplayer1.setLevel(worldserver1);
entityplayer1.removed = false;
entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot));
entityplayer1.unsetRemoved();
entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot()));
@@ -0,0 +0,0 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
@ -667,27 +578,23 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
@@ -0,0 +0,0 @@ import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.protocol.Packet;
import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.ChunkTaskPriorityQueueSorter;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.level.TicketType;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.util.profiling.ProfilerFiller;
@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
}
protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) {
+ // Paper start - no-tick view distance
+ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource();
+ ServerChunkCache chunkProviderServer = ((ServerLevel)this.level).getChunkSource();
+ ChunkMap chunkMap = chunkProviderServer.chunkMap;
+ // this code handles the addition of ticking tickets - the distance map handles the removal
+ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) {
@ -696,7 +603,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ chunkProviderServer.mainThreadProcessor.execute(() -> {
+ // double check that this condition still holds.
+ if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) {
+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update
+ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update
+ }
+ });
+ }
@ -711,7 +618,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (!LevelChunk.this.areNeighboursLoaded(1)) {
+ return;
+ }
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey);
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<net.minecraft.server.level.ServerPlayer> inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey);
+ if (inRange == null) {
+ return;
+ }
@ -721,11 +628,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ Packet[] chunkPackets = new Packet[2];
+ for (int index = 0, len = backingSet.length; index < len; ++index) {
+ Object temp = backingSet[index];
+ if (!(temp instanceof ServerPlayer)) {
+ if (!(temp instanceof net.minecraft.server.level.ServerPlayer)) {
+ continue;
+ }
+ ServerPlayer player = (ServerPlayer)temp;
+ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this);
+ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer)temp;
+ chunkMap.playerLoadedChunk(player, chunkPackets, LevelChunk.this);
+ }
+ })));
+ }
@ -736,10 +643,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final boolean isAnyNeighborsLoaded() {
@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
BlockState iblockdata = this.getBlockState(blockposition);
BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition);
BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.level, blockposition);
- this.world.setBlock(blockposition, iblockdata1, 20);
+ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here
- this.level.setBlock(blockposition, iblockdata1, 20);
+ this.level.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here
}
this.postProcessing[i].clear();
@ -747,14 +654,6 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/jav
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket;
import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.Ticket;
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
// Spigot start
@Override
@ -770,7 +669,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (viewDistance < 2 || viewDistance > 32) {
+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
+ }
+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ if (viewDistance != chunkMap.getEffectiveViewDistance()) {
+ chunkMap.setViewDistance(viewDistance);
+ }
@ -786,7 +685,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) {
+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
+ }
+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) {
+ chunkMap.setNoTickViewDistance(viewDistance);
+ }
@ -800,20 +699,12 @@ diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -0,0 +0,0 @@ import java.util.Collection;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.FlyingMob;
@@ -0,0 +0,0 @@ public class ActivationRange
maxRange = Math.max( maxRange, waterActivationRange );
maxRange = Math.max( maxRange, villagerActivationRange );
// Paper end
- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange );
+ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance
+ maxRange = Math.min( ( ((net.minecraft.server.level.ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance
for ( Player player : world.players() )
{

View file

@ -10,35 +10,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager;
// Paper end
+ // Paper start - optimise getPlayerByUUID
+ @Nullable
+ @Override
+ public Player getPlayerByUUID(UUID uuid) {
+ Entity player = this.entitiesByUuid.get(uuid);
+ return (player instanceof Player) ? (Player)player : null;
+ return this.getServer().getPlayerList().getPlayer(uuid);
+ }
+ // Paper end
+
// Add env and gen to constructor, WorldData -> WorldDataServer
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<net.minecraft.world.level.Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -0,0 +0,0 @@ public interface EntityGetter {
@Nullable
default Player getPlayerByUUID(UUID uuid) {
+ // Paper start - allow WorldServer to override
+ return this.getPlayerByUUID(uuid);
+ }
+ @Nullable
+ default Player getPlayerByUUID(UUID uuid) {
+ // Paper end
for (int i = 0; i < this.players().size(); ++i) {
Player entityhuman = (Player) this.players().get(i);
// Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error

View file

@ -30,23 +30,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled"));
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.entity.HopperBlockEntity;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
+ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
this.profiler.push(() -> {
return worldserver + " " + worldserver.dimension().location();
@ -70,28 +63,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
itemstack.setPopTime(this.getPopTime());
if (this.tag != null) {
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return list;
}
- @Override
- public <T extends Entity> List<T> getEntitiesOfClass(Class<? extends T> entityClass, AABB box, @Nullable Predicate<? super T> predicate) {
+ public <T extends Entity> List<T> getEntities(Class<? extends T> oclass, AABB axisalignedbb, @Nullable Predicate<? super T> predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER
+ @Override public <T extends Entity> List<T> getEntitiesOfClass(Class<? extends T> entityClass, AABB box, @Nullable Predicate<? super T> predicate) {
this.getProfiler().incrementCounter("getEntities");
int i = Mth.floor((box.minX - 2.0D) / 16.0D);
int j = Mth.ceil((box.maxX + 2.0D) / 16.0D);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
public void setCurrentChunk(LevelChunk chunk) {
this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null;
getMinecraftKey(); // Try to load if it doesn't exists.
return tileEntityKeyString;
}
+ static boolean IGNORE_TILE_UPDATES = false;
// Paper end
@ -102,57 +80,58 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void setChanged() {
if (this.level != null) {
+ if (IGNORE_TILE_UPDATES) return; // Paper
this.blockState = this.level.getBlockState(this.worldPosition);
this.level.blockEntityChanged(this.worldPosition, this);
if (!this.blockState.isAir()) {
BlockEntity.setChanged(this.level, this.worldPosition, this.blockState);
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java
@@ -0,0 +0,0 @@
package net.minecraft.world.level.block.entity;
import javax.annotation.Nullable;
+import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
@@ -0,0 +0,0 @@ public interface Hopper extends Container {
return Hopper.SUCK;
return SUCK;
}
- @Nullable
+ //@Nullable // Paper - it's annoying
Level getLevel();
+ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper
+ net.minecraft.world.level.Level getLevel();
+
+ default net.minecraft.core.BlockPos getBlockPosition() { return new net.minecraft.core.BlockPos(getLevelX(), getLevelY(), getLevelZ()); } // Paper
+
double getLevelX();
- double getLevelX();
+ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER
- double getLevelY();
+ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER
- double getLevelZ();
+ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER
}
double getLevelY();
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -0,0 +0,0 @@ package net.minecraft.world.level.block.entity;
import java.util.Iterator;
import java.util.List;
import java.util.function.BooleanSupplier;
-import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
-import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.HumanEntity;
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
return false;
}
+ // Paper start - Optimize Hoppers
+ private static boolean skipPullModeEventFire = false;
+ private static boolean skipPushModeEventFire = false;
+ public static boolean skipHopperEvents = false;
+
+ private boolean hopperPush(Container iinventory, Direction enumdirection) {
+ private static boolean hopperPush(Level level, BlockPos pos, Container iinventory, Direction enumdirection, HopperBlockEntity hopper) {
+ skipPushModeEventFire = skipHopperEvents;
+ boolean foundItem = false;
+ for (int i = 0; i < this.getContainerSize(); ++i) {
+ ItemStack item = this.getItem(i);
+ for (int i = 0; i < iinventory.getContainerSize(); ++i) {
+ ItemStack item = iinventory.getItem(i);
+ if (!item.isEmpty()) {
+ foundItem = true;
+ ItemStack origItemStack = item;
@ -165,13 +144,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // We only need to fire the event once to give protection plugins a chance to cancel this event
+ // Because nothing uses getItem, every event call should end up the same result.
+ if (!skipPushModeEventFire) {
+ itemstack = callPushMoveEvent(iinventory, itemstack);
+ itemstack = callPushMoveEvent(iinventory, itemstack, hopper);
+ if (itemstack == null) { // cancelled
+ origItemStack.setCount(origCount);
+ return false;
+ }
+ }
+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection);
+ final ItemStack itemstack2 = addItem(hopper, iinventory, itemstack, enumdirection);
+ final int remaining = itemstack2.getCount();
+ if (remaining != moved) {
+ origItemStack = origItemStack.cloneItemStack(true);
@ -179,7 +158,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (!origItemStack.isEmpty()) {
+ origItemStack.setCount(origCount - moved + remaining);
+ }
+ this.setItem(i, origItemStack);
+ hopper.setItem(i, origItemStack);
+ iinventory.setChanged();
+ return true;
+ }
@ -187,7 +166,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown
+ this.setCooldown(level.spigotConfig.hopperTransfer);
+ hopper.setCooldown(level.spigotConfig.hopperTransfer);
+ }
+ return false;
+ }
@ -233,16 +212,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return false;
+ }
+
+ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) {
+ private static ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack, HopperBlockEntity hopper) {
+ Inventory destinationInventory = getInventory(iinventory);
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(),
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(hopper.getOwner(false).getInventory(),
+ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true);
+ boolean result = event.callEvent();
+ if (!event.calledGetItem && !event.calledSetItem) {
+ skipPushModeEventFire = true;
+ }
+ if (!result) {
+ cooldownHopper(this);
+ cooldownHopper(hopper);
+ return null;
+ }
+
@ -296,58 +275,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ // Paper end
+
private boolean ejectItems() {
Container iinventory = this.getAttachedContainer();
private static boolean a(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit
Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata);
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (this.isFullContainer(iinventory, enumdirection)) {
if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) {
return false;
} else {
- for (int i = 0; i < this.getContainerSize(); ++i) {
+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest
+ for (int i = 0; i < this.getSize(); ++i) {
if (!this.getItem(i).isEmpty()) {
- ItemStack itemstack = this.getItem(i).copy();
+ ItemStack itemstack = this.getItem(i).cloneItemStack();
// ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection);
// CraftBukkit start - Call event when pushing items into other inventories
- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot
Inventory destinationInventory;
// Have to special case large chests as they work oddly
- if (iinventory instanceof CompoundContainer) {
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ if (iinventory instanceof InventoryLargeChest) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory);
} else {
destinationInventory = iinventory.getOwner().getInventory();
}
InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true);
- this.getLevel().getCraftServer().getPluginManager().callEvent(event);
+ this.getWorld().getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.setItem(i, itemstack);
- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
+ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
return false;
}
int origCount = event.getItem().getAmount(); // Spigot
+ return hopperPush(world, blockposition, iinventory, enumdirection, hopper); /* // Paper - disable rest
for (int i = 0; i < iinventory.getContainerSize(); ++i) {
if (!iinventory.getItem(i).isEmpty()) {
ItemStack itemstack = iinventory.getItem(i).copy();
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
// CraftBukkit end
if (itemstack1.isEmpty()) {
- iinventory.setChanged();
+ iinventory.update();
return true;
}
- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot
+ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot
this.setItem(i, itemstack);
}
}
@ -357,12 +296,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize());
}
- private boolean isFullContainer(Container inv, Direction enumdirection) {
- return getSlots(inv, enumdirection).allMatch((i) -> {
- ItemStack itemstack = inv.getItem(i);
private static boolean isFullContainer(Container inventory, Direction direction) {
- return HopperBlockEntity.getSlots(inventory, direction).allMatch((i) -> {
- ItemStack itemstack = inventory.getItem(i);
-
- return itemstack.getCount() >= itemstack.getMaxStackSize();
- });
+ return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams
}
private static boolean isEmptyContainer(Container inv, Direction facing) {
- return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> {
- return inv.getItem(i).isEmpty();
- });
+ // Paper start
+ return allMatch(inv, facing, IS_EMPTY_TEST);
+ }
+ private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate<ItemStack, Integer> test) {
+ if (iinventory instanceof WorldlyContainer) {
+ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) {
@ -379,10 +330,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ return true;
+ }
}
- return itemstack.getCount() >= itemstack.getMaxStackSize();
- });
+ private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate<ItemStack, Integer> test) {
+ if (iinventory instanceof WorldlyContainer) {
+ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) {
@ -402,106 +351,48 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ private static final java.util.function.BiPredicate<ItemStack, Integer> STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize();
+ private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty();
+
+ // Paper end
+
+ private boolean isFullContainer(Container inv, Direction enumdirection) {
+ // Paper start - no streams
+ return allMatch(inv, enumdirection, STACK_SIZE_TEST);
+ // Paper end
}
public static boolean suckInItems(Level world, Hopper hopper) {
Container iinventory = HopperBlockEntity.getSourceContainer(world, hopper);
private static boolean isEmptyContainer(Container inv, Direction facing) {
- return getSlots(inv, facing).allMatch((i) -> {
- return inv.getItem(i).isEmpty();
- });
+ return allMatch(inv, facing, IS_EMPTY_TEST);
}
public static boolean suckInItems(Hopper hopper) {
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (iinventory != null) {
Direction enumdirection = Direction.DOWN;
- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> {
- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection);
- return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> {
- return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot
+ // Paper start - optimize hoppers and remove streams
+ skipPullModeEventFire = skipHopperEvents;
+ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> {
+ return !HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> {
+ // Logic copied from below to avoid extra getItem calls
+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) {
+ if (!item.isEmpty() && canTakeItemFromContainer(iinventory, item, i, enumdirection)) {
+ return hopperPull(hopper, iinventory, item, i);
+ } else {
+ return false;
+ }
+ // Paper end
});
+ // Paper end
} else {
Iterator iterator = getItemsAtAndAbove(hopper).iterator();
Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator();
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {
+ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above
ItemStack itemstack = inventory.getItem(slot);
+ // Paper - method unused as logic is inlined above
private static boolean a(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot
ItemStack itemstack = iinventory.getItem(i);
- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) {
- ItemStack itemstack1 = itemstack.copy();
+ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins
+ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest
+ ItemStack itemstack1 = itemstack.cloneItemStack();
- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) {
+ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins
+ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest
ItemStack itemstack1 = itemstack.copy();
// ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null);
// CraftBukkit start - Call event on collection of items from inventories into the hopper
- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot
Inventory sourceInventory;
// Have to special case large chests as they work oddly
- if (inventory instanceof CompoundContainer) {
- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory);
+ if (iinventory instanceof InventoryLargeChest) {
+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory);
} else {
- sourceInventory = inventory.getOwner().getInventory();
+ sourceInventory = iinventory.getOwner().getInventory();
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false);
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false);
- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event);
+ ihopper.getWorld().getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
- inventory.setItem(slot, itemstack1);
+ iinventory.setItem(i, itemstack1);
- if (hopper instanceof HopperBlockEntity) {
- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot
- } else if (hopper instanceof MinecartHopper) {
- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot
+ if (ihopper instanceof TileEntityHopper) {
+ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot
+ } else if (ihopper instanceof EntityMinecartHopper) {
+ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot
}
return false;
}
int origCount = event.getItem().getAmount(); // Spigot
- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null);
+ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
// CraftBukkit end
if (itemstack2.isEmpty()) {
- inventory.setChanged();
+ iinventory.update();
return true;
}
- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot
- inventory.setItem(slot, itemstack1);
+ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot
itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot
- iinventory.setItem(i, itemstack1);
+ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations
}
@ -515,14 +406,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
itemEntity.level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return false;
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side);
}
+ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER
private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) {
return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing);
}
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
boolean flag1 = to.isEmpty();
@ -532,51 +415,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ IGNORE_TILE_UPDATES = false; // Paper
stack = ItemStack.EMPTY;
flag = true;
} else if (canMergeItems(itemstack1, stack)) {
} else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static List<ItemEntity> getItemsAtAndAbove(Hopper ihopper) {
- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> {
- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream();
public static List<ItemEntity> getItemsAtAndAbove(Level world, Hopper hopper) {
- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> {
- return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream();
- }).collect(Collectors.toList());
+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?!
+ Level world = ihopper.getLevel();
+ double d0 = ihopper.getX();
+ double d1 = ihopper.getY();
+ double d2 = ihopper.getZ();
+ double d0 = hopper.getLevelX();
+ double d1 = hopper.getLevelY();
+ double d2 = hopper.getLevelZ();
+ AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D);
+ return world.getEntities(ItemEntity.class, bb, Entity::isAlive);
+ return world.getEntitiesOfClass(ItemEntity.class, bb, Entity::isAlive);
+ // Paper end
}
@Nullable
public static Container getContainerAt(Level world, BlockPos blockposition) {
- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D);
+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper
public static Container getContainerAt(Level world, BlockPos pos) {
- return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D);
+ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper
}
+ public static Container getContainerAt(Level world, double x, double y, double z) { return getContainerAt(world, x, y, z, false); } // Paper - overload to default false
@Nullable
- public static Container getContainerAt(Level world, double x, double y, double z) {
+ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false
+ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper
- private static Container getContainerAt(Level world, double x, double y, double z) {
+ private static Container getContainerAt(Level world, double x, double y, double z, boolean optimizeEntities) {
Object object = null;
- BlockPos blockposition = new BlockPos(x, y, z);
+ BlockPos blockposition = new BlockPos(d0, d1, d2);
BlockPos blockposition = new BlockPos(x, y, z);
if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot
BlockState iblockdata = world.getBlockState(blockposition);
Block block = iblockdata.getBlock();
@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
- if (object == null) {
- List<Entity> list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR);
+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper
+ List<Entity> list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR);
List<Entity> list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR);
if (!list.isEmpty()) {
object = (Container) list.get(world.random.nextInt(list.size()));
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@ -584,7 +461,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@Override
public boolean isEmpty() {
this.unpackLootTable((Player) null);
this.unpackLootTable((Player)null);
- return this.getItems().stream().allMatch(ItemStack::isEmpty);
+ // Paper start
+ for (ItemStack itemStack : this.getItems()) {
@ -598,8 +475,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override
public ItemStack getItem(int slot) {
- this.unpackLootTable((Player) null);
- this.unpackLootTable((Player)null);
+ if (slot == 0) this.unpackLootTable((Player) null); // Paper
return (ItemStack) this.getItems().get(slot);
return this.getItems().get(slot);
}

View file

@ -14,6 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
BlockState iblockdata = this.level.getBlockState(blockposition);
- FluidState fluid = this.level.getFluidState(blockposition);
+ FluidState fluid = iblockdata.getFluidState(); // Paper
Optional<Float> optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid);
if (optional.isPresent()) {
if (!this.level.isInWorldBounds(blockposition)) {
break;

View file

@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
this.tellNeutralMobsThatIDied();
}
// SPIGOT-5478 must be called manually now
@ -16,4 +16,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event
// we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
if (!event.getKeepInventory()) {
// Paper start - replace logic
this.getInventory().clearContent();

View file

@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition());
+ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper
+ if (iblockdata == null) { return false; } // Paper
return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED);
- BlockState blockState = world.getBlockState(globalPos.pos());
+ BlockState blockState = world.getTypeIfLoaded(globalPos.pos()); // Paper
+ if (blockState == null) { return false; } // Paper
return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
}
}