9
0
mirror of https://github.com/SparklyPower/SparklyPaper.git synced 2025-12-22 16:39:33 +00:00

Readd patches from Airplane

This commit is contained in:
MrPowerGamerBR
2021-03-22 07:42:13 -03:00
parent 5b179340f6
commit 0ee0d8a3c5
19 changed files with 1632 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 23 Jan 2021 16:42:24 -0600
Subject: [PATCH] Remove streams
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java
index 72f1031e95b375823790f8cac4c102ba1205c9e8..e4821c1a7ceac582b019102230dbe5221add9050 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorBetterJob.java
@@ -3,6 +3,7 @@ package net.minecraft.world.entity.ai.behavior;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.GlobalPos;
import net.minecraft.server.level.WorldServer;
+import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.entity.ai.village.poi.VillagePlaceType;
@@ -21,11 +22,31 @@ public class BehaviorBetterJob extends Behavior<EntityVillager> {
protected void a(WorldServer worldserver, EntityVillager entityvillager, long i) {
GlobalPos globalpos = (GlobalPos) entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE).get();
+ // Airplane start - remove stream
+ /*
worldserver.y().c(globalpos.getBlockPosition()).ifPresent((villageplacetype) -> {
BehaviorUtil.a(entityvillager, (entityvillager1) -> {
return this.a(globalpos, villageplacetype, entityvillager1);
}).reduce(entityvillager, BehaviorBetterJob::a);
});
+ */
+ java.util.Optional<VillagePlaceType> optVillagePlaceType = worldserver.y().c(globalpos.getBlockPosition());
+ if (optVillagePlaceType.isPresent()) {
+ VillagePlaceType villageplacetype = optVillagePlaceType.get();
+ java.util.Optional<java.util.List<EntityLiving>> optList = entityvillager.getBehaviorController().getMemory(MemoryModuleType.MOBS);
+ if (optList.isPresent()) {
+ EntityVillager previous = entityvillager;
+ for (EntityLiving entityliving : optList.get()) {
+ if (entityliving instanceof EntityVillager && entityliving != entityvillager && entityliving.isAlive()) {
+ EntityVillager entityvillager1 = (EntityVillager) entityliving;
+ if (this.a(globalpos, villageplacetype, entityvillager1)) {
+ previous = a(previous, entityvillager1);
+ }
+ }
+ }
+ }
+ }
+ // Airplane end
}
private static EntityVillager a(EntityVillager entityvillager, EntityVillager entityvillager1) {

View File

@@ -0,0 +1,214 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 18:43:02 -0500
Subject: [PATCH] Strip raytracing for EntityLiving#hasLineOfSight
The IBlockAccess#rayTrace method is very wasteful in both allocations,
and in logic. While EntityLiving#hasLineOfSight provides static
parameters for collisions with blocks and fluids, the method still does
a lot of dynamic checks for both of these, which result in extra work.
As well, since the fluid collision option is set to NONE, the entire
fluid collision system is completely unneeded, yet used anyways.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java
index cc566784c7dd21cc2c44e0f351347f657e57ddcf..e9e7fcf2b63febe2a7d055826fabb86bc13a5cf3 100644
--- a/src/main/java/net/minecraft/util/MathHelper.java
+++ b/src/main/java/net/minecraft/util/MathHelper.java
@@ -240,6 +240,7 @@ public class MathHelper {
return f - (float) d(f);
}
+ public static double getDecimals(double num) { return h(num); } // Airplane
public static double h(double d0) {
return d0 - (double) d(d0);
}
@@ -418,6 +419,7 @@ public class MathHelper {
return f1 + f * (f2 - f1);
}
+ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // Airplane - OBFHELPER
public static double d(double d0, double d1, double d2) {
return d1 + d0 * (d2 - d1);
}
@@ -434,6 +436,7 @@ public class MathHelper {
return d0 * d0 * d0 * (d0 * (d0 * 6.0D - 15.0D) + 10.0D);
}
+ public static int sign(double num) { return k(num); } // Airplane - OBFHELPER
public static int k(double d0) {
return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1);
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
index 561905be42428855a07a2e63aca80d5dd63b22bf..d991e3be65dc94597bd56ad9e034972e0e99a840 100644
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
@@ -111,6 +111,7 @@ import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.MovingObjectPosition;
import net.minecraft.world.phys.MovingObjectPositionEntity;
import net.minecraft.world.phys.Vec3D;
+import net.minecraft.world.phys.shapes.VoxelShapeCollision;
import net.minecraft.world.scores.ScoreboardTeam;
import org.apache.logging.log4j.Logger;
@@ -3101,7 +3102,7 @@ public abstract class EntityLiving extends Entity {
Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ());
Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ());
- return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS;
+ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS; // Airplane - use direct method
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java
index e612e1d30f76e217b1aa23488ab025adce048f57..c9198d242b9053fad6fa5b53c1894679002d50a7 100644
--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java
+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java
@@ -14,9 +14,11 @@ import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.MovingObjectPosition;
import net.minecraft.world.phys.MovingObjectPositionBlock;
import net.minecraft.world.phys.Vec3D;
import net.minecraft.world.phys.shapes.VoxelShape;
+import net.minecraft.world.phys.shapes.VoxelShapeCollision;
public interface IBlockAccess {
@@ -56,6 +58,15 @@ public interface IBlockAccess {
return BlockPosition.a(axisalignedbb).map(this::getType);
}
+ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect
+ default MovingObjectPosition.EnumMovingObjectType rayTraceBlockDirect(Vec3D vec3d, Vec3D vec3d1, BlockPosition blockposition, IBlockData iblockdata, VoxelShapeCollision voxelshapecoll) {
+ VoxelShape voxelshape = RayTrace.BlockCollisionOption.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll);
+ MovingObjectPositionBlock movingobjectpositionblock = this.rayTrace(vec3d, vec3d1, blockposition, voxelshape, iblockdata);
+
+ return movingobjectpositionblock == null ? null : movingobjectpositionblock.getType();
+ }
+ // Airplane end
+
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) {
// Paper start - Prevent raytrace from loading chunks
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index c8a5d4972431ce9615312280f36181a2b9645df7..bbc842a173b12a96b1b63af347d2196ac1cb5f73 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -69,6 +69,8 @@ import net.minecraft.world.level.saveddata.maps.WorldMap;
import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.WorldDataMutable;
import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.MovingObjectPosition;
+import net.minecraft.world.phys.Vec3D;
import net.minecraft.world.phys.shapes.OperatorBoolean;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.shapes.VoxelShapeCollision;
@@ -378,6 +380,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return null;
}
+ // Airplane start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace)
+ public MovingObjectPosition.EnumMovingObjectType rayTraceDirect(Vec3D vec3d, Vec3D vec3d1, VoxelShapeCollision voxelshapecoll) {
+ // most of this code comes from IBlockAccess#a(RayTrace, BiFunction, Function), but removes the needless functions
+ if (vec3d.equals(vec3d1)) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+
+ double endX = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.x, vec3d.x);
+ double endY = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.y, vec3d.y);
+ double endZ = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.z, vec3d.z);
+
+ double startX = MathHelper.linearInterpolation(-1.0E-7D, vec3d.x, vec3d1.x);
+ double startY = MathHelper.linearInterpolation(-1.0E-7D, vec3d.y, vec3d1.y);
+ double startZ = MathHelper.linearInterpolation(-1.0E-7D, vec3d.z, vec3d1.z);
+
+ int currentX = MathHelper.floor(startX);
+ int currentY = MathHelper.floor(startY);
+ int currentZ = MathHelper.floor(startZ);
+
+ BlockPosition.MutableBlockPosition currentBlock = new BlockPosition.MutableBlockPosition(currentX, currentY, currentZ);
+
+ Chunk chunk = this.getChunkIfLoaded(currentBlock);
+ if (chunk == null) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+
+ MovingObjectPosition.EnumMovingObjectType initialCheck = this.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getType(currentBlock), voxelshapecoll);
+
+ if (initialCheck != null) {
+ return initialCheck;
+ }
+
+ double diffX = endX - startX;
+ double diffY = endY - startY;
+ double diffZ = endZ - startZ;
+
+ int xDirection = MathHelper.sign(diffX);
+ int yDirection = MathHelper.sign(diffY);
+ int zDirection = MathHelper.sign(diffZ);
+
+ double normalizedX = xDirection == 0 ? Double.MAX_VALUE : (double) xDirection / diffX;
+ double normalizedY = yDirection == 0 ? Double.MAX_VALUE : (double) yDirection / diffY;
+ double normalizedZ = zDirection == 0 ? Double.MAX_VALUE : (double) zDirection / diffZ;
+
+ double normalizedXDirection = normalizedX * (xDirection > 0 ? 1.0D - MathHelper.getDecimals(startX) : MathHelper.getDecimals(startX));
+ double normalizedYDirection = normalizedY * (yDirection > 0 ? 1.0D - MathHelper.getDecimals(startY) : MathHelper.getDecimals(startY));
+ double normalizedZDirection = normalizedZ * (zDirection > 0 ? 1.0D - MathHelper.getDecimals(startZ) : MathHelper.getDecimals(startZ));
+
+ MovingObjectPosition.EnumMovingObjectType result;
+
+ do {
+ if (normalizedXDirection > 1.0D && normalizedYDirection > 1.0D && normalizedZDirection > 1.0D) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+
+ if (normalizedXDirection < normalizedYDirection) {
+ if (normalizedXDirection < normalizedZDirection) {
+ currentX += xDirection;
+ normalizedXDirection += normalizedX;
+ } else {
+ currentZ += zDirection;
+ normalizedZDirection += normalizedZ;
+ }
+ } else if (normalizedYDirection < normalizedZDirection) {
+ currentY += yDirection;
+ normalizedYDirection += normalizedY;
+ } else {
+ currentZ += zDirection;
+ normalizedZDirection += normalizedZ;
+ }
+
+ currentBlock.setValues(currentX, currentY, currentZ);
+ if (chunk.getPos().x != currentBlock.getX() >> 4 || chunk.getPos().z != currentBlock.getZ() >> 4) {
+ chunk = this.getChunkIfLoaded(currentBlock);
+ if (chunk == null) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+ }
+ result = this.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getType(currentBlock), voxelshapecoll);
+ } while (result == null);
+
+ return result;
+ }
+ // Airplane end
+
public static boolean isValidLocation(BlockPosition blockposition) {
return blockposition.isValidLocation(); // Paper - use better/optimized check
}

View File

@@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 18:51:38 -0500
Subject: [PATCH] Simpler ShapelessRecipes comparison for Vanilla
Paper added a fancy sorting comparison due to Bukkit recipes breaking
the vanilla one, however this is far more advanced than what you need
for all the vanilla recipes.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java
index e112d149fc3a7af7f0c9a5280c94c9b03b2aba2d..d2afc367fb393c6206f9cd599d4603294d457608 100644
--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java
@@ -26,8 +26,16 @@ public class ShapelessRecipes implements RecipeCrafting {
private final String group;
private final ItemStack result;
private final NonNullList<RecipeItemStack> ingredients;
+ private final boolean isBukkit; // Airplane
+ // Airplane start - add isBukkit constructor param
public ShapelessRecipes(MinecraftKey minecraftkey, String s, ItemStack itemstack, NonNullList<RecipeItemStack> nonnulllist) {
+ this(minecraftkey, s, itemstack, nonnulllist, false);
+ }
+
+ public ShapelessRecipes(MinecraftKey minecraftkey, String s, ItemStack itemstack, NonNullList<RecipeItemStack> nonnulllist, boolean isBukkit) {
+ this.isBukkit = isBukkit;
+ // Airplane end
this.key = minecraftkey;
this.group = s;
this.result = itemstack;
@@ -69,6 +77,28 @@ public class ShapelessRecipes implements RecipeCrafting {
}
public boolean a(InventoryCrafting inventorycrafting, World world) {
+ // Airplane start
+ if (!this.isBukkit) {
+ java.util.List<RecipeItemStack> ingredients = com.google.common.collect.Lists.newArrayList(this.ingredients.toArray(new RecipeItemStack[0]));
+
+ inventory: for (int index = 0; index < inventorycrafting.getSize(); index++) {
+ ItemStack itemStack = inventorycrafting.getItem(index);
+
+ if (!itemStack.isEmpty()) {
+ for (int i = 0; i < ingredients.size(); i++) {
+ if (ingredients.get(i).test(itemStack)) {
+ ingredients.remove(i);
+ continue inventory;
+ }
+ }
+ return false;
+ }
+ }
+
+ return ingredients.isEmpty();
+ }
+ // Airplane end
+
AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager();
int i = 0;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
index de9c5ed6b03a290fe77eec719f0079fd7bd9b7f5..8c02f6fdffb59153712a3be778f9c454fd87b73b 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
@@ -44,6 +44,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe
data.set(i, toNMS(ingred.get(i), true));
}
- MinecraftServer.getServer().getCraftingManager().addRecipe(new ShapelessRecipes(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data));
+ MinecraftServer.getServer().getCraftingManager().addRecipe(new ShapelessRecipes(CraftNamespacedKey.toMinecraft(this.getKey()), this.getGroup(), CraftItemStack.asNMSCopy(this.getResult()), data, true)); // Airplane
}
}

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sun, 1 Nov 2020 16:59:08 -0600
Subject: [PATCH] Swap priority of checks in chunk ticking
World.V showed up a lot in lag spikes for some reason, although I wonder
if it's just Spark getting JVM safe points.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index 46f960b9276dced41deb8f741454b6cce5a81529..277132da0b3672a9097b16f3b8534975dc795e3e 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -1210,7 +1210,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("thunder");
final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
- if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder
+ if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // Airplane - check this.W last
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);

View File

@@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sun, 13 Dec 2020 17:52:35 -0600
Subject: [PATCH] Reduce projectile chunk loading
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java
index e55061b6c04b4bde92404a6ef58ba9a52cd99c1d..24d205dd1f31ece82d5cf516b8642eb0172e1a97 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java
@@ -4,6 +4,8 @@ import net.minecraft.core.BlockPosition;
import net.minecraft.core.particles.Particles;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.util.MathHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.EntityTypes;
@@ -102,6 +104,37 @@ public abstract class EntityProjectile extends IProjectile {
this.setPosition(d0, d1, d2);
}
+ private static int loadedThisTick = 0;
+ private static int loadedTick;
+
+ private int buffered = 0;
+
+ // Airplane start
+ @Override
+ public void setPosition(double d0, double d1, double d2) {
+ if (loadedTick != MinecraftServer.currentTick) {
+ loadedTick = MinecraftServer.currentTick;
+ loadedThisTick = 0;
+ }
+ int previousX = MathHelper.floor(this.locX()) >> 4, previousZ = MathHelper.floor(this.locZ()) >> 4;
+ int newX = MathHelper.floor(d0) >> 4, newZ = MathHelper.floor(d2) >> 4;
+ if (previousX != newX || previousZ != newZ) {
+ boolean isLoaded = this.world.isChunkLoaded(newX, newZ);
+ if (!isLoaded) {
+ if (loadedThisTick > 10) { // Airplane 10 = max chunks to load from projectiles in a tick todo config
+ if (++buffered > 20) { // Airplane 20 = max chunks a single projectile loads overall todo config
+ this.die();
+ }
+ return;
+ }
+ loadedThisTick++;
+ }
+ buffered = 0;
+ }
+ super.setPosition(d0, d1, d2);
+ }
+ // Airplane end
+
protected float k() {
return 0.03F;
}

View File

@@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sun, 13 Dec 2020 17:53:08 -0600
Subject: [PATCH] Only check for spooky season once an hour
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
index 61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2..341b95f73a839a548b202e7bf97fd18760c71fd8 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -247,13 +248,22 @@ public class EntityBat extends EntityAmbient {
}
}
+ // Airplane start - only check for spooky season once an hour
+ private static boolean isSpookySeason = false;
+ private static final int ONE_HOUR = 20 * 60 * 60;
+ private static int lastSpookyCheck = -ONE_HOUR;
private static boolean eJ() {
+ if (MinecraftServer.currentTick - lastSpookyCheck > ONE_HOUR) {
LocalDate localdate = LocalDate.now();
int i = localdate.get(ChronoField.DAY_OF_MONTH);
int j = localdate.get(ChronoField.MONTH_OF_YEAR);
+ isSpookySeason = j == 10 && i >= 20 || j == 11 && i <= 3;
+ lastSpookyCheck = MinecraftServer.currentTick;
+ }
- return j == 10 && i >= 20 || j == 11 && i <= 3;
+ return isSpookySeason;
}
+ // Airplane end
@Override
protected float b(EntityPose entitypose, EntitySize entitysize) {

View File

@@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 7 Jan 2021 11:49:36 -0600
Subject: [PATCH] Optimize random calls in chunk ticking
Especially at over 30,000 chunks these random calls are fairly heavy. We
use a different method here for checking lightning, and for checking
ice.
Lighting: Each chunk now keeps an int of how many ticks until the
lightning should strike. This int is a random number from 0 to 100000 * 2,
the multiplication is required to keep the probability the same.
Ice and snow: We just generate a single random number 0-16 and increment
it, while checking if it's 0 for the current chunk.
Depending on configuration for things that tick in a chunk, this is a
5-10% improvement.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
index cb83f1152c52a99d25e4e80cc8bf18c6793e8b50..87c87b9767003652814c3726eece64470dbb69a8 100644
--- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java
@@ -1000,6 +1000,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
// Paper end - optimize isOutisdeRange
this.world.getMethodProfiler().enter("pollingChunks");
+ this.world.resetIceAndSnowTick(); // Airplane - reset ice & snow tick random
int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED);
boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index 277132da0b3672a9097b16f3b8534975dc795e3e..b33f37309d4dd22c033ad84effa4ff9d6e20a790 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -1200,6 +1200,8 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final BiomeBase[] biomeBaseCache = new BiomeBase[1];
// Tuinity end - optimise chunk ice snow ticking
+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane
+
public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
@@ -1210,7 +1212,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("thunder");
final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
- if (!this.paperConfig.disableThunder && flag && this.random.nextInt(100000) == 0 && this.W()) { // Paper - Disable thunder // Airplane - check this.W last
+ if (!this.paperConfig.disableThunder && flag && chunk.shouldDoLightning(this.random) && this.W()) { // Paper - Disable thunder // Airplane - check this.W last // Airplane - replace random with shouldDoLighting
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);
@@ -1234,7 +1236,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
gameprofilerfiller.exitEnter("iceandsnow");
- if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
+ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - optimize further random ticking
// Paper start - optimise chunk ticking
// Tuinity start - optimise chunk ice snow ticking
BiomeBase[] biomeCache = this.biomeBaseCache;
diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java
index 259d4ac89e84fd334ff65ea8a606e1fc50cc882b..226f9e5a3d867b5365f3ea44c1459ed7265c1b41 100644
--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java
@@ -99,6 +99,18 @@ public class Chunk implements IChunkAccess {
private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key
private volatile boolean x;
+ // Airplane start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
+ private int lightningTick;
+ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline
+ public final boolean shouldDoLightning(java.util.Random random) {
+ if (this.lightningTick-- <= 0) {
+ this.lightningTick = random.nextInt(100000) << 1;
+ return true;
+ }
+ return false;
+ }
+ // Airplane end
+
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) {
this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null);
}
@@ -333,6 +345,7 @@ public class Chunk implements IChunkAccess {
// CraftBukkit start
this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
this.entitySlicesManager = new com.tuinity.tuinity.world.ChunkEntitySlices(this.world, this.loc.x, this.loc.z, 0, 15); // TODO update for 1.17 // Tuinity
+ this.lightningTick = this.world.random.nextInt(100000) << 1; // Airplane - initialize lightning tick
}
public org.bukkit.Chunk bukkitChunk;

View File

@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Fri, 15 Jan 2021 20:08:54 -0600
Subject: [PATCH] Don't get entity equipment if not needed
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
index d991e3be65dc94597bd56ad9e034972e0e99a840..1a7866bed9cb7f0431454d3af4733de05c0cba78 100644
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
@@ -910,11 +910,13 @@ public abstract class EntityLiving extends Entity {
}
if (entity != null) {
- ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD);
- Item item = itemstack.getItem();
+ // Airplane start - don't get equipment if not needed
+ //ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD);
+ //Item item = itemstack.getItem();
EntityTypes<?> entitytypes = entity.getEntityType();
- if (entitytypes == EntityTypes.SKELETON && item == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && item == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && item == Items.CREEPER_HEAD) {
+ if (entitytypes == EntityTypes.SKELETON && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && this.getEquipment(EnumItemSlot.HEAD).getItem() == Items.CREEPER_HEAD) {
+ // Airplane end
d0 *= 0.5D;
}
}

View File

@@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 4 Feb 2021 23:24:20 -0600
Subject: [PATCH] Reduce allocs & improve perf of StructureManager
Focuses on two methods, getStructureStarts & getFeatureStarts. For
getStructureStarts, it inlines getFeatureStarts so it doesn't have to
calculate an entire list when it returns early. As well, it uses a
LongIterator in order to not allocate longs for each position.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java
index acacbf9617f99b97fc7fd2ba718775e1b3e429e9..967ae0212028d57d366497f7f25c61776c1ac3f2 100644
--- a/src/main/java/net/minecraft/world/level/StructureManager.java
+++ b/src/main/java/net/minecraft/world/level/StructureManager.java
@@ -15,6 +15,11 @@ import net.minecraft.world.level.levelgen.feature.StructureGenerator;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.StructureStart;
+// Airplane start
+import it.unimi.dsi.fastutil.longs.LongIterator;
+import it.unimi.dsi.fastutil.longs.LongSet;
+// Airplane end
+
public class StructureManager {
private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER
@@ -51,13 +56,15 @@ public class StructureManager {
public java.util.List<StructureStart<?>> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator<?> structureGenerator, IWorldReader world) {
// Tuinity end - add world parameter
java.util.List<StructureStart<?>> list = new ObjectArrayList<>();
- for (Long curLong: (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { // Tuinity - fix deadlock on world gen - chunk can be unloaded while generating, so we should be using the generator's regionlimitedaccess so we always get the chunk
- SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0);
+ // Airplane start - skip allocating Longs
+ (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator).forEach((java.util.function.LongConsumer) curLong -> {
+ SectionPosition sectionPosition1 = SectionPosition.a(ChunkCoordIntPair.getX(curLong), 0, ChunkCoordIntPair.getZ(curLong)); // don't allocate ChunkCoordIntPair
StructureStart<?> structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS));
if (structurestart != null && structurestart.e()) {
list.add(structurestart);
}
- }
+ });
+ // Airplane end
return list;
}
// Paper end
@@ -85,7 +92,18 @@ public class StructureManager {
}
public StructureStart<?> getStructureStarts(BlockPosition blockposition, boolean flag, StructureGenerator<?> structuregenerator, IWorldReader world) {
// Paper start - remove structure streams
- for (StructureStart<?> structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator, world)) { // Tuinity end - add world parameter
+ // Airplane start - inline getFeatureStarts to skip creating the list
+ SectionPosition sectionPosition = SectionPosition.a(blockposition);
+
+ // use iterator here instead of forEach like in getFeatureStarts so we can return early
+ LongSet longSet = (world == null ? getLevel() : world).getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structuregenerator);
+ LongIterator iterator = longSet.iterator();
+ while (iterator.hasNext()) {
+ long curLong = iterator.nextLong();
+ SectionPosition sectionPosition1 = SectionPosition.a(ChunkCoordIntPair.getX(curLong), 0, ChunkCoordIntPair.getZ(curLong)); // don't allocate ChunkCoordIntPair
+ StructureStart<?> structurestart = a(sectionPosition1, structuregenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS));
+ if (structurestart != null && structurestart.e()) {
+
if (structurestart.c().b(blockposition)) {
if (!flag) {
return structurestart;
@@ -96,7 +114,10 @@ public class StructureManager {
}
}
}
+
+ }
}
+ // Airplane end
return StructureStart.a;
// Paper end
}

View File

@@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 4 Feb 2021 23:28:46 -0600
Subject: [PATCH] Cache palette array
The reasoning for reusing it in ChunkRegionLoader is because ThreadLocal
lookups are fairly expensive, and if we put it in DataPaletteBlock the
ThreadLocal lookup would happen 18 times.
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java
index a6937366cd9c9d708edb5cd1ab3ac096e7b2032e..a579c5bf9e20c74aa3bf8ef6bc00576409805ca6 100644
--- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java
+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java
@@ -235,12 +235,16 @@ public class DataPaletteBlock<T> implements DataPaletteExpandable<T> {
this.b();
}
+ // Airplane start - add parameter for reusing aint
public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize
+ a(nbttagcompound, s, s1, new int[4096]);
+ }
+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1, int[] aint) { // Paper - synchronize // Airplane end
this.a();
DataPaletteHash<T> datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f);
T t0 = this.g;
int i = datapalettehash.a(this.g);
- int[] aint = new int[4096];
+ //int[] aint = new int[4096]; // Airplane - use parameter
for (int j = 0; j < 4096; ++j) {
T t1 = this.a(j);
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java
index ec2b238480413ba9c123d9ddeaa787d9520e1b74..bf96f9e538fc29ca914536e8a7ce727ebe43a8b2 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java
@@ -468,6 +468,7 @@ public class ChunkRegionLoader {
public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) {
return saveChunk(worldserver, ichunkaccess, null);
}
+ private static final ThreadLocal<int[]> paletteArray = ThreadLocal.withInitial(() -> new int[4096]); // Airplane
public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) {
// Paper end
// Tuinity start - rewrite light impl
@@ -498,6 +499,7 @@ public class ChunkRegionLoader {
NBTTagCompound nbttagcompound2;
+ int[] aint = paletteArray.get(); // Airplane - use cached
for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change
int finalI = i; // CraftBukkit - decompile errors
ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> {
@@ -518,7 +520,7 @@ public class ChunkRegionLoader {
nbttagcompound2 = new NBTTagCompound();
nbttagcompound2.setByte("Y", (byte) (i & 255));
if (chunksection != Chunk.a) {
- chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates");
+ chunksection.getBlocks().a(nbttagcompound2, "Palette", "BlockStates", aint); // Airplane
}
if (nibblearray != null && !nibblearray.c()) {

View File

@@ -0,0 +1,224 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Tue, 9 Feb 2021 19:05:58 -0600
Subject: [PATCH] Reduce memory allocations
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java
index 8edc279e7a3fdfb7e10718f1deee34b7e3fb2f28..73ec17dea5d5668e49c9a6ad679bd3a362960c72 100644
--- a/src/main/java/net/minecraft/core/BlockPosition.java
+++ b/src/main/java/net/minecraft/core/BlockPosition.java
@@ -438,6 +438,14 @@ public class BlockPosition extends BaseBlockPosition {
public BlockPosition b(int i, int j, int k) {
return super.b(i, j, k).immutableCopy();
}
+ // Airplane start - version of b that doesn't copy
+ public BlockPosition addValues(int x, int y, int z) {
+ ((BaseBlockPosition)this).a += x;
+ ((BaseBlockPosition)this).b += y;
+ ((BaseBlockPosition)this).e += z;
+ return this;
+ }
+ // Airplane end
@Override
public BlockPosition shift(EnumDirection enumdirection, int i) {
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
index d7eede51f1c4ebbe8e00b16efd6331c87db53bb4..bc18b9c3aac4c5feeb1603554e0ac009af9b457e 100644
--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
@@ -705,7 +705,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return d2 * d2 + d3 * d3;
}
- private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) {
+ // Airplane start - create copy that accepts x/z instead of allocating pair
+ private static int b(ChunkCoordIntPair chunkcoordintpair, EntityPlayer entityplayer, boolean flag) { return someDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, entityplayer, flag); }
+ private static int someDistanceCalculation(int x, int z, EntityPlayer entityplayer, boolean flag) {
int i;
int j;
@@ -719,12 +721,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
j = MathHelper.floor(entityplayer.locZ() / 16.0D);
}
- return a(chunkcoordintpair, i, j);
+ return someOtherDistanceCalculation(x, z, i, j);
+ // Airplane end
}
- private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) {
- int k = chunkcoordintpair.x - i;
- int l = chunkcoordintpair.z - j;
+ // Airplane start - create copy that accepts x/z instead of allocating pair
+ private static int a(ChunkCoordIntPair chunkcoordintpair, int i, int j) { return someOtherDistanceCalculation(chunkcoordintpair.x, chunkcoordintpair.z, i, j); }
+ private static int someOtherDistanceCalculation(int x, int z, int i, int j) {
+ int k = x - i;
+ int l = z - j;
+ // Airplane end
return Math.max(Math.abs(k), Math.abs(l));
}
@@ -2571,11 +2577,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
boolean flag1 = this.tracker.attachedToPlayer;
if (!flag1) {
+ // Airplane start - use int/longs instead of ChunkCoordIntPair
+ /*
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ);
- PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair());
+ */
+ int x = this.tracker.chunkX, z = this.tracker.chunkZ;
+ long chunkcoordintpair = ChunkCoordIntPair.pair(x, z);
+ PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair);
if (playerchunk != null && playerchunk.getSendingChunk() != null && PlayerChunkMap.this.playerChunkManager.isChunkSent(entityplayer, MathHelper.floor(this.tracker.locX()) >> 4, MathHelper.floor(this.tracker.locZ()) >> 4)) { // Paper - no-tick view distance // Tuinity - don't broadcast in chunks the player hasn't received
- flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance;
+ flag1 = PlayerChunkMap.someDistanceCalculation(x, z, entityplayer, false) <= PlayerChunkMap.this.viewDistance;
+ // Airplane end
}
}
@@ -2605,8 +2617,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
}
private int b() {
+ // Airplane start
+ int i = this.trackingDistance; // move out of if statement
+ if (!this.tracker.passengers.isEmpty()) {
Collection<Entity> collection = this.tracker.getAllPassengers();
- int i = this.trackingDistance;
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
@@ -2618,6 +2632,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
i = j;
}
}
+ }
+ // Airplane end
return this.a(i);
}
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index b33f37309d4dd22c033ad84effa4ff9d6e20a790..6d3bef91b13701834d3cd87e44500f79c33d9bcb 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -1105,7 +1105,28 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("tick");
if (!entity.dead && !(entity instanceof EntityComplexPart)) {
+ // Airplane start - inline this.a to prevent creation of lambda
+ /*
this.a(this::entityJoinedWorld, entity);
+ */
+ boolean doMidTick = false; // usually there's a returns in the catch, so treat it like that
+ try {
+ this.entityJoinedWorld(entity);
+ doMidTick = true;
+ } catch (Throwable throwable) {
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper
+ // Paper start - Prevent tile entity and entity crashes
+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ();
+ System.err.println(msg);
+ throwable.printStackTrace();
+ getServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable)));
+ entity.dead = true;
+ // Paper end
+ }
+ if (doMidTick) {
+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
+ }
+ // Airplane end
}
gameprofilerfiller.exit();
@@ -1450,9 +1471,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
++entity.ticksLived;
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
+ // Airplane start - create debug lambda once, todo do we even WANT the method profiler?
+ /*
gameprofilerfiller.a(() -> {
return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString();
});
+ */
+ gameprofilerfiller.a(entity.getEntityType().getEntityName);
+ // Airplane end
gameprofilerfiller.c("tickNonPassenger");
if (isActive) { // Paper - EAR 2
TimingHistory.activatedEntityTicks++; // Paper
diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java
index f2cf33d42839710a3bbdf0c8ea0be28af6fcb19d..983a35589c4328238be97166f66f0c6aaa146df9 100644
--- a/src/main/java/net/minecraft/world/entity/EntityTypes.java
+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java
@@ -270,6 +270,8 @@ public class EntityTypes<T extends Entity> {
private MinecraftKey bq;
private final EntitySize br;
+ public java.util.function.Supplier<String> getEntityName = () -> IRegistry.ENTITY_TYPE.getKey(this).toString(); // Airplane - create lambda ones
+
private static <T extends Entity> EntityTypes<T> a(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error
return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s));
}
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index bbc842a173b12a96b1b63af347d2196ac1cb5f73..0ad326341bd187257376f643f1fad7fc3a72c417 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -1103,19 +1103,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public void a(Consumer<Entity> consumer, Entity entity) {
try {
- consumer.accept(entity);
+ consumer.accept(entity); // Airplane - error on change
} catch (Throwable throwable) {
if (throwable instanceof ThreadDeath) throw throwable; // Paper
// Paper start - Prevent tile entity and entity crashes
String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ();
System.err.println(msg);
throwable.printStackTrace();
- getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); // Airplane - error on change
entity.dead = true;
return;
// Paper end
}
- MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick // Airplane - error on change
}
// Paper start - Prevent armor stands from doing entity lookups
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java
index 712596420af83e6e1b9d147ae2fd8d8a1f36e1b9..9c29fa3efac7e16df81b8a44934e3286bb37f1f6 100644
--- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java
+++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java
@@ -54,8 +54,14 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow {
if (worldserver.getLightLevel(blockposition.up()) >= 9) {
IBlockData iblockdata1 = this.getBlockData();
+ // Airplane start - use mutable position
+ BlockPosition.MutableBlockPosition blockposition1 = new BlockPosition.MutableBlockPosition();
for (int i = 0; i < 4; ++i) {
+ blockposition1.setValues(blockposition).addValues(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
+ /*
BlockPosition blockposition1 = blockposition.b(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
+ */
+ // Airplane end
if (worldserver.getType(blockposition1).a(Blocks.DIRT) && c(iblockdata1, (IWorldReader) worldserver, blockposition1)) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, (IBlockData) iblockdata1.set(BlockDirtSnowSpreadable.a, worldserver.getType(blockposition1.up()).a(Blocks.SNOW))); // CraftBukkit

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 18 Feb 2021 13:13:27 -0600
Subject: [PATCH] Skip POI finding if stuck in vehicle
Airplane
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java
index bc8786e2aaeab4dbae4e9c7666ad816bc5bfac3f..09133c5822bc1386bc3d8a5f3c94196420bbfaea 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java
@@ -67,6 +67,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) {
this.f = i + 20L + (long) worldserver.getRandom().nextInt(20);
+ if (entitycreature.getNavigation().isStuck()) this.f += 200L; // Airplane - wait an additional 10s to check again if they're stuck
VillagePlace villageplace = worldserver.y();
this.g.long2ObjectEntrySet().removeIf((entry) -> {
diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java
index 148bdbc2cffb002d8b6dd05e70854ab503804949..48e6a4c588ef39a4bde067d79b96a656c68750ce 100644
--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java
@@ -433,6 +433,7 @@ public abstract class NavigationAbstract {
}
}
+ public boolean isStuck() { return this.t(); } // Airplane - OBFHELPER
public boolean t() {
return this.t;
}

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 10:19:15 -0600
Subject: [PATCH] Skip copying unloading tile entities
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index 0ad326341bd187257376f643f1fad7fc3a72c417..e3f1f20608cab7067674b2cdd2759a34902b6626 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -106,7 +106,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
//public final List<TileEntity> tileEntityList = Lists.newArrayList(); // Paper - remove unused list
public final List<TileEntity> tileEntityListTick = Lists.newArrayList();
protected final List<TileEntity> tileEntityListPending = Lists.newArrayList();
- protected final java.util.Set<TileEntity> tileEntityListUnload = com.google.common.collect.Sets.newHashSet();
+ protected final java.util.Set<TileEntity> tileEntityListUnload = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); // Airplane - use set with faster contains
public final Thread serverThread;
private final boolean debugWorld;
private int d;
@@ -986,12 +986,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
gameprofilerfiller.enter("blockEntities");
timings.tileEntityTick.startTiming(); // Spigot
if (!this.tileEntityListUnload.isEmpty()) {
+ // Airplane start - we just use the identitymap as the basis for the unload set now instead of copying
+ /*
// Paper start - Use alternate implementation with faster contains
java.util.Set<TileEntity> toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
toRemove.addAll(tileEntityListUnload);
this.tileEntityListTick.removeAll(toRemove);
// Paper end
//this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list
+ */
+ this.tileEntityListTick.removeAll(this.tileEntityListUnload);
+ // Airplane end
this.tileEntityListUnload.clear();
}

View File

@@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 10:40:22 -0600
Subject: [PATCH] Reduce entity chunk ticking checks from 3 to 1
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index 6d3bef91b13701834d3cd87e44500f79c33d9bcb..9d97e2ea5c207c42f1cc9aa14bc87dc8e0a1bb1e 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -1081,11 +1081,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end */
gameprofilerfiller.enter("checkDespawn");
+ boolean entityTickingChunk = false; if (!entity.dead) entityTickingChunk = this.getChunkProvider().isInEntityTickingChunk(entity); // Airplane - check once, chunks won't unload ticking entities
if (!entity.dead) {
entity.checkDespawn();
// Tuinity start - optimise notify()
if (entity.inChunk && entity.valid) {
- if (this.getChunkProvider().isInEntityTickingChunk(entity)) {
+ if (entityTickingChunk) { // Airplane - reuse
this.updateNavigatorsInRegion(entity);
}
} else {
@@ -1111,7 +1112,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
*/
boolean doMidTick = false; // usually there's a returns in the catch, so treat it like that
try {
- this.entityJoinedWorld(entity);
+ this.entityJoinedWorld(entity, entityTickingChunk); // Airplane - reuse
doMidTick = true;
} catch (Throwable throwable) {
if (throwable instanceof ThreadDeath) throw throwable; // Paper
@@ -1136,7 +1137,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.entitiesById.remove(entity.getId()); // Tuinity
this.unregisterEntity(entity);
} else if (entity.inChunk && entity.valid) { // Tuinity start - optimise notify()
- if (this.getChunkProvider().isInEntityTickingChunk(entity)) {
+ if (entityTickingChunk) { // Airplane - reuse
this.updateNavigatorsInRegion(entity);
}
} else {
@@ -1437,7 +1438,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Tuinity end - log detailed entity tick information
- public void entityJoinedWorld(Entity entity) {
+ // Airplane start - reuse check for in entity ticking chunk
+ public void entityJoinedWorld(Entity entity) { entityJoinedWorld(entity, this.getChunkProvider().isInEntityTickingChunk(entity)); }
+ public void entityJoinedWorld(Entity entity, boolean entityTickingChunk) { // Airplane end
// Tuinity start - log detailed entity tick information
com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
try {
@@ -1445,7 +1448,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
currentlyTickingEntity.lazySet(entity);
}
// Tuinity end - log detailed entity tick information
- if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) {
+ if (!(entity instanceof EntityHuman) && !entityTickingChunk) { // Airplane - reuse
this.chunkCheck(entity);
} else {
++TimingHistory.entityTicks; // Paper - timings

View File

@@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 12:24:41 -0600
Subject: [PATCH] Remove iterators from inventory contains
diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java
index 2df3ae0b72ccb5f816d55fed15396ba5a1affb7f..754a3ea18905b79ae5ae4fc2442c94f0611b6d0e 100644
--- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java
+++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java
@@ -630,6 +630,8 @@ public class PlayerInventory implements IInventory, INamableTileEntity {
}
public boolean h(ItemStack itemstack) {
+ // Airplane start - skip using abstract iterators and stuff, they're generic and slow and allocating them sucks
+ /*
Iterator iterator = this.f.iterator();
while (iterator.hasNext()) {
@@ -644,6 +646,20 @@ public class PlayerInventory implements IInventory, INamableTileEntity {
}
}
}
+ */
+ List<NonNullList<ItemStack>> components = this.getComponents();
+ for (int i = 0; i < components.size(); i++) {
+ List<ItemStack> list = components.get(i);
+
+ for (int j = 0; j < list.size(); j++) {
+ ItemStack itemstack1 = list.get(j);
+
+ if (!itemstack1.isEmpty() && itemstack1.doMaterialsMatch(itemstack)) {
+ return true;
+ }
+ }
+ }
+ // Airplane end
return false;
}

View File

@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 14:02:04 -0600
Subject: [PATCH] Cache entityhuman display name
diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
index 44038dd278b988508047023107683e5370af54ad..ad85dda5c50b797904824a08513fbcec042128ea 100644
--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
@@ -162,7 +162,8 @@ public abstract class EntityHuman extends EntityLiving {
protected int bG;
protected final float bH = 0.02F;
private int g;
- private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER
+ private IChatBaseComponent displayName; // Airplane - cache displayName
+ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; this.displayName = null; } // Paper - OBFHELPER // Airplane - use to reset displayName
private ItemStack bL;
private final ItemCooldown bM;
@Nullable
@@ -1828,7 +1829,12 @@ public abstract class EntityHuman extends EntityLiving {
@Override
public IChatBaseComponent getDisplayName() {
- return new ChatComponentText(this.bJ.getName());
+ // Airplane start - cache display name
+ if (this.displayName == null) {
+ this.displayName = new ChatComponentText(this.getProfile().getName());
+ }
+ return this.displayName;
+ // Airplane end
}
public InventoryEnderChest getEnderChest() {

View File

@@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 15:05:28 -0600
Subject: [PATCH] Early return optimization for target finding
diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java
index 88972dd8252bd2d2d8e384d616484ff682949fa8..5e8d3b84cbad299e09e8f25bfc712d11e1d1068e 100644
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java
@@ -84,9 +84,17 @@ public class PathfinderTargetCondition {
}
if (this.b > 0.0D) {
+ // Airplane start - try to return early
+ double range = (useFollowRange ? getFollowRange(entityliving) : this.b);
+ double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); // move up here to use early
+
+ if (d2 > range * range) { // if they're further than the absolute furthest allowed, they don't match
+ return false;
+ }
+
double d0 = this.g ? entityliving1.A(entityliving) : 1.0D;
- double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper
- double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ());
+ double d1 = Math.max(range * d0, 2.0D); // Paper // Airplane - reuse range calculated above
+ // Airplane end
if (d2 > d1 * d1) {
return false;

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Wed, 17 Mar 2021 13:00:57 -0500
Subject: [PATCH] More debug for plugins not shutting down tasks
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 79b684e3b1d572c3d294f92dffc2c64bb8ae4472..44842dd0809868238d0cc3a308a8d8348f804dcf 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -978,6 +978,11 @@ public final class CraftServer implements Server {
plugin.getDescription().getName(),
"This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies."
));
+ getLogger().log(Level.SEVERE, String.format("%s Stacktrace", worker.getThread().getName()));
+ StackTraceElement[] stackTrace = worker.getThread().getStackTrace();
+ for (StackTraceElement element : stackTrace) {
+ getLogger().log(Level.SEVERE, " " + element.toString());
+ }
}
}
// Paper end

View File

@@ -0,0 +1,287 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: froobynooby <froobynooby@froobworld.com>
Date: Sat, 20 Mar 2021 18:55:58 +0930
Subject: [PATCH] Skip unnecessary hopper pulls and pushes
This patch reduces unnecessary hopper pulls and pushes by skipping them if all of the following conditions are met:
1) The last attempted pull/push failed.
2) There are no items/inventory entities to be pulled/pushed from/to.
3) The state of the hopper has not changed since the last attempted pull/push.
4) The state of any inventory the hopper can pull/push from/to has not changed since the last attempted pull/push.
If all four of these conditions are met then any pull/push must fail and therefore can be skipped.
diff --git a/src/main/java/net/minecraft/world/level/block/BlockComposter.java b/src/main/java/net/minecraft/world/level/block/BlockComposter.java
index e4e519ba773388b8d26a8f794a6eff51e3d8f72e..288678a3a9aee8a2bd03195ec9311693290a1b62 100644
--- a/src/main/java/net/minecraft/world/level/block/BlockComposter.java
+++ b/src/main/java/net/minecraft/world/level/block/BlockComposter.java
@@ -7,6 +7,7 @@ import javax.annotation.Nullable;
import net.minecraft.SystemUtils;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.EnumDirection;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffects;
@@ -29,6 +30,7 @@ import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.block.state.properties.BlockProperties;
import net.minecraft.world.level.block.state.properties.BlockStateInteger;
import net.minecraft.world.level.block.state.properties.IBlockState;
+import net.minecraft.world.level.chunk.Chunk;
import net.minecraft.world.level.pathfinder.PathMode;
import net.minecraft.world.phys.MovingObjectPositionBlock;
import net.minecraft.world.phys.shapes.OperatorBoolean;
@@ -283,6 +285,14 @@ public class BlockComposter extends Block implements IInventoryHolder {
if ((Integer) iblockdata.get(BlockComposter.a) == 7) {
worldserver.setTypeAndData(blockposition, (IBlockData) iblockdata.a((IBlockState) BlockComposter.a), 3);
worldserver.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_COMPOSTER_READY, SoundCategory.BLOCKS, 1.0F, 1.0F);
+ // Paper start - keep track of inventory updates
+ Chunk chunk = worldserver.getChunkIfLoaded(blockposition);
+ if (chunk != null) {
+ chunk.inventoryUpdateMap.put(blockposition, MinecraftServer.currentTick);
+ } else {
+ Chunk.lastUnknownInventoryUpdate = MinecraftServer.currentTick;
+ }
+ // Paper end
}
}
@@ -409,6 +419,14 @@ public class BlockComposter extends Block implements IInventoryHolder {
} else {
this.generatorAccess.setTypeAndData(this.blockPosition, this.blockData, 3);
this.emptied = false;
+ // Paper start - keep track of inventory updates
+ Chunk chunk = generatorAccess.getMinecraftWorld().getChunkIfLoaded(blockPosition);
+ if (chunk != null) {
+ chunk.inventoryUpdateMap.put(blockPosition, MinecraftServer.currentTick);
+ } else {
+ Chunk.lastUnknownInventoryUpdate = MinecraftServer.currentTick;
+ }
+ // Paper end
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..55c3bcd3e309cf666b35c21fe0506b223b48debe 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
@@ -7,6 +7,8 @@ import net.minecraft.core.IRegistry;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
import net.minecraft.resources.MinecraftKey;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.IInventory;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.EnumBlockMirror;
import net.minecraft.world.level.block.EnumBlockRotation;
@@ -156,12 +158,28 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { /
public void update() {
if (this.world != null) {
+ // Paper start - keep track of inventory updates
+ if (this instanceof IInventory) {
+ Chunk chunk = getCurrentChunk();
+ if (chunk != null) {
+ chunk.inventoryUpdateMap.put(getPosition(), MinecraftServer.currentTick);
+ } else {
+ Chunk.lastUnknownInventoryUpdate = MinecraftServer.currentTick;
+ }
+ }
+ // Paper end
if (IGNORE_TILE_UPDATES) return; // Paper
this.c = this.world.getType(this.position);
this.world.b(this.position, this);
if (!this.c.isAir()) {
this.world.updateAdjacentComparators(this.position, this.c.getBlock());
}
+ // Paper start - keep track of inventory updates
+ } else {
+ if (this instanceof IInventory) {
+ Chunk.lastUnknownInventoryUpdate = MinecraftServer.currentTick;
+ }
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
index 537dc52e5ff3325555ee6049bc7f277952983b76..860a654ead7e7486aed1434fe2c711cc1dbca3b5 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
@@ -12,6 +12,7 @@ import net.minecraft.core.NonNullList;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.chat.ChatMessage;
import net.minecraft.network.chat.IChatBaseComponent;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.world.ContainerUtil;
import net.minecraft.world.IInventory;
import net.minecraft.world.IInventoryHolder;
@@ -29,6 +30,7 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.BlockChest;
import net.minecraft.world.level.block.BlockHopper;
import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.world.level.chunk.Chunk;
import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.shapes.OperatorBoolean;
import net.minecraft.world.phys.shapes.VoxelShapes;
@@ -159,13 +161,15 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
if (!this.m() && (Boolean) this.getBlock().get(BlockHopper.ENABLED)) {
boolean flag = false;
- if (!this.isEmpty()) {
+ if (!shouldSkipPush() && !this.isEmpty()) { // Paper - don't attempt a futile push
flag = this.k();
}
+ lastAttemptedPush = MinecraftServer.currentTick; // Paper
- if (!this.j()) {
+ if (!shouldSkipPull() && !this.isFull()) { // Paper - don't attempt a futile pull
flag |= (Boolean) supplier.get();
}
+ lastAttemptedPull = MinecraftServer.currentTick; // Paper
if (flag) {
this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
@@ -180,6 +184,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
}
}
+ private boolean isFull() { return j(); } // Paper - OBFHELPER
private boolean j() {
Iterator iterator = this.items.iterator();
@@ -221,6 +226,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
itemstack = callPushMoveEvent(iinventory, itemstack);
if (itemstack == null) { // cancelled
origItemStack.setCount(origCount);
+ lastSuccessfulPush = MinecraftServer.currentTick; // Count as success because plugins are unpredictable
return false;
}
}
@@ -234,6 +240,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
}
this.setItem(i, origItemStack);
iinventory.update();
+ lastSuccessfulPush = MinecraftServer.currentTick;
return true;
}
origItemStack.setCount(origCount);
@@ -256,6 +263,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
itemstack = callPullMoveEvent(ihopper, iinventory, itemstack);
if (itemstack == null) { // cancelled
origItemStack.setCount(origCount);
+ if (ihopper instanceof TileEntityHopper) ((TileEntityHopper) ihopper).lastSuccessfulPull = MinecraftServer.currentTick; // Count as a success because plugins are unpredictable
// Drastically improve performance by returning true.
// No plugin could of relied on the behavior of false as the other call
// site for IMIE did not exhibit the same behavior
@@ -275,6 +283,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
iinventory.setItem(i, origItemStack);
IGNORE_TILE_UPDATES = false;
iinventory.update();
+ if (ihopper instanceof TileEntityHopper) ((TileEntityHopper) ihopper).lastSuccessfulPull = MinecraftServer.currentTick;
return true;
}
origItemStack.setCount(origCount);
@@ -349,6 +358,81 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
}
}
// Paper end
+ // Paper start - skip unnecessary hopper pulls and pushes
+ private int lastUpdate = Integer.MIN_VALUE;
+ private int lastAttemptedPull = Integer.MIN_VALUE;
+ private int lastSuccessfulPull = Integer.MIN_VALUE;
+ private int lastAttemptedPush = Integer.MIN_VALUE;
+ private int lastSuccessfulPush = Integer.MIN_VALUE;
+ private static final java.util.function.BiPredicate<Chunk, Integer> containsInventories = (chunk, section) -> chunk.getInventoryEntityCounts()[section] > 0;
+ private static final java.util.function.BiPredicate<Chunk, Integer> containsItemsOrInventories = (chunk, section) -> chunk.getItemCounts()[section] > 0 || chunk.getInventoryEntityCounts()[section] > 0;
+
+ private boolean shouldSkipPull() {
+ return lastAttemptedPull > lastSuccessfulPull && // the last attempted pull was unsuccessful
+ Chunk.lastUnknownInventoryUpdate < lastAttemptedPush && // there have been no inventories with unknown locations updated since the last attempted pull
+ noNearbySectionsMatch(position.add(0, 1, 0), containsItemsOrInventories) && // there are no items or inventories we can pull
+ lastUpdate < lastAttemptedPull && // this hopper has not changed state since the last attempted pull
+ getCurrentChunk().inventoryUpdateMap.getOrDefault(position.add(0, 1, 0), Integer.MIN_VALUE) < lastAttemptedPull; // the inventory above has not changed state since the last attempted pull
+ }
+
+ private boolean shouldSkipPush() {
+ if (lastAttemptedPush <= lastSuccessfulPush) { // the last attempted push was successful
+ return false;
+ }
+ BlockPosition toPosition = this.position.shift(this.getBlock().get(BlockHopper.FACING));
+ if (noNearbySectionsMatch(toPosition, containsInventories) && // there are no inventory entities we can push to
+ Chunk.lastUnknownInventoryUpdate < lastAttemptedPush && // there have been no inventories with unknown locations updated since the last attempted push
+ lastUpdate < lastAttemptedPush // this hopper has not changed state since the last attempted push
+ ) {
+ Chunk chunk = getCurrentChunk();
+ // toPosition may not be in the same chunk as the hopper so we have to check
+ int toChunkOffsetX = ((toPosition.getX() + 3 >> 4) - chunk.locX) + ((toPosition.getX() - 2 >> 4) - chunk.locX);
+ int toChunkOffsetZ = ((toPosition.getZ() + 3 >> 4) - chunk.locZ) + ((toPosition.getZ() - 2 >> 4) - chunk.locZ);
+ if (toChunkOffsetX != 0 || toChunkOffsetZ != 0) {
+ chunk = chunk.getRelativeNeighbourIfLoaded(toChunkOffsetX, toChunkOffsetZ);
+ }
+ if (chunk != null) {
+ return chunk.inventoryUpdateMap.getOrDefault(toPosition, Integer.MIN_VALUE) < lastAttemptedPush; // the inventory the hopper is facing has not changed state since the last attempted push
+ }
+ }
+ return false;
+ }
+
+ // Returns true if none of the sections near to (within two blocks of) blockPosition satisfy predicate
+ // This method assumes blockPosition is no more than 16 blocks from the hopper
+ private boolean noNearbySectionsMatch(BlockPosition blockPosition, java.util.function.BiPredicate<Chunk, Integer> predicate) {
+ Chunk currentChunk = getCurrentChunk();
+ final int minY = Math.max(0, (blockPosition.getY() - 2) >> 4);
+ final int maxY = Math.min(15, (blockPosition.getY() + 2 + 2) >> 4);
+ for (int y = minY; y <= maxY; y++) {
+ if (predicate.test(currentChunk, y)) {
+ return false;
+ }
+ }
+
+ final int offsetX = ((blockPosition.getX() + 3 >> 4) - currentChunk.locX) + ((blockPosition.getX() - 2 >> 4) - currentChunk.locX);
+ final int offsetZ = ((blockPosition.getZ() + 3 >> 4) - currentChunk.locZ) + ((blockPosition.getZ() - 2 >> 4) - currentChunk.locZ);
+ for (int x = Math.min(0, offsetX); x <= Math.max(0, offsetX); x++) {
+ for (int z = Math.min(0, offsetZ); z <= Math.max(0, offsetZ); z++) {
+ Chunk chunk = currentChunk.getRelativeNeighbourIfLoaded(x, z);
+ if (chunk == null) continue;
+ for (int y = minY; y <= maxY; y++) {
+ if (predicate.test(chunk, y)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ lastUpdate = MinecraftServer.currentTick; // Keep track of updates locally so we don't have to do an extra map lookup in shouldSkipPull and shouldSkipPull
+ }
+ // Paper end
private boolean k() {
IInventory iinventory = this.l();
diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java
index 226f9e5a3d867b5365f3ea44c1459ed7265c1b41..305d01a71aebddc9f534b9e026e615c584416920 100644
--- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java
@@ -147,6 +147,17 @@ public class Chunk implements IChunkAccess {
// Keep this synced with entitySlices.add() and entitySlices.remove()
private final int[] itemCounts = new int[16];
private final int[] inventoryEntityCounts = new int[16];
+
+ public int[] getItemCounts() {
+ return itemCounts;
+ }
+
+ public int[] getInventoryEntityCounts() {
+ return inventoryEntityCounts;
+ }
+ // Keep track of inventory updates
+ public static Integer lastUnknownInventoryUpdate = Integer.MIN_VALUE;
+ public it.unimi.dsi.fastutil.objects.Object2IntMap<BlockPosition> inventoryUpdateMap = new it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap<>();
// Paper end
// Tuinity start - optimise hard collision handling