Updated Upstream and Sidestream(s) (Paper/Tuinity/Purpur/Airplane/Empirecraft) (#412)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Paper Changes:
0ea308381 Updated Upstream (Bukkit/CraftBukkit)

Tuinity Changes:
a539774 Fix off-by-one for BasicEntityList
0763cd1 Updated Upstream (Paper)
ad35543 Various optimisations
2006b9b Discord vanity URL

Purpur Changes:
4086888 [ci-skip] Fix formatting issue in previous commit
70ec0e2 Updated Upstream (Paper & Tuinity)
d7d72b3 Remove unused event from api
6ec1ed7 [ci-skip] hmm

Airplane Changes:
7dc1546 Updated Upstream (Tuinity)
04fd4dc Updated Upstream (Tuinity)

Empirecraft Changes:
586aef63 Prevent grindstones from overstacking items
4cf96630 Updated Paper
This commit is contained in:
Simon Gardling 2021-02-19 14:39:10 -05:00 committed by GitHub
parent 59848dbcd2
commit c18ae50aab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 1703 additions and 1114 deletions

View File

@ -248,12 +248,12 @@ This is an overview over all patches that are currently used.
| server | New nbt cache | Hugo Planque | ishland |
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| server | Optimise EntityInsentient#checkDespawn | Spottedleaf | |
| server | Optimise WorldServer#notify | Spottedleaf | |
| server | Optimise chunk tick iteration | Spottedleaf | |
| server | Optimise closest entity lookup used by AI goals | Spottedleaf | |
| server | Optimise closest entity lookup | Spottedleaf | |
| server | Optimise collision checking in player move packet handling | Spottedleaf | |
| server | Optimise entity hard collision checking | Spottedleaf | |
| server | Optimise nearby player lookups | Spottedleaf | |
| server | Optimise non-flush packet sending | Spottedleaf | |
| server | Optimise portals | Ivan Pekov | |
| server | Optimise tab complete | Spottedleaf | |
@ -275,7 +275,6 @@ This is an overview over all patches that are currently used.
| server | PaperPR - Add hex color code support for console logging | Esophose | |
| server | PaperPR - Config option for Piglins guarding chests | jmp | |
| server | PaperPR - Fix username connecting with no texture being | Camotoy | |
| api | PaperPR - PlayerItemCooldownEvent | KennyTV | |
| server | Per World Spawn Limits | Chase Whipple | |
| server | Per entity (type) collision settings | MrIvanPlays | tr7zw |
| server | Persistent TileEntity Lore and DisplayName | jmp | |
@ -296,13 +295,13 @@ This is an overview over all patches that are currently used.
| server | Populator seed controls | Spottedleaf | |
| server | Port hydrogen | JellySquid | |
| server | Preload ProtocolLib EnumWrappers | ishland | |
| server | Prevent grindstones from overstacking items | chickeneer | |
| server | Prevent light queue overfill when no players are online | Spottedleaf | |
| server | Prevent long map entry creation in light engine | Spottedleaf | |
| server | Prevent unload() calls removing tickets for sync loads | Spottedleaf | |
| server | Properly handle cancellation of projectile hit event | Spottedleaf | |
| server | Purpur config files | William Blake Galbreath | |
| api | Purpur config files | William Blake Galbreath | |
| server | Queue lighting update only once | Paul Sauve | |
| server | Rabbit naturally spawn toast and killer | William Blake Galbreath | |
| api | Rabid Wolf API | Encode42 | |
| server | Raid cooldown setting | jmp | |

2
Paper

@ -1 +1 @@
Subproject commit 088fa6f28b029e58cfe286608fff9803f932a512
Subproject commit 0ea3083817707d792ebac246895455a0aa0d3425

View File

@ -26,6 +26,8 @@ internal fun Project.createApplyPatchesTask(
}
fun applyPatches(patchDir: Path, applyName: String, name: String, wasGitSigningEnabled: Boolean, projectDir: File): Boolean {
if (Files.notExists(patchDir)) return true
val patchPaths = Files.newDirectoryStream(patchDir)
.map { it.toFile() }
.filter { it.name.endsWith(".patch") }

View File

@ -88,10 +88,10 @@ index 2e7721a650c5a351b3584665bd236f92ef577761..b3c2b461b2a654a9e37a57f2f62b3ba8
return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1);
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 7c367fe6152c30aab3e53c8f88cceba606891c93..6e6059daba05d7ce3aabeed85cc0e0d2daa04f92 100644
index 87766db4e3c2e522b738fa304a861dc0985d878a..44f52fb6e3aedeadec4be3979ad1c625643cf9fa 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -332,6 +332,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -363,6 +363,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return null;
}

View File

@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 31 Oct 2020 19:03:25 -0500
Subject: [PATCH] Queue lighting update only once
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/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 9e6381a60b804a957eda5b72582d5545faebcb3e..1da5c7def8b476cf638548b05d3e2015bc372f51 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -996,6 +996,7 @@ public class ChunkProviderServer extends IChunkProvider {
// Paper - moved up
// Tuinity start - optimise chunk tick iteration
com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<Chunk> iterator = this.entityTickingChunks.iterator();
+ boolean updateLighting = false; // Airplane
try {
while (iterator.hasNext()) {
Chunk chunk = iterator.next();
@@ -1020,7 +1021,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
this.world.timings.chunkTicks.startTiming(); // Spigot // Paper
- this.world.a(chunk, k);
+ if (this.world.abool(chunk, k)) updateLighting = true; // Airplane
this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper
MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick
}
@@ -1030,6 +1031,7 @@ public class ChunkProviderServer extends IChunkProvider {
} finally {
iterator.finishedIterating();
}
+ if (updateLighting) this.getLightEngine().queueUpdate(); // Airplane
// Tuinity end - optimise chunk tick iteration
this.world.getMethodProfiler().enter("customSpawners");
if (flag1) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 307794aebb4ccd4d409013ed485e6defda2149ca..f599f80a543cfd3de97e5f80372ffed6c7bfd9ff 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1027,7 +1027,10 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom();
// Paper end
- public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
+ // Airplane start - create version of chunk tick that returns a bool for updating lighting
+ public void a(Chunk chunk, int i) { this.abool(chunk, i); }
+ public boolean abool(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
+ // Airplane end
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
int j = chunkcoordintpair.d();
@@ -1136,9 +1139,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
gameprofilerfiller.exit();
timings.chunkTicksBlocks.stopTiming(); // Paper
- getChunkProvider().getLightEngine().queueUpdate(); // Paper
+ // Airplane start
+ //getChunkProvider().getLightEngine().queueUpdate(); // Paper
+ return true;
+ // Airplane end
// Paper end
}
+ return false; // Airplane
}
protected BlockPosition a(BlockPosition blockposition) {

View File

@ -23,10 +23,10 @@ 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/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index f599f80a543cfd3de97e5f80372ffed6c7bfd9ff..fdab9a50bc5d433c76fda1501110524792a749c8 100644
index 5d92398369862881d997c270671ddb6b78ed2cb4..6694a669f9fbae0dce857e97651ed527f5481427 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1040,7 +1040,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1134,7 +1134,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

View File

@ -34,7 +34,7 @@ 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/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 68d6fb69a0c1b98b3c11b6d80783faaa58272526..fa1d559a07199bf52d8ae04b2c34261efdebdcdb 100644
index 8fda4702764e80dae93ef9c0eb53abc198642ab1..0924f6b484468f3cf3c2d405101c0158c12d69e6 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -53,6 +53,18 @@ public class Chunk implements IChunkAccess {
@ -56,19 +56,19 @@ index 68d6fb69a0c1b98b3c11b6d80783faaa58272526..fa1d559a07199bf52d8ae04b2c34261e
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) {
this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null);
}
@@ -325,6 +337,7 @@ public class Chunk implements IChunkAccess {
@@ -287,6 +299,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;
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 1da5c7def8b476cf638548b05d3e2015bc372f51..03bcd704e3c08f5b54b124df1583e3ccdb4cb485 100644
index 18270d44185b0ec41b9b6e1d2135e7aae3b33261..e8a6bc2654e840395fee70d79695c5a395a4fc1b 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -965,6 +965,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -973,6 +973,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
// Paper end - optimize isOutisdeRange
this.world.getMethodProfiler().enter("pollingChunks");
@ -77,19 +77,19 @@ index 1da5c7def8b476cf638548b05d3e2015bc372f51..03bcd704e3c08f5b54b124df1583e3cc
boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index fdab9a50bc5d433c76fda1501110524792a749c8..6dc1f6d7f734b8c769c86109701155ebe9c2f6bd 100644
index 6694a669f9fbae0dce857e97651ed527f5481427..dd9ae27a208b5e55a1c473eda6e068a0fc3eb64f 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1027,6 +1027,8 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1124,6 +1124,8 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom();
// Paper end
+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane
+
// Airplane start - create version of chunk tick that returns a bool for updating lighting
public void a(Chunk chunk, int i) { this.abool(chunk, i); }
public boolean abool(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
@@ -1040,7 +1042,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
@@ -1134,7 +1136,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
@ -98,7 +98,7 @@ index fdab9a50bc5d433c76fda1501110524792a749c8..6dc1f6d7f734b8c769c86109701155eb
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);
@@ -1070,7 +1072,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1164,7 +1166,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
gameprofilerfiller.exitEnter("iceandsnow");

View File

@ -98,7 +98,7 @@ index 4a3469aca9f9e47d2ea3f3bae6ce77f5f11d6b50..5af5b50889961b10e812598dbea657c4
++this.conversionTicks;
if (this.conversionTicks > 300) {
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 65841a7bb58e210f07c0afd74c2fd5b3873bdd60..4c2e0b8aafecbc2a4b68e2c30b64db1c692d3667 100644
index d6a086f59d9df8ef7f727e6a83fa51a14995123e..cb094f00b6c7869632b9dacfc2c8c8e8299fddde 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -133,10 +133,10 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -30,7 +30,7 @@ index b884addf2ce6f1ef7394658078deb2e75370654f..e20b91b36587d1191f8f9e8dd501607b
boolean flag1 = iblockdata.getFluid().a((Tag) TagsFluid.WATER);
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index ee91c33a7a2edca02caf5c71fd6429f97eac7e2d..324b78a51557cdd97e125f22eff8a4f54153d9f4 100644
index ae17950438132c5084210252bd345517131d5a99..1016305a571a2fc211cd0e58b7210d8cfb4461d5 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -372,7 +372,10 @@ public final class SpawnerCreature {

View File

@ -56,10 +56,10 @@ index 631eb682e81e30d2a937fd1eafccd8a9ab82d21e..dc07376845f84ea949a2153cb75d2cd9
return (EntityTypes) IRegistry.a((IRegistry) IRegistry.ENTITY_TYPE, s, (Object) entitytypes_builder.a(s));
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a996343d62a88d 100644
index 61570ab947b5a153a4c2bcb5a09344f060e6052d..121deda90227cb0416d6642607b24093df2baa80 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -638,7 +638,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -641,7 +641,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return d2 * d2 + d3 * d3;
}
@ -70,7 +70,7 @@ index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a99634
int i;
int j;
@@ -652,12 +654,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -655,12 +657,16 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
j = MathHelper.floor(entityplayer.locZ() / 16.0D);
}
@ -91,7 +91,7 @@ index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a99634
return Math.max(Math.abs(k), Math.abs(l));
}
@@ -2496,11 +2502,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2499,11 +2505,17 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
boolean flag1 = this.tracker.attachedToPlayer;
if (!flag1) {
@ -111,7 +111,7 @@ index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a99634
}
}
@@ -2530,8 +2542,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2533,8 +2545,10 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
}
private int b() {
@ -123,7 +123,7 @@ index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a99634
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
@@ -2543,6 +2557,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2546,6 +2560,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
i = j;
}
}
@ -133,10 +133,10 @@ index 2c2becef8b56d7e5e998976222df85d2c8516c43..cde7d0e641b2e1e8e6a4ce9510a99634
return this.a(i);
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 6e6059daba05d7ce3aabeed85cc0e0d2daa04f92..6e4c7a9b32c9e8057db3cbcead0b75d858fd6e18 100644
index 44f52fb6e3aedeadec4be3979ad1c625643cf9fa..8c162c5fdeaffccc9a28b592e030971fe51cafb3 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1055,19 +1055,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -1086,19 +1086,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public void a(Consumer<Entity> consumer, Entity entity) {
try {
@ -160,10 +160,10 @@ index 6e6059daba05d7ce3aabeed85cc0e0d2daa04f92..6e4c7a9b32c9e8057db3cbcead0b75d8
// Paper start - Prevent armor stands from doing entity lookups
@Override
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 6dc1f6d7f734b8c769c86109701155ebe9c2f6bd..2289c92c8933bfa0f382167fa5790a4ea17b7c75 100644
index dd9ae27a208b5e55a1c473eda6e068a0fc3eb64f..d4672e7fa899a39bae2d9179472b22db28a58f19 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -915,7 +915,28 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1012,7 +1012,28 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("tick");
if (!entity.dead && !(entity instanceof EntityComplexPart)) {
@ -192,7 +192,7 @@ index 6dc1f6d7f734b8c769c86109701155ebe9c2f6bd..2289c92c8933bfa0f382167fa5790a4e
}
gameprofilerfiller.exit();
@@ -1286,9 +1307,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1376,9 +1397,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
++entity.ticksLived;
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();

View File

@ -19,10 +19,10 @@ index 657885cdaa086293f6b5aa6f3058acd16df0ba35..8724ad342bec7c733b3c825bd62dbfa5
Block.a(iblockdata, iblockdata1, generatoraccess, blockposition_mutableblockposition, i, j);
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 6e4c7a9b32c9e8057db3cbcead0b75d858fd6e18..c0872f8a53b862558c7fa2fe17ebb0a796da03ce 100644
index 8c162c5fdeaffccc9a28b592e030971fe51cafb3..bfc7a1c234b5fe4aa58b48c3673f473d26561077 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -774,7 +774,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -805,7 +805,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public void neighborChanged(BlockPosition pos, Block blockIn, BlockPosition fromPos) { a(pos, blockIn, fromPos); } // Paper - OBFHELPER
public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) {
if (!this.isClientSide) {

View File

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: chickeneer <emcchickeneer@gmail.com>
Date: Tue, 16 Feb 2021 16:28:00 -0600
Subject: [PATCH] Prevent grindstones from overstacking items
diff --git a/src/main/java/net/minecraft/server/ContainerGrindstone.java b/src/main/java/net/minecraft/server/ContainerGrindstone.java
index 39f809a37b58e008e7ef32c0759eeecbde26bc94..458d9828a9e3023dd469f76320a1d513c85fd892 100644
--- a/src/main/java/net/minecraft/server/ContainerGrindstone.java
+++ b/src/main/java/net/minecraft/server/ContainerGrindstone.java
@@ -183,7 +183,7 @@ public class ContainerGrindstone extends Container {
i = Math.max(item.getMaxDurability() - l, 0);
itemstack2 = this.b(itemstack, itemstack1);
if (!itemstack2.e()) {
- if (!ItemStack.matches(itemstack, itemstack1)) {
+ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper
this.resultInventory.setItem(0, ItemStack.b);
this.c();
return;

View File

@ -129,7 +129,7 @@ index 0000000000000000000000000000000000000000..fe7330fabe386966c2d203a190a00a78
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index c0872f8a53b862558c7fa2fe17ebb0a796da03ce..77c748ad07ee257742c4d36825bdd9e916b5d851 100644
index bfc7a1c234b5fe4aa58b48c3673f473d26561077..4ffaf36b40b32be25bd1944d8b8ddbc342256947 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -97,6 +97,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -141,7 +141,7 @@ index c0872f8a53b862558c7fa2fe17ebb0a796da03ce..77c748ad07ee257742c4d36825bdd9e9
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
public static BlockPosition lastPhysicsProblem; // Spigot
private org.spigotmc.TickLimiter entityLimiter;
@@ -199,6 +201,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -230,6 +232,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper
this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config
this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig(((WorldDataServer) worlddatamutable).getName(), env); // Purpur

View File

@ -1,89 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: KennyTV <kennytv@t-online.de>
Date: Mon, 20 Apr 2020 13:57:13 +0200
Subject: [PATCH] PaperPR - PlayerItemCooldownEvent
diff --git a/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java b/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2002909f30d2bd833dc13cf09b0bc4bdae0d6757
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/event/player/PlayerItemCooldownEvent.java
@@ -0,0 +1,77 @@
+package net.pl3x.purpur.event.player;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player receives a cooldown on an item.
+ */
+public final class PlayerItemCooldownEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ @NotNull
+ private final Material type;
+ private int cooldown;
+ private boolean cancelled;
+
+ public PlayerItemCooldownEvent(@NotNull Player player, @NotNull Material type, int cooldown) {
+ super(player);
+ this.type = type;
+ this.cooldown = cooldown;
+ }
+
+ /**
+ * Get the material affected by the cooldown.
+ *
+ * @return material affected by the cooldown
+ */
+ @NotNull
+ public Material getType() {
+ return type;
+ }
+
+ /**
+ * Gets the cooldown in ticks.
+ *
+ * @return cooldown in ticks
+ */
+ public int getCooldown() {
+ return cooldown;
+ }
+
+ /**
+ * Sets the cooldown of the material in ticks.
+ * Setting the cooldown to 0 results in removing an already existing cooldown for the material.
+ *
+ * @param cooldown cooldown in ticks, has to be a positive number
+ */
+ public void setCooldown(int cooldown) {
+ Preconditions.checkArgument(cooldown >= 0, "The cooldown has to be equal to or greater than 0!");
+ this.cooldown = cooldown;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ cancelled = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@ -78,7 +78,7 @@ index de9ea6770b8afc5e1020bef04ac6cca93b6b420c..21d0570a59240e955ff148bac0226b22
if (this.bF) {
this.bF = false;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 93c0c3376c3cb2fe416c8ae3e740ffda5f985b78..226b5cd399449ca3587964221765e4d241dfc739 100644
index 970c1be5477a01ab9c6d79e84c519e22775564ff..ee1d5e2dc9fb21190a73e0f333e962a19264dd56 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -95,6 +95,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -89,7 +89,7 @@ index 93c0c3376c3cb2fe416c8ae3e740ffda5f985b78..226b5cd399449ca3587964221765e4d2
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
public static BlockPosition lastPhysicsProblem; // Spigot
@@ -154,8 +155,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -185,8 +186,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, final DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper

View File

@ -84,7 +84,7 @@ index 173a210392d71cdfc551f095dc0d9c9040d22d3f..7d7a512ad752e15fbe0edce47da1da76
return this.serverStatisticManager;
}
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index 93f2ac996904ddefed04704e554209d047faa59f..b1a546c9ef91169591ed5a71ac1c97dbc84afc03 100644
index ad286848ddb7803640ef7eeea46b58473dd1d0c4..2e514b8291a544a88667fbca2389bde4c2ecb109 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -174,28 +174,18 @@ public interface IEntityAccess {
@ -193,10 +193,10 @@ index 4185ec46435ddf48d9e25c4d71ac4e14eb6301cf..1d810a9b23d236493db121dde92c7ebc
if (from.getX() != Double.MAX_VALUE) {
Location oldTo = to.clone();
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 9a8a1e05a60bca77adc904017ae70ef5f629df0b..cc1182be1f9b01ab5d8e2499f7f15ad8798de3d3 100644
index d2b50cdc43c737d9fdfdcd7838de24cbca2017e4..9759e5cba57d14c15f78f12985a516131800d004 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -790,7 +790,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -887,7 +887,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end
if (this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> {
@ -205,7 +205,7 @@ index 9a8a1e05a60bca77adc904017ae70ef5f629df0b..cc1182be1f9b01ab5d8e2499f7f15ad8
})) {
// CraftBukkit start
long l = this.worldData.getDayTime() + 24000L;
@@ -1127,7 +1127,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1224,7 +1224,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
while (iterator.hasNext()) {
EntityPlayer entityplayer = (EntityPlayer) iterator.next();

View File

@ -98,7 +98,7 @@ index 9f4f56c47ecd4b35ebf33ca0bf9a040074ababf2..565c938d879940d8e12fe320ea8524d2
}
}
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 8a5e2806e68e5f4431fd9563fae780861e87632f..3936741bb8c1b3ad766d651e4bb8c9f5ddbe4f08 100644
index a47217c020d2c2a3caddafa0549dc827373798dd..07908edcaffb5ee1be8a71f3f0affb91c7e6e51b 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -950,6 +950,7 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Zombie horse naturally spawn
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index cc1182be1f9b01ab5d8e2499f7f15ad8798de3d3..30388fca6d3db797825949642d372a4091cc48c2 100644
index 9759e5cba57d14c15f78f12985a516131800d004..76058d466cf256298ea6439fffbd8d661c159f58 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1004,12 +1004,18 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1101,12 +1101,18 @@ public class WorldServer extends World implements GeneratorAccessSeed {
boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper
if (flag1) {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Cat spawning options
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index b1a546c9ef91169591ed5a71ac1c97dbc84afc03..6edff6d8ce67f64420a845e992339dadf53641f8 100644
index 2e514b8291a544a88667fbca2389bde4c2ecb109..288105ae657ade252032aa0ac9c191a8e8ebf549 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -47,6 +47,7 @@ public interface IEntityAccess {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Entities pick up loot bypass mob-griefing gamerule
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 3936741bb8c1b3ad766d651e4bb8c9f5ddbe4f08..ac6460d261014bb4b9878c96e4b447f7a471752d 100644
index 07908edcaffb5ee1be8a71f3f0affb91c7e6e51b..d38102bbf48dd498d80911e954e910a33d390daa 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -546,7 +546,7 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -36,10 +36,10 @@ index b2a76db173ae12bff2e8a7de411cb489fdb2e9c7..2a5eda6a7e67d0b8682a96552248ea4e
private CraftMerchant craftMerchant;
diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
index f1a509063c09e603140c74255a3fb901693d2cc5..74c2d89af516ffc252032d5cbd12b489ea46813e 100644
index fa3e786cd6ef67da378a5d51583ca84a82677d8c..47a89bdd163d4690fa96f63d7a9723b3bcc9fa0b 100644
--- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
@@ -40,6 +40,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -41,6 +41,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
this.goalSelector.a(1, new PathfinderGoalPanic(this, 0.5D));
this.goalSelector.a(1, new PathfinderGoalLookAtTradingPlayer(this));
this.goalSelector.a(2, new EntityVillagerTrader.a(this, 2.0D, 0.35D));

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Allow leashing villagers
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index ac6460d261014bb4b9878c96e4b447f7a471752d..fe721a8aac68c07476ad44244f00dc5e1ac9c02f 100644
index d38102bbf48dd498d80911e954e910a33d390daa..566d6a2551ffbcf4366596cab87a7239a75156c6 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -1147,6 +1147,7 @@ public abstract class EntityInsentient extends EntityLiving {
@ -33,10 +33,10 @@ index 1cde71b812c7721298e7addb74de01e4ea297499..e4aedb3df5d0a47b5bb9175627aa794f
@Override
diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
index 74c2d89af516ffc252032d5cbd12b489ea46813e..96dda6a14fd17509e9bcb72cc7e9c8532c6a036b 100644
index 47a89bdd163d4690fa96f63d7a9723b3bcc9fa0b..298d2b6f6e352bb82f3a5a307466bb6e8f47d9d3 100644
--- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
@@ -47,6 +47,13 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -48,6 +48,13 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Dispenser curse of binding protection
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index fe721a8aac68c07476ad44244f00dc5e1ac9c02f..21f94651fcb47103b12806d456417882e7f84dcd 100644
index 566d6a2551ffbcf4366596cab87a7239a75156c6..9807441d53fcf4ef7aaffe3801542f5a371eb7af 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -996,6 +996,13 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -221,7 +221,7 @@ index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10e
}
}
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index 661ad8f8e67046211e001ea40d97660d7c88f8e5..ee91c33a7a2edca02caf5c71fd6429f97eac7e2d 100644
index a77b1d61b9dcb0a2a27d7e50357eaf44c99a661e..ae17950438132c5084210252bd345517131d5a99 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -385,6 +385,7 @@ public final class SpawnerCreature {
@ -233,10 +233,10 @@ index 661ad8f8e67046211e001ea40d97660d7c88f8e5..ee91c33a7a2edca02caf5c71fd6429f9
return iblockdata.r(iblockaccess, blockposition) ? false : (iblockdata.isPowerSource() ? false : (!fluid.isEmpty() ? false : (iblockdata.a((Tag) TagsBlock.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entitytypes.a(iblockdata))));
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 226b5cd399449ca3587964221765e4d241dfc739..0f259913ddcf151bc0128f2591e1223a56a9e115 100644
index ee1d5e2dc9fb21190a73e0f333e962a19264dd56..8246bdf5e686c2089397e8669cf37968ef3de80d 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1566,6 +1566,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -1597,6 +1597,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f);
}

View File

@ -49,10 +49,10 @@ index 120bf8436fd82294c339add2e7bff1cda8311aea..848a185c04aa90a62e6bcc49ad68a748
return true;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 0f259913ddcf151bc0128f2591e1223a56a9e115..1ac2e9f373ae5b4250ff9faf726a962a739d6faf 100644
index 8246bdf5e686c2089397e8669cf37968ef3de80d..d3b3b771640a46ce9a898f645cf50007e25ae7c2 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1641,4 +1641,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -1672,4 +1672,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public final boolean isDebugWorld() {
return this.debugWorld;
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Entity lifespan
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index 21f94651fcb47103b12806d456417882e7f84dcd..fcc247e86992d1e1a94438ee4f0a70182390cc62 100644
index 9807441d53fcf4ef7aaffe3801542f5a371eb7af..ee005e482396f8ff7e46a7ca981c843a76bdda71 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -54,7 +54,7 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -22,10 +22,10 @@ index 829d4a7508e1656dbdc912096b7eafcf30cbb5b2..6aea156d7c7a9ca8a357aad6a6781d72
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 30388fca6d3db797825949642d372a4091cc48c2..138f5c577391980f2b218b25a4251ac853bb9bad 100644
index 76058d466cf256298ea6439fffbd8d661c159f58..dc15d19fb75cd0988235ce193ac7f03c35d713c7 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -321,14 +321,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -418,14 +418,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end
if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) {
this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> {

View File

@ -2201,7 +2201,7 @@ index c57bf5091430709778dc21d70c8a32819c9d6639..b0a5c36d1132e2558a1fefbd9f8dd264
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index fcc247e86992d1e1a94438ee4f0a70182390cc62..d9b00a24b378b74e126518da9142249d2ad62c55 100644
index ee005e482396f8ff7e46a7ca981c843a76bdda71..b64278a8e349467305b75b2180a4a423ed49d7e4 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -30,7 +30,7 @@ public abstract class EntityInsentient extends EntityLiving {
@ -4379,10 +4379,10 @@ index a0bfef54c853d57c9a5c6d3f9f19591649295357..548a993a1de939396d075f9176e0d60e
this.h(entityhuman);
}
diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
index 96dda6a14fd17509e9bcb72cc7e9c8532c6a036b..3ea66955df304fd13aac2cf9bb93ea156558ae57 100644
index 298d2b6f6e352bb82f3a5a307466bb6e8f47d9d3..d41960088bb8bc6a7fece0ef152403c43a768dde 100644
--- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
@@ -23,6 +23,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -24,6 +24,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
@ -4390,7 +4390,7 @@ index 96dda6a14fd17509e9bcb72cc7e9c8532c6a036b..3ea66955df304fd13aac2cf9bb93ea15
this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> {
return this.world.isNight() && !entityvillagertrader.isInvisible();
}));
@@ -48,6 +49,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -49,6 +50,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
}
// Purpur - start
@ -4407,7 +4407,7 @@ index 96dda6a14fd17509e9bcb72cc7e9c8532c6a036b..3ea66955df304fd13aac2cf9bb93ea15
@Override
public boolean a(EntityHuman entityhuman) {
return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed();
@@ -75,8 +86,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -76,8 +87,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
}
if (this.getOffers().isEmpty()) {
@ -5028,10 +5028,10 @@ index 5af554870bcf36e47aef43b966b141b9eda6c4d5..c59305ef7dd7847e204d4c4ed79758bf
return new Vec3D(this.x * d0, this.y * d1, this.z * d2);
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 1ac2e9f373ae5b4250ff9faf726a962a739d6faf..97cc98af100edfad82668200759a5eed8fc67558 100644
index d3b3b771640a46ce9a898f645cf50007e25ae7c2..34e5f8b3bf1b0045856ec0d06ec6d62d0b976862 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1650,5 +1650,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -1681,5 +1681,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public boolean isTheEnd() {
return getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END;
}
@ -5043,7 +5043,7 @@ index 1ac2e9f373ae5b4250ff9faf726a962a739d6faf..97cc98af100edfad82668200759a5eed
// Purpur end
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 138f5c577391980f2b218b25a4251ac853bb9bad..c451e71601fc48294f9161ca5ef8442d31ad96f7 100644
index dc15d19fb75cd0988235ce193ac7f03c35d713c7..9163ee821cc91f6ceb317fb4914e0394564a821b 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -102,6 +102,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Allow toggling special MobSpawners per world
In vanilla, these are all hardcoded on for world type 0 (overworld) and hardcoded off for every other world type. Default config behaviour matches this.
diff --git a/src/main/java/net/minecraft/server/MobSpawnerTrader.java b/src/main/java/net/minecraft/server/MobSpawnerTrader.java
index 8d89f51182444852062d549d23c00a93e601eb38..072ec40f751b19c2a78dfcc6e439c64358d864d3 100644
index 341af7474690b929cfa3e35cd464bbbbacb6685e..ad00ff2bd525768e4f06631d16b912c61c8eee28 100644
--- a/src/main/java/net/minecraft/server/MobSpawnerTrader.java
+++ b/src/main/java/net/minecraft/server/MobSpawnerTrader.java
@@ -132,7 +132,17 @@ public class MobSpawnerTrader implements MobSpawner {
@ -29,10 +29,10 @@ index 8d89f51182444852062d549d23c00a93e601eb38..072ec40f751b19c2a78dfcc6e439c643
if (SpawnerCreature.a(EntityPositionTypes.Surface.ON_GROUND, iworldreader, blockposition2, EntityTypes.WANDERING_TRADER)) {
blockposition1 = blockposition2;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 97cc98af100edfad82668200759a5eed8fc67558..ded92fe7c7871bae6e9741747a67636d570cdeef 100644
index 34e5f8b3bf1b0045856ec0d06ec6d62d0b976862..d72580deaa50617b5b6a991777f4b36c138308a6 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -156,7 +156,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -187,7 +187,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper
this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config
@ -42,10 +42,10 @@ index 97cc98af100edfad82668200759a5eed8fc67558..ded92fe7c7871bae6e9741747a67636d
this.generator = gen;
this.world = new CraftWorld((WorldServer) this, gen, env);
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index c451e71601fc48294f9161ca5ef8442d31ad96f7..02cbbf11a2b71573f50aac6fdfaa6643c18832bf 100644
index 9163ee821cc91f6ceb317fb4914e0394564a821b..ae3ec2eca3130943536b80bd1296eba67aa08e3c 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -339,7 +339,24 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -436,7 +436,24 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.L = new ObjectLinkedOpenHashSet();
this.Q = flag1;
this.server = minecraftserver;

View File

@ -18,7 +18,7 @@ index 1b9b43ee696575d986c25cafec07d863acb951a7..e837db171545ceacbc84a2b360cf0d95
public PacketPlayOutUpdateTime() {}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 02cbbf11a2b71573f50aac6fdfaa6643c18832bf..307794aebb4ccd4d409013ed485e6defda2149ca 100644
index ae3ec2eca3130943536b80bd1296eba67aa08e3c..5d92398369862881d997c270671ddb6b78ed2cb4 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -94,6 +94,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -29,7 +29,7 @@ index 02cbbf11a2b71573f50aac6fdfaa6643c18832bf..307794aebb4ccd4d409013ed485e6def
// CraftBukkit start
@@ -388,6 +389,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -485,6 +486,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.getServer().addWorld(this.getWorld()); // CraftBukkit
this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper
@ -37,7 +37,7 @@ index 02cbbf11a2b71573f50aac6fdfaa6643c18832bf..307794aebb4ccd4d409013ed485e6def
}
// Tuinity start - optimise collision
@@ -972,7 +974,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1069,7 +1071,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.nextTickListBlock.nextTick(); // Paper
this.nextTickListFluid.nextTick(); // Paper
this.worldDataServer.u().a(this.server, i);
@ -60,7 +60,7 @@ index 02cbbf11a2b71573f50aac6fdfaa6643c18832bf..307794aebb4ccd4d409013ed485e6def
this.setDayTime(this.worldData.getDayTime() + 1L);
}
@@ -981,6 +997,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1078,6 +1094,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void setDayTime(long i) {
this.worldDataServer.setDayTime(i);

View File

@ -33,7 +33,7 @@ index bba343542e7e6fa83ec802d97b4c139bb210ab28..d9f9e2235d091e14e5d34bb9a3273e7f
int experience = this.getRandom().nextInt(7) + 1;
org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, entityanimal, entityplayer, this.breedItem, experience);
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index ded92fe7c7871bae6e9741747a67636d570cdeef..7c367fe6152c30aab3e53c8f88cceba606891c93 100644
index d72580deaa50617b5b6a991777f4b36c138308a6..87766db4e3c2e522b738fa304a861dc0985d878a 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -104,6 +104,48 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -85,7 +85,7 @@ index ded92fe7c7871bae6e9741747a67636d570cdeef..7c367fe6152c30aab3e53c8f88cceba6
public CraftWorld getWorld() {
return this.world;
@@ -157,6 +199,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -188,6 +230,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper
this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((WorldDataServer)worlddatamutable).getName()); // Tuinity - Server Config
this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig(((WorldDataServer) worlddatamutable).getName(), env); // Purpur

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Changeable Mob Left Handed Chance
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index d9b00a24b378b74e126518da9142249d2ad62c55..de977e80eb6cad74cbea3a00702ef804693374f0 100644
index b64278a8e349467305b75b2180a4a423ed49d7e4..08efc5fec023acf68da1b5931a9b5eb8c16e9fc3 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -1137,7 +1137,7 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -1165,10 +1165,10 @@ index 60962553e4f374b38de82f2cd4d72cef3d956c72..eef51f8e5734b897164ca9514e7b49b2
@Override
diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
index 3ea66955df304fd13aac2cf9bb93ea156558ae57..32864e522b63d5d02c73a4df9f996c2ebe1b53ad 100644
index d41960088bb8bc6a7fece0ef152403c43a768dde..9eb9ace0f59366787bc2789ecabf7800b6d29d5c 100644
--- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
@@ -63,6 +63,11 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@@ -64,6 +64,11 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
public boolean a(EntityHuman entityhuman) {
return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed();
}

View File

@ -31,7 +31,7 @@ index beee80c3d8277f2d784fb6b8a4152a871ee020b0..b884addf2ce6f1ef7394658078deb2e7
@Override
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index de977e80eb6cad74cbea3a00702ef804693374f0..65841a7bb58e210f07c0afd74c2fd5b3873bdd60 100644
index 08efc5fec023acf68da1b5931a9b5eb8c16e9fc3..d6a086f59d9df8ef7f727e6a83fa51a14995123e 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -786,7 +786,8 @@ public abstract class EntityInsentient extends EntityLiving {

View File

@ -2032,7 +2032,7 @@ index 1f334d63282bd5c23dc3b275a220f09e60c34537..85f60b56b5689b77ba3d9e99e29b4f73
public final boolean e() { // Paper
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 96a6f4675dc10a0047b7d2ee4164d0376de36c27..a4bbf3d9520db9911a5709d8d8c60322ee2fb8e2 100644
index 0ea1b25bf98d71c251351807fa92d4d08eb6b06e..c8c0748628e83b6396c13afe896acc16c85109b0 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -112,7 +112,7 @@ public class ChunkProviderServer extends IChunkProvider {
@ -2210,7 +2210,7 @@ index 96a6f4675dc10a0047b7d2ee4164d0376de36c27..a4bbf3d9520db9911a5709d8d8c60322
public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier<WorldPersistentData> supplier) {
this.world = worldserver;
this.serverThreadQueue = new ChunkProviderServer.a(worldserver);
@@ -591,8 +750,8 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -599,8 +758,8 @@ public class ChunkProviderServer extends IChunkProvider {
return !this.a(playerchunk, k);
}
@ -2349,10 +2349,10 @@ index 95dd6f2034439699399b0f51ab2b761a5747331d..c9692b3e50c503affaadd217c1660291
midTickLoadChunks(); // Paper
} catch (Throwable throwable) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 42b12ad5ba68bdf8f76704ddd970715770183de0..12a207afc263f02ba1971777fe5c30d120ba9292 100644
index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..b03865a932d341ae2fdad6c9447979fa9e95fc14 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -504,6 +504,7 @@ public class PlayerChunk {
@@ -508,6 +508,7 @@ public class PlayerChunk {
// Paper end - per player view distance
}
@ -2360,7 +2360,7 @@ index 42b12ad5ba68bdf8f76704ddd970715770183de0..12a207afc263f02ba1971777fe5c30d1
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) {
int i = chunkstatus.c();
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = (CompletableFuture) this.statusFutures.get(i);
@@ -674,6 +675,9 @@ public class PlayerChunk {
@@ -678,6 +679,9 @@ public class PlayerChunk {
// Paper start - rewrite ticklistserver
PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z);
// Paper end - rewrite ticklistserver
@ -2370,7 +2370,7 @@ index 42b12ad5ba68bdf8f76704ddd970715770183de0..12a207afc263f02ba1971777fe5c30d1
}
});
@@ -684,6 +688,12 @@ public class PlayerChunk {
@@ -688,6 +692,12 @@ public class PlayerChunk {
if (flag4 && !flag5) {
this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage
this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@ -2383,7 +2383,7 @@ index 42b12ad5ba68bdf8f76704ddd970715770183de0..12a207afc263f02ba1971777fe5c30d1
}
boolean flag6 = playerchunk_state.isAtLeast(PlayerChunk.State.ENTITY_TICKING);
@@ -701,7 +711,9 @@ public class PlayerChunk {
@@ -705,7 +715,9 @@ public class PlayerChunk {
Chunk entityTickingChunk = either.left().get();
PlayerChunk.this.isEntityTickingReady = true;
@ -2394,7 +2394,7 @@ index 42b12ad5ba68bdf8f76704ddd970715770183de0..12a207afc263f02ba1971777fe5c30d1
}
@@ -713,6 +725,12 @@ public class PlayerChunk {
@@ -717,6 +729,12 @@ public class PlayerChunk {
if (flag6 && !flag7) {
this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage
this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@ -2495,7 +2495,7 @@ index e21c747b6c39155c44bf30860681d67b0b29fb12..9f4f9df09968dc45878ad59f5ee45672
return voxelshape != b() && voxelshape1 != b() ? (voxelshape.isEmpty() && voxelshape1.isEmpty() ? false : !c(b(), b(voxelshape, voxelshape1, OperatorBoolean.OR), OperatorBoolean.ONLY_FIRST)) : true;
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2b94c195db43d8e7fd58301a33377e87daa16e98..2abce373f7dc4223f40b900e2e2b2e1aa8f0a6bf 100644
index cf7d94aabab600822eb5e27f38690b06456d5fcc..4183117fe3977e4f0c927b4262a4804bcb8738f6 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -55,6 +55,7 @@ import org.bukkit.event.server.MapInitializeEvent;

View File

@ -200,10 +200,10 @@ index 76f9bb728def91744910d0b680b73e753f1a2b26..84ff9cfe89defad2e907708f837d33f6
for (java.util.Iterator<Entry<ArraySetSorted<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index a4bbf3d9520db9911a5709d8d8c60322ee2fb8e2..a61a9e71c435000eab1b906026767a45c998dafa 100644
index c8c0748628e83b6396c13afe896acc16c85109b0..4082c4f366bce1784759bda773d3d35472403ade 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1190,6 +1190,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1198,6 +1198,7 @@ public class ChunkProviderServer extends IChunkProvider {
@Override
protected boolean executeNext() {
@ -304,7 +304,7 @@ index 8efdd9bd0827d1f6a31d5f943f986dabe7d05137..43b5fa67a6b6e778a059063390fb47d6
IBlockData iblockdata1 = oldBlock;
IBlockData iblockdata2 = actualBlock;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2abce373f7dc4223f40b900e2e2b2e1aa8f0a6bf..bc324860305c216c18f52f34dbf2564f61067bd5 100644
index 4183117fe3977e4f0c927b4262a4804bcb8738f6..e285038154d83cbf0d7c0b6b8a247c11b9e20119 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1661,6 +1661,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -140,7 +140,7 @@ index 8c7080777b370f97e1291dfedde5b419290f39cc..7fff1b3e4eda519851b714502d33122c
});
throw CancelledPacketHandleException.INSTANCE;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index bc324860305c216c18f52f34dbf2564f61067bd5..e1fbbb47cd665193bc8aa6188524cd8a9dedbb60 100644
index e285038154d83cbf0d7c0b6b8a247c11b9e20119..97a9a201a055520a7ab92b3ecc8987eb560bf263 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -901,7 +901,26 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -18,10 +18,10 @@ index a263cd7a0680e0cc3517f84308118eb32c487732..77df6888803093ad9527d276033f2ed7
// re-schedule eventually
toTick.tickState = STATE_SCHEDULED;
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index a61a9e71c435000eab1b906026767a45c998dafa..722a61d290243dc60dd9b7b9ae17572040e14f14 100644
index 4082c4f366bce1784759bda773d3d35472403ade..7bb23731b548d5344013429a7d7df13686cb2249 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -885,7 +885,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -893,7 +893,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.getMethodProfiler().enter("purge");
this.world.timings.doChunkMap.startTiming(); // Spigot
this.chunkMapDistance.purgeTickets();
@ -30,7 +30,7 @@ index a61a9e71c435000eab1b906026767a45c998dafa..722a61d290243dc60dd9b7b9ae175720
this.tickDistanceManager();
this.world.timings.doChunkMap.stopTiming(); // Spigot
this.world.getMethodProfiler().exitEnter("chunks");
@@ -895,7 +895,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -903,7 +903,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.timings.doChunkUnload.startTiming(); // Spigot
this.world.getMethodProfiler().exitEnter("unload");
this.playerChunkMap.unloadChunks(booleansupplier);
@ -39,16 +39,25 @@ index a61a9e71c435000eab1b906026767a45c998dafa..722a61d290243dc60dd9b7b9ae175720
this.world.timings.doChunkUnload.stopTiming(); // Spigot
this.world.getMethodProfiler().exit();
this.clearCache();
@@ -996,7 +996,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -975,6 +975,8 @@ public class ChunkProviderServer extends IChunkProvider {
// Paper end
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
+ int ticked = 0; // Tuinity - exec chunk tasks during world tick
+
this.p = spawnercreature_d;
this.world.getMethodProfiler().exit();
//List<PlayerChunk> list = Lists.newArrayList(this.playerChunkMap.f()); // Paper
@@ -1004,7 +1006,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.timings.chunkTicks.startTiming(); // Spigot // Paper
this.world.a(chunk, k);
this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper
- if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper
+ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick
+ if ((++ticked & 1) == 0) MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick
}
}
}
@@ -1152,41 +1152,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1160,41 +1162,7 @@ public class ChunkProviderServer extends IChunkProvider {
ChunkProviderServer.this.world.getMethodProfiler().c("runTask");
super.executeTask(runnable);
}
@ -279,7 +288,7 @@ index 43b5fa67a6b6e778a059063390fb47d6a599a948..165b8e20ab090284b7c70b5cc9c0d582
// Paper start - Prevent armor stands from doing entity lookups
@Override
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index e1fbbb47cd665193bc8aa6188524cd8a9dedbb60..da9172303b8acf5613b283a98bf7f6f0fe859d62 100644
index 97a9a201a055520a7ab92b3ecc8987eb560bf263..f2e630598320f7f09ecdee5a9a548b20cc1b7877 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -297,6 +297,10 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -22,10 +22,10 @@ With this change I could get all 200 on at 0ms ping.
So in general this patch should reduce Netty I/O thread load.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 722a61d290243dc60dd9b7b9ae17572040e14f14..fb21da40b4ceccd521393851f533f9ed9ddcd677 100644
index 7bb23731b548d5344013429a7d7df13686cb2249..c8c4d4f3d5a0ca6255473f3f256eeb32f18a9984 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1012,7 +1012,25 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1022,7 +1022,25 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.getMethodProfiler().exit();
}

View File

@ -19,7 +19,7 @@ This patch also reverts incorrect use(s) of the class by paper.
any exception thrown from it.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index fb21da40b4ceccd521393851f533f9ed9ddcd677..b4c9fed303504b6839fcbdb919f8bb7612792bbc 100644
index c8c4d4f3d5a0ca6255473f3f256eeb32f18a9984..e1a17abda657c7eb7aee7cd0763bcb48cc8b154a 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -174,9 +174,9 @@ public class ChunkProviderServer extends IChunkProvider {

View File

@ -1457,7 +1457,7 @@ index f011869880fedae4b69e505491e8bdbc5f51dfba..0d10d317cd0b60fc0866ae505c7fd71f
return this.j.d();
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index da9172303b8acf5613b283a98bf7f6f0fe859d62..8e1bd6029a5230f03616d9ff00b55ab14feced3f 100644
index f2e630598320f7f09ecdee5a9a548b20cc1b7877..74cd5d412b285469f6f77bef73e65b139179992e 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -361,6 +361,251 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Optimise chunk tick iteration
Use a dedicated list of entity ticking chunks to reduce the cost
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index b4c9fed303504b6839fcbdb919f8bb7612792bbc..288d487a6f22435f9070b830451f6005149c8262 100644
index e1a17abda657c7eb7aee7cd0763bcb48cc8b154a..8c0aed61400a89799592d3d457c1d78f0217d066 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -22,6 +22,12 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
@ -22,7 +22,7 @@ index b4c9fed303504b6839fcbdb919f8bb7612792bbc..288d487a6f22435f9070b830451f6005
public class ChunkProviderServer extends IChunkProvider {
private static final List<ChunkStatus> b = ChunkStatus.a(); static final List<ChunkStatus> getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER
@@ -972,19 +978,23 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -982,19 +988,23 @@ public class ChunkProviderServer extends IChunkProvider {
//List<PlayerChunk> list = Lists.newArrayList(this.playerChunkMap.f()); // Paper
//Collections.shuffle(list); // Paper
// Paper - moved up
@ -54,7 +54,7 @@ index b4c9fed303504b6839fcbdb919f8bb7612792bbc..288d487a6f22435f9070b830451f6005
ChunkCoordIntPair chunkcoordintpair = playerchunk.i();
if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange
@@ -1000,7 +1010,11 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1010,7 +1020,11 @@ public class ChunkProviderServer extends IChunkProvider {
}
}
}

View File

@ -12,10 +12,10 @@ completion (completion of the world gen future,
PlayerChunkMap#b(PlayerChunk, ChunkStatus)) was detected and fixed.
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8f717091e 100644
index b03865a932d341ae2fdad6c9447979fa9e95fc14..9a321c8a0a357ca1fd47d0c7fe4fe7af17204389 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -560,6 +560,7 @@ public class PlayerChunk {
@@ -564,6 +564,7 @@ public class PlayerChunk {
}
protected void a(PlayerChunkMap playerchunkmap) {
@ -23,7 +23,7 @@ index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8
ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel);
ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel);
boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET;
@@ -569,7 +570,8 @@ public class PlayerChunk {
@@ -573,7 +574,8 @@ public class PlayerChunk {
// CraftBukkit start
// ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
@ -33,7 +33,7 @@ index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8
Chunk chunk = (Chunk)either.left().orElse(null);
if (chunk != null) {
playerchunkmap.callbackExecutor.execute(() -> {
@@ -634,7 +636,8 @@ public class PlayerChunk {
@@ -638,7 +640,8 @@ public class PlayerChunk {
if (!flag2 && flag3) {
// Paper start - cache ticking ready status
int expectCreateCount = ++this.fullChunkCreateCount;
@ -43,7 +43,7 @@ index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8
if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) {
// note: Here is a very good place to add callbacks to logic waiting on this.
Chunk fullChunk = either.left().get();
@@ -665,7 +668,8 @@ public class PlayerChunk {
@@ -669,7 +672,8 @@ public class PlayerChunk {
if (!flag4 && flag5) {
// Paper start - cache ticking ready status
@ -53,7 +53,7 @@ index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8
if (either.left().isPresent()) {
// note: Here is a very good place to add callbacks to logic waiting on this.
Chunk tickingChunk = either.left().get();
@@ -705,7 +709,8 @@ public class PlayerChunk {
@@ -709,7 +713,8 @@ public class PlayerChunk {
}
// Paper start - cache ticking ready status
@ -63,7 +63,7 @@ index 12a207afc263f02ba1971777fe5c30d120ba9292..52e586a7e193b0012c9939554376f6e8
if (either.left().isPresent()) {
// note: Here is a very good place to add callbacks to logic waiting on this.
Chunk entityTickingChunk = either.left().get();
@@ -756,7 +761,8 @@ public class PlayerChunk {
@@ -760,7 +765,8 @@ public class PlayerChunk {
// CraftBukkit start
// ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins.
if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {

View File

@ -9,7 +9,7 @@ issues where teleporting players across worlds while ticking.
Also allows us to run mid tick while ticking entities.
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 8e1bd6029a5230f03616d9ff00b55ab14feced3f..6e5a3467f92c29181d26c03ecf49d598d75a4633 100644
index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc127f3871 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -61,7 +61,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -164,8 +164,8 @@ index 8e1bd6029a5230f03616d9ff00b55ab14feced3f..6e5a3467f92c29181d26c03ecf49d598
+ try { // Tuinity end
while (iterator.hasNext()) {
NavigationAbstract navigationabstract = (NavigationAbstract) iterator.next();
@@ -1951,6 +1964,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit start - fix SPIGOT-6362
@@ -1962,6 +1975,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
navigationabstract.b(blockposition);
}
}

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Prevent unload() calls removing tickets for sync loads
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 288d487a6f22435f9070b830451f6005149c8262..d4cb3850178576fe4605502ff12351b16fa98d16 100644
index 8c0aed61400a89799592d3d457c1d78f0217d066..99f618cc9fbde5bd96cd7e6a7601d0f65d2d842f 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -701,6 +701,8 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -709,6 +709,8 @@ public class ChunkProviderServer extends IChunkProvider {
Arrays.fill(this.cacheChunk, (Object) null);
}
@ -17,7 +17,7 @@ index 288d487a6f22435f9070b830451f6005149c8262..d4cb3850178576fe4605502ff12351b1
private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) {
// Paper start - add isUrgent - old sig left in place for dirty nms plugins
return getChunkFutureMainThread(i, j, chunkstatus, flag, false);
@@ -719,9 +721,12 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -727,9 +729,12 @@ public class ChunkProviderServer extends IChunkProvider {
PlayerChunk.State currentChunkState = PlayerChunk.getChunkState(playerchunk.getTicketLevel());
currentlyUnloading = (oldChunkState.isAtLeast(PlayerChunk.State.BORDER) && !currentChunkState.isAtLeast(PlayerChunk.State.BORDER));
}
@ -30,7 +30,7 @@ index 288d487a6f22435f9070b830451f6005149c8262..d4cb3850178576fe4605502ff12351b1
if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper
if (this.a(playerchunk, l)) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
@@ -732,12 +737,20 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -740,12 +745,20 @@ public class ChunkProviderServer extends IChunkProvider {
playerchunk = this.getChunk(k);
gameprofilerfiller.exit();
if (this.a(playerchunk, l)) {

View File

@ -19,10 +19,10 @@ index 7991c66a8fe7ee9725ab75fb80d1363cd7348532..68ab5ccb2fcfe1de0503c9336572f28e
private static final Map<Class<?>, String> taskNameCache = new MapMaker().weakKeys().makeMap();
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index d4cb3850178576fe4605502ff12351b16fa98d16..c1759c5e60d5e863c57a866188500b5f1e0dd63f 100644
index 99f618cc9fbde5bd96cd7e6a7601d0f65d2d842f..0e5e7a321dc7066444d92387968a7c41cb3a8470 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -807,6 +807,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -815,6 +815,7 @@ public class ChunkProviderServer extends IChunkProvider {
public boolean tickDistanceManager() { // Paper - private -> public
if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper
@ -30,7 +30,7 @@ index d4cb3850178576fe4605502ff12351b16fa98d16..c1759c5e60d5e863c57a866188500b5f
boolean flag = this.chunkMapDistance.a(this.playerChunkMap);
boolean flag1 = this.playerChunkMap.b();
@@ -816,6 +817,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -824,6 +825,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.clearCache();
return true;
}

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Range check flag dirty calls in PlayerChunk
Simply return.
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 52e586a7e193b0012c9939554376f6e8f717091e..a072208bcd92ffa9ed47757de291b82be2e71e8e 100644
index 9a321c8a0a357ca1fd47d0c7fe4fe7af17204389..48976b1f07aeb0d588d0856f18b6fd07b2d18e05 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -362,7 +362,7 @@ public class PlayerChunk {
@@ -366,7 +366,7 @@ public class PlayerChunk {
if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks
Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
@ -18,7 +18,7 @@ index 52e586a7e193b0012c9939554376f6e8f717091e..a072208bcd92ffa9ed47757de291b82b
byte b0 = (byte) SectionPosition.a(blockposition.getY());
if (b0 < 0 || b0 >= this.dirtyBlocks.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
@@ -421,7 +421,7 @@ public class PlayerChunk {
@@ -425,7 +425,7 @@ public class PlayerChunk {
this.a(world, blockposition, iblockdata);
} else {
ChunkSection chunksection = chunk.getSections()[sectionposition.getY()];

View File

@ -8,10 +8,10 @@ Sync loading the chunk at this stage would cause it to load
older data, as well as screwing our region state.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index c1759c5e60d5e863c57a866188500b5f1e0dd63f..0145f33f66f68a3cf03eae2128aaaa026ddc9951 100644
index 0e5e7a321dc7066444d92387968a7c41cb3a8470..ce0bb4d228a73d8353d67828529879e1c99682f9 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -807,6 +807,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -815,6 +815,7 @@ public class ChunkProviderServer extends IChunkProvider {
public boolean tickDistanceManager() { // Paper - private -> public
if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper

View File

@ -1,472 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 27 Aug 2020 09:40:16 -0700
Subject: [PATCH] Optimise closest entity lookup used by AI goals
Use a special entity slice for tracking entities by class as well
as counts per chunk. This should reduce the number of entities searched.
diff --git a/src/main/java/com/tuinity/tuinity/chunk/ChunkEntitiesByClass.java b/src/main/java/com/tuinity/tuinity/chunk/ChunkEntitiesByClass.java
new file mode 100644
index 0000000000000000000000000000000000000000..37428f4b9ae45175fda545e9d8b55cf8a3b8c87b
--- /dev/null
+++ b/src/main/java/com/tuinity/tuinity/chunk/ChunkEntitiesByClass.java
@@ -0,0 +1,186 @@
+package com.tuinity.tuinity.chunk;
+
+import com.destroystokyo.paper.util.maplist.EntityList;
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+import net.minecraft.server.AxisAlignedBB;
+import net.minecraft.server.Chunk;
+import net.minecraft.server.Entity;
+import net.minecraft.server.MathHelper;
+import org.spigotmc.AsyncCatcher;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+public final class ChunkEntitiesByClass {
+
+ // this class attempts to restore the original intent of nms.EntitySlice and improve upon it:
+ // fast lookups for specific entity types in a chunk. However vanilla does not track things on a
+ // chunk-wide basis, which is very important to our optimisations here: we want to eliminate chunks
+ // before searching multiple slices. We also want to maintain only lists that we need to maintain for memory purposes:
+ // so we have no choice but to lazily initialise mappings of class -> entity.
+ // Typically these are used for entity AI lookups, which means we take a heavy initial cost but ultimately win
+ // since AI lookups happen a lot.
+
+ // This optimisation is only half of the battle with entity AI, we need to be smarter about picking the closest entity.
+ // See World#getClosestEntity
+
+ // aggressively high load factors for each map here + fastutil collections: we want the smallest memory footprint
+ private final ExposedReference2IntOpenHashMap<Class<?>> chunkWideCount = new ExposedReference2IntOpenHashMap<>(4, 0.9f);
+ {
+ this.chunkWideCount.defaultReturnValue(Integer.MIN_VALUE);
+ }
+ private final Reference2ObjectOpenHashMap<Class<?>, ArrayList<Entity>>[] slices = new Reference2ObjectOpenHashMap[16];
+ private final Chunk chunk;
+
+ public ChunkEntitiesByClass(final Chunk chunk) {
+ this.chunk = chunk;
+ }
+
+ public boolean hasEntitiesMaybe(final Class<?> clazz) {
+ final int count = this.chunkWideCount.getInt(clazz);
+ return count == Integer.MIN_VALUE || count > 0;
+ }
+
+ public void addEntity(final Entity entity, final int sectionY) {
+ AsyncCatcher.catchOp("Add entity call");
+ if (this.chunkWideCount.isEmpty()) {
+ return;
+ }
+
+ final Object[] keys = this.chunkWideCount.getKey();
+ final int[] values = this.chunkWideCount.getValue();
+
+ Reference2ObjectOpenHashMap<Class<?>, ArrayList<Entity>> slice = this.slices[sectionY];
+ if (slice == null) {
+ slice = this.slices[sectionY] = new Reference2ObjectOpenHashMap<>(4, 0.9f);
+ }
+
+ for (int i = 0, len = keys.length; i < len; ++i) {
+ final Object _key = keys[i];
+ if (!(_key instanceof Class)) {
+ continue;
+ }
+ final Class<?> key = (Class<?>)_key;
+ if (key.isInstance(entity)) {
+ ++values[i];
+ slice.computeIfAbsent(key, (keyInMap) -> {
+ return new ArrayList<>();
+ }).add(entity);
+ }
+ }
+ }
+
+ public void removeEntity(final Entity entity, final int sectionY) {
+ AsyncCatcher.catchOp("Remove entity call");
+ if (this.chunkWideCount.isEmpty()) {
+ return;
+ }
+
+ final Object[] keys = this.chunkWideCount.getKey();
+ final int[] values = this.chunkWideCount.getValue();
+
+ Reference2ObjectOpenHashMap<Class<?>, ArrayList<Entity>> slice = this.slices[sectionY];
+ if (slice == null) {
+ return; // seriously brain damaged plugins
+ }
+
+ for (int i = 0, len = keys.length; i < len; ++i) {
+ final Object _key = keys[i];
+ if (!(_key instanceof Class)) {
+ continue;
+ }
+ final Class<?> key = (Class<?>)_key;
+ if (key.isInstance(entity)) {
+ --values[i];
+ final ArrayList<Entity> list = slice.get(key);
+ if (list == null) {
+ return; // seriously brain damaged plugins
+ }
+ list.remove(entity);
+ }
+ }
+ }
+
+
+ private void computeClass(final Class<?> clazz) {
+ AsyncCatcher.catchOp("Entity class compute call");
+ int totalCount = 0;
+
+ EntityList entityList = this.chunk.entities;
+ Entity[] entities = entityList.getRawData();
+ for (int i = 0, len = entityList.size(); i < len; ++i) {
+ final Entity entity = entities[i];
+
+ if (clazz.isInstance(entity)) {
+ ++totalCount;
+ Reference2ObjectOpenHashMap<Class<?>, ArrayList<Entity>> slice = this.slices[entity.chunkY];
+ if (slice == null) {
+ slice = this.slices[entity.chunkY] = new Reference2ObjectOpenHashMap<>(4, 0.9f);
+ }
+ slice.computeIfAbsent(clazz, (keyInMap) -> {
+ return new ArrayList<>();
+ }).add(entity);
+ }
+ }
+
+ this.chunkWideCount.put(clazz, totalCount);
+ }
+
+ public void lookupClass(final Class<?> clazz, final Entity entity, final AxisAlignedBB boundingBox, final Predicate<Entity> predicate, final List<Entity> into) {
+ final int count = this.chunkWideCount.getInt(clazz);
+ if (count == Integer.MIN_VALUE) {
+ this.computeClass(clazz);
+ if (this.chunkWideCount.getInt(clazz) <= 0) {
+ return;
+ }
+ } else if (count <= 0) {
+ return;
+ }
+
+ // copied from getEntities
+ int min = MathHelper.floor((boundingBox.minY - 2.0D) / 16.0D);
+ int max = MathHelper.floor((boundingBox.maxY + 2.0D) / 16.0D);
+
+ min = MathHelper.clamp(min, 0, this.slices.length - 1);
+ max = MathHelper.clamp(max, 0, this.slices.length - 1);
+
+ for (int y = min; y <= max; ++y) {
+ final Reference2ObjectOpenHashMap<Class<?>, ArrayList<Entity>> slice = this.slices[y];
+ if (slice == null) {
+ continue;
+ }
+
+ final ArrayList<Entity> entities = slice.get(clazz);
+ if (entities == null) {
+ continue;
+ }
+
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ Entity entity1 = entities.get(i);
+ if (entity1.shouldBeRemoved) continue; // Paper
+
+ if (entity1 != entity && entity1.getBoundingBox().intersects(boundingBox)) {
+ if (predicate == null || predicate.test(entity1)) {
+ into.add(entity1);
+ }
+ }
+ }
+ }
+ }
+
+ static final class ExposedReference2IntOpenHashMap<K> extends Reference2IntOpenHashMap<K> {
+
+ public ExposedReference2IntOpenHashMap(final int expected, final float loadFactor) {
+ super(expected, loadFactor);
+ }
+
+ public Object[] getKey() {
+ return this.key;
+ }
+
+ public int[] getValue() {
+ return this.value;
+ }
+ }
+}
diff --git a/src/main/java/com/tuinity/tuinity/util/CachedLists.java b/src/main/java/com/tuinity/tuinity/util/CachedLists.java
index 387eeb5d770ba9fe564c61df8cc92ac8b1569f61..21e50c75e0bffaa5cc5faf6aa81ae7428caca731 100644
--- a/src/main/java/com/tuinity/tuinity/util/CachedLists.java
+++ b/src/main/java/com/tuinity/tuinity/util/CachedLists.java
@@ -1,6 +1,7 @@
package com.tuinity.tuinity.util;
import net.minecraft.server.AxisAlignedBB;
+import net.minecraft.server.Chunk;
import net.minecraft.server.Entity;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.util.UnsafeList;
@@ -46,8 +47,28 @@ public class CachedLists {
tempGetEntitiesListInUse = false;
}
+ static final UnsafeList<Chunk> TEMP_GET_CHUNKS_LIST = new UnsafeList<>(1024);
+ static boolean tempGetChunksListInUse;
+
+ public static UnsafeList<Chunk> getTempGetChunksList() {
+ if (!Bukkit.isPrimaryThread() || tempGetChunksListInUse) {
+ return new UnsafeList<>();
+ }
+ tempGetChunksListInUse = true;
+ return TEMP_GET_CHUNKS_LIST;
+ }
+
+ public static void returnTempGetChunksList(List<Chunk> list) {
+ if (list != TEMP_GET_CHUNKS_LIST) {
+ return;
+ }
+ ((UnsafeList)list).setSize(0);
+ tempGetChunksListInUse = false;
+ }
+
public static void reset() {
TEMP_COLLISION_LIST.completeReset();
TEMP_GET_ENTITIES_LIST.completeReset();
+ TEMP_GET_CHUNKS_LIST.completeReset();
}
}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index dface62144bb230c576e9eafad1016d19d211118..cd4a36a2f0feb2df928ee5ed7f0bca6d996bad7f 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -141,6 +141,22 @@ public class Chunk implements IChunkAccess {
}
// Tuinity end - optimise hard collision handling
+ // Tuinity start - entity slices by class
+ private final com.tuinity.tuinity.chunk.ChunkEntitiesByClass entitiesByClass = new com.tuinity.tuinity.chunk.ChunkEntitiesByClass(this);
+
+ public boolean hasEntitiesMaybe(Class<?> clazz) {
+ return this.entitiesByClass.hasEntitiesMaybe(clazz);
+ }
+
+ public final void getEntitiesClass(Class<?> clazz, Entity entity, AxisAlignedBB boundingBox, Predicate<Entity> predicate, List<Entity> into) {
+ if (!org.bukkit.Bukkit.isPrimaryThread()) {
+ this.getEntities((Class)clazz, boundingBox, (List)into, (Predicate)predicate);
+ return;
+ }
+ this.entitiesByClass.lookupClass(clazz, entity, boundingBox, predicate, into);
+ }
+ // Tuinity end - entity slices by class
+
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList<Block> ticklist, TickList<FluidType> ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer<Chunk> consumer) {
this.sections = new ChunkSection[16];
this.e = Maps.newHashMap();
@@ -644,7 +660,7 @@ public class Chunk implements IChunkAccess {
entity.chunkX = this.loc.x;
entity.chunkY = k;
entity.chunkZ = this.loc.z;
- this.entities.add(entity); // Paper - per chunk entity list
+ this.entities.add(entity); this.entitiesByClass.addEntity(entity, entity.chunkY); // Paper - per chunk entity list // Tuinity - entities by class
this.entitySlices[k].add(entity); if (entity.hardCollides()) this.hardCollidingEntities[k].add(entity); // Tuinity - optimise hard colliding entities
// Paper start
if (entity instanceof EntityItem) {
@@ -683,7 +699,7 @@ public class Chunk implements IChunkAccess {
entity.entitySlice = null;
entity.inChunk = false;
}
- if (entity.hardCollides()) this.hardCollidingEntities[i].remove(entity); if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities
+ if (entity.hardCollides()) this.hardCollidingEntities[i].remove(entity); this.entitiesByClass.removeEntity(entity, i); if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities // Tuinity - entities by class
return;
}
if (entity instanceof EntityItem) {
@@ -996,6 +1012,7 @@ public class Chunk implements IChunkAccess {
}
+ public final <T extends Entity> void getEntities(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, List<T> list, @Nullable Predicate<? super T> predicate) { this.a(oclass, axisalignedbb, list, predicate); } // Tuinity - OBFHELPER
public <T extends Entity> void a(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, List<T> list, @Nullable Predicate<? super T> predicate) {
org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D);
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index c17cbadeff9cb3ea955b9db99ab71d6d7fd8c247..93f2ac996904ddefed04704e554209d047faa59f 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -214,12 +214,12 @@ public interface IEntityAccess {
}
@Nullable
- default <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ default <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition"
return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix
}
@Nullable
- default <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ default <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition"
return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix
}
diff --git a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
index 253377c6238594de1f76cafcbf8223592e4d3f6b..3ebe3d0dc4c2c6aee6ea349006a74cbe5aa8e78f 100644
--- a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
+++ b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
@@ -51,6 +51,7 @@ public class PathfinderTargetCondition {
return this;
}
+ public final boolean test(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { return this.a(entityliving, entityliving1); } // Tuinity - OBFHELPER
public boolean a(@Nullable EntityLiving entityliving, EntityLiving entityliving1) {
if (entityliving == entityliving1) {
return false;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index dccdbb1c218d9fd8acb81998bd5884dc4aba7c1c..1d87e7461d28d8a639fafcfdfa5496014e9180f6 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1186,7 +1186,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
if (chunk != null) {
- chunk.a(oclass, axisalignedbb, list, predicate);
+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class
}
}
}
@@ -1209,7 +1209,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
if (chunk != null) {
- chunk.a(oclass, axisalignedbb, list, predicate);
+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class
}
}
}
@@ -1217,6 +1217,106 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return list;
}
+ // Tuinity start
+ @Override
+ public <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb);
+ }
+
+ @Override
+ public <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb);
+ }
+
+ public final <T extends EntityLiving> T getClosestEntity(Class<? extends T> clazz,
+ PathfinderTargetCondition condition,
+ @Nullable EntityLiving source,
+ double x, double y, double z,
+ AxisAlignedBB boundingBox) {
+ org.bukkit.craftbukkit.util.UnsafeList<Entity> entities = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList();
+ try {
+ int lowerX = MCUtil.fastFloor((boundingBox.minX - 2.0D)) >> 4;
+ int upperX = MCUtil.fastFloor((boundingBox.maxX + 2.0D)) >> 4;
+ int lowerZ = MCUtil.fastFloor((boundingBox.minZ - 2.0D)) >> 4;
+ int upperZ = MCUtil.fastFloor((boundingBox.maxZ + 2.0D)) >> 4;
+
+ org.bukkit.craftbukkit.util.UnsafeList<Chunk> chunks = com.tuinity.tuinity.util.CachedLists.getTempGetChunksList();
+ try {
+ T closest = null;
+ double closestDistance = Double.MAX_VALUE;
+ ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider();
+
+ int centerX = (lowerX + upperX) >> 1;
+ int centerZ = (lowerZ + upperZ) >> 1;
+ // Copied from MCUtil.getSpiralOutChunks
+ Chunk temp;
+ if ((temp = chunkProvider.getChunkAtIfLoadedImmediately(centerX, centerZ)) != null && temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ int radius = Math.max((upperX - lowerX + 1) >> 1, (upperZ - lowerZ + 1) >> 1);
+ for (int r = 1; r <= radius; r++) {
+ int ox = -r;
+ int oz = r;
+
+ // Iterates the edge of half of the box; then negates for other half.
+ while (ox <= r && oz > -r) {
+ {
+ int cx = centerX + ox;
+ int cz = centerZ + oz;
+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ &&
+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null &&
+ temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ }
+ {
+ int cx = centerX - ox;
+ int cz = centerZ - oz;
+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ &&
+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null &&
+ temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ }
+
+ if (ox < r) {
+ ox++;
+ } else {
+ oz--;
+ }
+ }
+ }
+
+ Object[] chunkData = chunks.getRawDataArray();
+ for (int cindex = 0, clen = chunks.size(); cindex < clen; ++cindex) {
+ final Chunk chunk = (Chunk)chunkData[cindex];
+
+ chunk.getEntitiesClass(clazz, source, boundingBox, null, entities);
+
+ Object[] entityData = entities.getRawDataArray();
+ for (int eindex = 0, entities_len = entities.size(); eindex < entities_len; ++eindex) {
+ T entity = (T)entityData[eindex];
+ double distance = entity.getDistanceSquared(x, y, z);
+ // check distance first, as it's the least expensive
+ if (distance < closestDistance && condition.test(source, entity)) {
+ closest = entity;
+ closestDistance = distance;
+ }
+ }
+
+ entities.setSize(0);
+ }
+
+ return closest;
+ } finally {
+ com.tuinity.tuinity.util.CachedLists.returnTempGetChunksList(chunks);
+ }
+ } finally {
+ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(entities);
+ }
+ }
+ // Tuinity end
+
@Nullable
public abstract Entity getEntity(int i);
diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
index 50f855b931dba60754fff9c7cdf5e0e744f00fdd..7c0d90552eeb6de7dab174e2ba4acfc89a7b3db0 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
@@ -35,6 +35,13 @@ public class UnsafeList<E> extends AbstractList<E> implements List<E>, RandomAcc
iterPool[0] = new Itr();
}
+ // Tuinity start
+ @Override
+ public void sort(java.util.Comparator<? super E> c) {
+ Arrays.sort((E[])this.data, 0, size, c);
+ }
+ // Tuinity end
+
public UnsafeList(int capacity) {
this(capacity, 5);
}

View File

@ -0,0 +1,985 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 27 Aug 2020 09:40:16 -0700
Subject: [PATCH] Optimise closest entity lookup
Rewrites the entity slice storage so that entity by
class lookups look through less entities in total.
Also optimise the nearest entity by class method
used by entity AI as well.
As a sidenote, this entity slice implementation
removes the async catchers because it has been
designed to be MT-Safe for reads off of other
threads.
diff --git a/src/main/java/com/tuinity/tuinity/util/CachedLists.java b/src/main/java/com/tuinity/tuinity/util/CachedLists.java
index 387eeb5d770ba9fe564c61df8cc92ac8b1569f61..21e50c75e0bffaa5cc5faf6aa81ae7428caca731 100644
--- a/src/main/java/com/tuinity/tuinity/util/CachedLists.java
+++ b/src/main/java/com/tuinity/tuinity/util/CachedLists.java
@@ -1,6 +1,7 @@
package com.tuinity.tuinity.util;
import net.minecraft.server.AxisAlignedBB;
+import net.minecraft.server.Chunk;
import net.minecraft.server.Entity;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.util.UnsafeList;
@@ -46,8 +47,28 @@ public class CachedLists {
tempGetEntitiesListInUse = false;
}
+ static final UnsafeList<Chunk> TEMP_GET_CHUNKS_LIST = new UnsafeList<>(1024);
+ static boolean tempGetChunksListInUse;
+
+ public static UnsafeList<Chunk> getTempGetChunksList() {
+ if (!Bukkit.isPrimaryThread() || tempGetChunksListInUse) {
+ return new UnsafeList<>();
+ }
+ tempGetChunksListInUse = true;
+ return TEMP_GET_CHUNKS_LIST;
+ }
+
+ public static void returnTempGetChunksList(List<Chunk> list) {
+ if (list != TEMP_GET_CHUNKS_LIST) {
+ return;
+ }
+ ((UnsafeList)list).setSize(0);
+ tempGetChunksListInUse = false;
+ }
+
public static void reset() {
TEMP_COLLISION_LIST.completeReset();
TEMP_GET_ENTITIES_LIST.completeReset();
+ TEMP_GET_CHUNKS_LIST.completeReset();
}
}
diff --git a/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java b/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cc14620d26d63a9e8fec7735625b22411b43e98
--- /dev/null
+++ b/src/main/java/com/tuinity/tuinity/world/ChunkEntitySlices.java
@@ -0,0 +1,401 @@
+package com.tuinity.tuinity.world;
+
+import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+import net.minecraft.server.AxisAlignedBB;
+import net.minecraft.server.Entity;
+import net.minecraft.server.EntityComplexPart;
+import net.minecraft.server.EntityEnderDragon;
+import net.minecraft.server.EntityTypes;
+import net.minecraft.server.MathHelper;
+import net.minecraft.server.World;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Predicate;
+
+public final class ChunkEntitySlices {
+
+ private static final int RTREE_THRESHOLD = 20;
+
+ protected final int minSection;
+ protected final int maxSection;
+ protected final int chunkX;
+ protected final int chunkZ;
+ protected final World world;
+
+ protected final EntityCollectionBySection allEntities;
+ protected final EntityCollectionBySection hardCollidingEntities;
+ protected final Reference2ObjectOpenHashMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
+
+ public ChunkEntitySlices(final World world, final int chunkX, final int chunkZ,
+ final int minSection, final int maxSection) { // inclusive, inclusive
+ this.minSection = minSection;
+ this.maxSection = maxSection;
+ this.chunkX = chunkX;
+ this.chunkZ = chunkZ;
+ this.world = world;
+
+ this.allEntities = new EntityCollectionBySection(this);
+ this.hardCollidingEntities = new EntityCollectionBySection(this);
+ this.entitiesByClass = new Reference2ObjectOpenHashMap<>();
+ }
+
+ // synchronized is used in this class for write protection, thank you dumbass mods for doing dumb
+ // shit async.
+
+ public synchronized void addEntity(final Entity entity, final int chunkSection) {
+ final int sectionIndex = chunkSection - this.minSection;
+
+ this.allEntities.addEntity(entity, sectionIndex);
+
+ if (entity.hardCollides()) {
+ this.hardCollidingEntities.addEntity(entity, sectionIndex);
+ }
+
+ for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
+ this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
+
+ if (entry.getKey().isInstance(entity)) {
+ entry.getValue().addEntity(entity, sectionIndex);
+ }
+ }
+ }
+
+ public synchronized void removeEntity(final Entity entity, final int chunkSection) {
+ final int sectionIndex = chunkSection - this.minSection;
+
+ this.allEntities.removeEntity(entity, sectionIndex);
+
+ if (entity.hardCollides()) {
+ this.hardCollidingEntities.removeEntity(entity, sectionIndex);
+ }
+
+ for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
+ this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
+
+ if (entry.getKey().isInstance(entity)) {
+ entry.getValue().removeEntity(entity, sectionIndex);
+ }
+ }
+ }
+
+ public void getHardCollidingEntities(final Entity except, final AxisAlignedBB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
+ this.hardCollidingEntities.getEntities(except, box, into, predicate);
+ }
+
+ public void getEntities(final Entity except, final AxisAlignedBB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
+ this.allEntities.getEntitiesWithEnderDragonParts(except, box, into, predicate);
+ }
+
+ public <T extends Entity> void getEntities(final EntityTypes<?> type, final AxisAlignedBB box, final List<? super T> into,
+ final Predicate<? super T> predicate) {
+ this.allEntities.getEntities(type, box, (List)into, (Predicate)predicate);
+ }
+
+ protected EntityCollectionBySection initClass(final Class<? extends Entity> clazz) {
+ final EntityCollectionBySection ret = new EntityCollectionBySection(this);
+
+ for (int sectionIndex = 0; sectionIndex < this.allEntities.entitiesBySection.length; ++sectionIndex) {
+ final BasicEntityList<Entity> sectionEntities = this.allEntities.entitiesBySection[sectionIndex];
+ if (sectionEntities == null) {
+ continue;
+ }
+
+ final Entity[] storage = sectionEntities.storage;
+
+ for (int i = 0, len = Math.min(storage.length, sectionEntities.size()); i < len; ++i) {
+ final Entity entity = storage[i];
+
+ if (clazz.isInstance(entity)) {
+ ret.addEntity(entity, sectionIndex);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ public <T extends Entity> void getEntities(final Class<? extends T> clazz, final Entity except, final AxisAlignedBB box, final List<? super T> into,
+ final Predicate<? super T> predicate) {
+ EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
+ if (collection != null) {
+ collection.getEntities(except, box, (List)into, (Predicate)predicate);
+ } else {
+ synchronized (this) {
+ this.entitiesByClass.putIfAbsent(clazz, collection = this.initClass(clazz));
+ }
+ collection.getEntities(except, box, (List)into, (Predicate)predicate);
+ }
+ }
+
+ public synchronized void updateEntity(final Entity entity) {
+ /*// TODO
+ if (prev aabb != entity.getBoundingBox()) {
+ this.entityMap.delete(entity, prev aabb);
+ this.entityMap.insert(entity, prev aabb = entity.getBoundingBox());
+ }*/
+ }
+
+ protected static final class BasicEntityList<E extends Entity> {
+
+ protected static final Entity[] EMPTY = new Entity[0];
+ protected static final int DEFAULT_CAPACITY = 4;
+
+ protected E[] storage;
+ protected int size;
+
+ public BasicEntityList() {
+ this(0);
+ }
+
+ public BasicEntityList(final int cap) {
+ this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
+ }
+
+ public boolean isEmpty() {
+ return this.size == 0;
+ }
+
+ public int size() {
+ return this.size;
+ }
+
+ private void resize() {
+ if (this.storage == EMPTY) {
+ this.storage = (E[])new Entity[DEFAULT_CAPACITY];
+ } else {
+ this.storage = Arrays.copyOf(this.storage, this.storage.length * 2);
+ }
+ }
+
+ public void add(final E entity) {
+ final int idx = this.size++;
+ if (idx >= this.storage.length) {
+ this.resize();
+ this.storage[idx] = entity;
+ } else {
+ this.storage[idx] = entity;
+ }
+ }
+
+ public int indexOf(final E entity) {
+ final E[] storage = this.storage;
+
+ for (int i = 0, len = Math.min(this.storage.length, this.size); i < len; ++i) {
+ if (storage[i] == entity) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public boolean remove(final E entity) {
+ final int idx = this.indexOf(entity);
+ if (idx == -1) {
+ return false;
+ }
+
+ final int size = --this.size;
+ final E[] storage = this.storage;
+ if (idx != size) {
+ System.arraycopy(storage, idx + 1, storage, idx, size - idx);
+ }
+
+ storage[size] = null;
+
+ return true;
+ }
+
+ public boolean has(final E entity) {
+ return this.indexOf(entity) != -1;
+ }
+ }
+
+ protected static final class EntityCollectionBySection {
+
+ protected final ChunkEntitySlices manager;
+ protected final long[] nonEmptyBitset;
+ protected final BasicEntityList<Entity>[] entitiesBySection;
+ protected int count;
+
+ public EntityCollectionBySection(final ChunkEntitySlices manager) {
+ this.manager = manager;
+
+ final int sectionCount = manager.maxSection - manager.minSection + 1;
+
+ this.nonEmptyBitset = new long[(sectionCount + (Long.SIZE - 1)) >>> 6]; // (sectionCount + (Long.SIZE - 1)) / Long.SIZE
+ this.entitiesBySection = new BasicEntityList[sectionCount];
+ }
+
+ public void addEntity(final Entity entity, final int sectionIndex) {
+ BasicEntityList<Entity> list = this.entitiesBySection[sectionIndex];
+
+ if (list != null && list.has(entity)) {
+ return;
+ }
+
+ if (list == null) {
+ this.entitiesBySection[sectionIndex] = list = new BasicEntityList<>();
+ this.nonEmptyBitset[sectionIndex >>> 6] |= (1L << (sectionIndex & (Long.SIZE - 1)));
+ }
+
+ list.add(entity);
+ ++this.count;
+ }
+
+ public void removeEntity(final Entity entity, final int sectionIndex) {
+ final BasicEntityList<Entity> list = this.entitiesBySection[sectionIndex];
+
+ if (list == null || !list.remove(entity)) {
+ return;
+ }
+
+ --this.count;
+
+ if (list.isEmpty()) {
+ this.entitiesBySection[sectionIndex] = null;
+ this.nonEmptyBitset[sectionIndex >>> 6] ^= (1L << (sectionIndex & (Long.SIZE - 1)));
+ }
+ }
+
+ public void getEntities(final Entity except, final AxisAlignedBB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
+ if (this.count == 0) {
+ return;
+ }
+
+ final int minSection = this.manager.minSection;
+ final int maxSection = this.manager.maxSection;
+
+ final int min = MathHelper.clamp(MathHelper.floor(box.minY - 2.0) >> 4, minSection, maxSection);
+ final int max = MathHelper.clamp(MathHelper.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
+
+ // TODO use the bitset
+
+ final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
+
+ for (int section = min; section <= max; ++section) {
+ final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
+
+ if (list == null) {
+ continue;
+ }
+
+ final Entity[] storage = list.storage;
+
+ for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
+ final Entity entity = storage[i];
+
+ if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
+ continue;
+ }
+
+ if (predicate != null && !predicate.test(entity)) {
+ continue;
+ }
+
+ into.add(entity);
+ }
+ }
+ }
+
+ public void getEntitiesWithEnderDragonParts(final Entity except, final AxisAlignedBB box, final List<Entity> into,
+ final Predicate<? super Entity> predicate) {
+ if (this.count == 0) {
+ return;
+ }
+
+ final int minSection = this.manager.minSection;
+ final int maxSection = this.manager.maxSection;
+
+ final int min = MathHelper.clamp(MathHelper.floor(box.minY - 2.0) >> 4, minSection, maxSection);
+ final int max = MathHelper.clamp(MathHelper.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
+
+ // TODO use the bitset
+
+ final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
+
+ for (int section = min; section <= max; ++section) {
+ final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
+
+ if (list == null) {
+ continue;
+ }
+
+ final Entity[] storage = list.storage;
+
+ for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
+ final Entity entity = storage[i];
+
+ if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
+ continue;
+ }
+
+ if (predicate != null && !predicate.test(entity)) {
+ continue;
+ }
+
+ into.add(entity);
+
+ if (entity instanceof EntityEnderDragon) {
+ for (final EntityComplexPart part : ((EntityEnderDragon)entity).children) {
+ if (part == except || !part.getBoundingBox().intersects(box)) {
+ continue;
+ }
+
+ if (predicate != null && !predicate.test(part)) {
+ continue;
+ }
+
+ into.add(part);
+ }
+ }
+ }
+ }
+ }
+
+ public <T extends Entity> void getEntities(final EntityTypes<?> type, final AxisAlignedBB box, final List<? super T> into,
+ final Predicate<? super T> predicate) {
+ if (this.count == 0) {
+ return;
+ }
+
+ final int minSection = this.manager.minSection;
+ final int maxSection = this.manager.maxSection;
+
+ final int min = MathHelper.clamp(MathHelper.floor(box.minY - 2.0) >> 4, minSection, maxSection);
+ final int max = MathHelper.clamp(MathHelper.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
+
+ // TODO use the bitset
+
+ final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
+
+ for (int section = min; section <= max; ++section) {
+ final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
+
+ if (list == null) {
+ continue;
+ }
+
+ final Entity[] storage = list.storage;
+
+ for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
+ final Entity entity = storage[i];
+
+ if (entity == null || (type != null && entity.getEntityType() != type) || !entity.getBoundingBox().intersects(box)) {
+ continue;
+ }
+
+ if (predicate != null && !predicate.test((T)entity)) {
+ continue;
+ }
+
+ into.add((T)entity);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java b/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..000ab23a48186d6b910c62e6922af3b85c198fca
--- /dev/null
+++ b/src/main/java/com/tuinity/tuinity/world/EntitySliceManager.java
@@ -0,0 +1,115 @@
+package com.tuinity.tuinity.world;
+
+import com.tuinity.tuinity.util.CoordinateUtils;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import net.minecraft.server.WorldServer;
+import java.util.concurrent.locks.StampedLock;
+
+public final class EntitySliceManager {
+
+ protected static final int REGION_SHIFT = 5;
+ protected static final int REGION_MASK = (1 << REGION_SHIFT) - 1;
+ protected static final int REGION_SIZE = 1 << REGION_SHIFT;
+
+ public final WorldServer world;
+
+ private final StampedLock stateLock = new StampedLock();
+ protected final Long2ObjectOpenHashMap<ChunkSlicesRegion> regions = new Long2ObjectOpenHashMap<>(32, 0.7f);
+
+ public EntitySliceManager(final WorldServer world) {
+ this.world = world;
+ }
+
+ public ChunkSlicesRegion getRegion(final int regionX, final int regionZ) {
+ final long key = CoordinateUtils.getChunkKey(regionX, regionZ);
+ final long attempt = this.stateLock.tryOptimisticRead();
+ if (attempt != 0L) {
+ try {
+ final ChunkSlicesRegion ret = this.regions.get(key);
+
+ if (this.stateLock.validate(attempt)) {
+ return ret;
+ }
+ } catch (final Error error) {
+ throw error;
+ } catch (final Throwable thr) {
+ // ignore
+ }
+ }
+
+ this.stateLock.readLock();
+ try {
+ return this.regions.get(key);
+ } finally {
+ this.stateLock.tryUnlockRead();
+ }
+ }
+
+ public synchronized void removeChunk(final int chunkX, final int chunkZ) {
+ final long key = CoordinateUtils.getChunkKey(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
+ final int relIndex = (chunkX & REGION_MASK) | ((chunkZ & REGION_MASK) << REGION_SHIFT);
+
+ final ChunkSlicesRegion region = this.regions.get(key);
+ final int remaining = region.remove(relIndex);
+
+ if (remaining == 0) {
+ this.stateLock.writeLock();
+ try {
+ this.regions.remove(key);
+ } finally {
+ this.stateLock.tryUnlockWrite();
+ }
+ }
+ }
+
+ public synchronized void addChunk(final int chunkX, final int chunkZ, final ChunkEntitySlices slices) {
+ final long key = CoordinateUtils.getChunkKey(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
+ final int relIndex = (chunkX & REGION_MASK) | ((chunkZ & REGION_MASK) << REGION_SHIFT);
+
+ ChunkSlicesRegion region = this.regions.get(key);
+ if (region != null) {
+ region.add(relIndex, slices);
+ } else {
+ region = new ChunkSlicesRegion();
+ region.add(relIndex, slices);
+ this.stateLock.writeLock();
+ try {
+ this.regions.put(key, region);
+ } finally {
+ this.stateLock.tryUnlockWrite();
+ }
+ }
+ }
+
+ public static final class ChunkSlicesRegion {
+
+ protected final ChunkEntitySlices[] slices = new ChunkEntitySlices[REGION_SIZE * REGION_SIZE];
+ protected int sliceCount;
+
+ public ChunkEntitySlices get(final int index) {
+ return this.slices[index];
+ }
+
+ public int remove(final int index) {
+ final ChunkEntitySlices slices = this.slices[index];
+ if (slices == null) {
+ throw new IllegalStateException();
+ }
+
+ this.slices[index] = null;
+
+ return --this.sliceCount;
+ }
+
+ public void add(final int index, final ChunkEntitySlices slices) {
+ final ChunkEntitySlices curr = this.slices[index];
+ if (curr != null) {
+ throw new IllegalStateException();
+ }
+
+ this.slices[index] = slices;
+
+ ++this.sliceCount;
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index dface62144bb230c576e9eafad1016d19d211118..3f6dbba68fe7331c97c4e0fe3c8ada365970577a 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -92,54 +92,24 @@ public class Chunk implements IChunkAccess {
// Paper end
// Tuinity start - optimise hard collision handling
- final com.destroystokyo.paper.util.maplist.EntityList[] hardCollidingEntities = new com.destroystokyo.paper.util.maplist.EntityList[16];
-
- {
- for (int i = 0, len = this.hardCollidingEntities.length; i < len; ++i) {
- this.hardCollidingEntities[i] = new com.destroystokyo.paper.util.maplist.EntityList();
- }
- }
+ // Tuinity - optimised entity slices
public final void getHardCollidingEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List<Entity> into, Predicate<Entity> predicate) {
- // copied from getEntities
- int min = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D);
- int max = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D);
-
- min = MathHelper.clamp(min, 0, this.hardCollidingEntities.length - 1);
- max = MathHelper.clamp(max, 0, this.hardCollidingEntities.length - 1);
-
- for (int k = min; k <= max; ++k) {
- com.destroystokyo.paper.util.maplist.EntityList entityList = this.hardCollidingEntities[k];
- Entity[] entities = entityList.getRawData();
-
- for (int i = 0, len = entityList.size(); i < len; ++i) {
- Entity entity1 = entities[i];
- if (entity1.shouldBeRemoved) continue; // Paper
-
- if (entity1 != entity && entity1.getBoundingBox().intersects(axisalignedbb)) {
- if (predicate == null || predicate.test(entity1)) {
- into.add(entity1);
- }
-
- if (!(entity1 instanceof EntityEnderDragon)) {
- continue;
- }
+ this.entitySlicesManager.getHardCollidingEntities(entity, axisalignedbb, into, predicate); // Tuinity
+ }
+ // Tuinity end - optimise hard collision handling
- EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon)entity1).children;
- int l = aentitycomplexpart.length;
+ // Tuinity start - optimised entity slices
+ protected final com.tuinity.tuinity.world.ChunkEntitySlices entitySlicesManager;
- for (int i1 = 0; i1 < l; ++i1) {
- EntityComplexPart entitycomplexpart = aentitycomplexpart[i1];
+ public final boolean hasEntitiesMaybe(Class<?> clazz) { // Tuinity start
+ return true; // Tuinity end
+ }
- if (entitycomplexpart != entity && entitycomplexpart.getBoundingBox().intersects(axisalignedbb) && (predicate == null || predicate.test(entitycomplexpart))) {
- into.add(entitycomplexpart);
- }
- }
- }
- }
- }
+ public final void getEntitiesClass(Class<?> clazz, Entity entity, AxisAlignedBB boundingBox, Predicate<Entity> predicate, List<Entity> into) {
+ this.entitySlicesManager.getEntities((Class)clazz, entity, boundingBox, (List)into, (Predicate)predicate); // Tuinity
}
- // Tuinity end - optimise hard collision handling
+ // Tuinity end - optimised entity slices
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList<Block> ticklist, TickList<FluidType> ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer<Chunk> consumer) {
this.sections = new ChunkSection[16];
@@ -184,6 +154,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
}
public org.bukkit.Chunk bukkitChunk;
@@ -644,8 +615,9 @@ public class Chunk implements IChunkAccess {
entity.chunkX = this.loc.x;
entity.chunkY = k;
entity.chunkZ = this.loc.z;
- this.entities.add(entity); // Paper - per chunk entity list
- this.entitySlices[k].add(entity); if (entity.hardCollides()) this.hardCollidingEntities[k].add(entity); // Tuinity - optimise hard colliding entities
+ this.entities.add(entity); // Tuinity
+ this.entitySlices[k].add(entity); // Tuinity
+ this.entitySlicesManager.addEntity(entity, k); // Tuinity
// Paper start
if (entity instanceof EntityItem) {
itemCounts[k]++;
@@ -683,7 +655,8 @@ public class Chunk implements IChunkAccess {
entity.entitySlice = null;
entity.inChunk = false;
}
- if (entity.hardCollides()) this.hardCollidingEntities[i].remove(entity); if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities
+ this.entitySlicesManager.removeEntity(entity, i); // Tuinity
+ if (!this.entitySlices[i].remove(entity)) { // Tuinity - optimise hard colliding entities // Tuinity - entities by class // Tuinity
return;
}
if (entity instanceof EntityItem) {
@@ -926,116 +899,18 @@ public class Chunk implements IChunkAccess {
}
public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List<Entity> list, @Nullable Predicate<? super Entity> predicate) {
- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D);
- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D);
-
- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1);
- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1);
-
- for (int k = i; k <= j; ++k) {
- List<Entity> entityslice = this.entitySlices[k]; // Spigot
- List<Entity> list1 = entityslice; // Spigot
- int l = list1.size();
-
- for (int i1 = 0; i1 < l; ++i1) {
- Entity entity1 = (Entity) list1.get(i1);
- if (entity1.shouldBeRemoved) continue; // Paper
-
- if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) {
- if (predicate == null || predicate.test(entity1)) {
- list.add(entity1);
- }
-
- if (entity1 instanceof EntityEnderDragon) {
- EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity1).eJ();
- int j1 = aentitycomplexpart.length;
-
- for (int k1 = 0; k1 < j1; ++k1) {
- EntityComplexPart entitycomplexpart = aentitycomplexpart[k1];
-
- if (entitycomplexpart != entity && entitycomplexpart.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(entitycomplexpart))) {
- list.add(entitycomplexpart);
- }
- }
- }
- }
- }
- }
+ this.entitySlicesManager.getEntities(entity, axisalignedbb, list, predicate); // Tuinity - optimised entity slices
}
public <T extends Entity> void a(@Nullable EntityTypes<?> entitytypes, AxisAlignedBB axisalignedbb, List<? super T> list, Predicate<? super T> predicate) {
- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D);
- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D);
-
- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1);
- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1);
-
- for (int k = i; k <= j; ++k) {
- Iterator iterator = this.entitySlices[k].iterator(); // Spigot
-
- // Paper start - Don't search for inventories if we have none, and that is all we want
- /*
- * We check if they want inventories by seeing if it is the static `IEntitySelector.d`
- *
- * Make sure the inventory selector stays in sync.
- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()`
- */
- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue;
- while (iterator.hasNext()) {
- T entity = (T) iterator.next(); // CraftBukkit - decompile error
- if (entity.shouldBeRemoved) continue; // Paper
-
- if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) {
- list.add(entity);
- }
- }
- }
+ this.entitySlicesManager.getEntities(entitytypes, axisalignedbb, (List)list, (Predicate)predicate); // Tuinity - optimised entity slices
}
+ public final <T extends Entity> void getEntities(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, List<T> list, @Nullable Predicate<? super T> predicate) { this.a(oclass, axisalignedbb, list, predicate); } // Tuinity - OBFHELPER
public <T extends Entity> void a(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, List<T> list, @Nullable Predicate<? super T> predicate) {
- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
- int i = MathHelper.floor((axisalignedbb.minY - 2.0D) / 16.0D);
- int j = MathHelper.floor((axisalignedbb.maxY + 2.0D) / 16.0D);
-
- i = MathHelper.clamp(i, 0, this.entitySlices.length - 1);
- j = MathHelper.clamp(j, 0, this.entitySlices.length - 1);
-
- // Paper start
- int[] counts;
- if (EntityItem.class.isAssignableFrom(oclass)) {
- counts = itemCounts;
- } else if (IInventory.class.isAssignableFrom(oclass)) {
- counts = inventoryEntityCounts;
- } else {
- counts = null;
- }
- // Paper end
- for (int k = i; k <= j; ++k) {
- if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for
- Iterator iterator = this.entitySlices[k].iterator(); // Spigot
-
- // Paper start - Don't search for inventories if we have none, and that is all we want
- /*
- * We check if they want inventories by seeing if it is the static `IEntitySelector.d`
- *
- * Make sure the inventory selector stays in sync.
- * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()`
- */
- if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue;
- // Paper end
- while (iterator.hasNext()) {
- T t0 = (T) iterator.next(); // CraftBukkit - decompile error
- if (t0.shouldBeRemoved) continue; // Paper
-
- if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check
- list.add(t0);
- }
- }
- }
+ this.entitySlicesManager.getEntities(oclass, null, axisalignedbb, list, predicate); // Tuinity - optimised entity slices
}
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index c17cbadeff9cb3ea955b9db99ab71d6d7fd8c247..93f2ac996904ddefed04704e554209d047faa59f 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -214,12 +214,12 @@ public interface IEntityAccess {
}
@Nullable
- default <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ default <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition"
return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix
}
@Nullable
- default <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ default <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get closest entity by class that matches path finder target condition"
return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix
}
diff --git a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
index 253377c6238594de1f76cafcbf8223592e4d3f6b..3ebe3d0dc4c2c6aee6ea349006a74cbe5aa8e78f 100644
--- a/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
+++ b/src/main/java/net/minecraft/server/PathfinderTargetCondition.java
@@ -51,6 +51,7 @@ public class PathfinderTargetCondition {
return this;
}
+ public final boolean test(@Nullable EntityLiving entityliving, EntityLiving entityliving1) { return this.a(entityliving, entityliving1); } // Tuinity - OBFHELPER
public boolean a(@Nullable EntityLiving entityliving, EntityLiving entityliving1) {
if (entityliving == entityliving1) {
return false;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index dccdbb1c218d9fd8acb81998bd5884dc4aba7c1c..1d87e7461d28d8a639fafcfdfa5496014e9180f6 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1186,7 +1186,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
if (chunk != null) {
- chunk.a(oclass, axisalignedbb, list, predicate);
+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class
}
}
}
@@ -1209,7 +1209,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
if (chunk != null) {
- chunk.a(oclass, axisalignedbb, list, predicate);
+ chunk.getEntitiesClass(oclass, null, axisalignedbb, (Predicate)predicate, (List)list); // Tuinity - optimise lookup by entity class
}
}
}
@@ -1217,6 +1217,106 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return list;
}
+ // Tuinity start
+ @Override
+ public <T extends EntityLiving> T b(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb);
+ }
+
+ @Override
+ public <T extends EntityLiving> T a(Class<? extends T> oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) {
+ return this.getClosestEntity(oclass, pathfindertargetcondition, entityliving, d0, d1, d2, axisalignedbb);
+ }
+
+ public final <T extends EntityLiving> T getClosestEntity(Class<? extends T> clazz,
+ PathfinderTargetCondition condition,
+ @Nullable EntityLiving source,
+ double x, double y, double z,
+ AxisAlignedBB boundingBox) {
+ org.bukkit.craftbukkit.util.UnsafeList<Entity> entities = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList();
+ try {
+ int lowerX = MCUtil.fastFloor((boundingBox.minX - 2.0D)) >> 4;
+ int upperX = MCUtil.fastFloor((boundingBox.maxX + 2.0D)) >> 4;
+ int lowerZ = MCUtil.fastFloor((boundingBox.minZ - 2.0D)) >> 4;
+ int upperZ = MCUtil.fastFloor((boundingBox.maxZ + 2.0D)) >> 4;
+
+ org.bukkit.craftbukkit.util.UnsafeList<Chunk> chunks = com.tuinity.tuinity.util.CachedLists.getTempGetChunksList();
+ try {
+ T closest = null;
+ double closestDistance = Double.MAX_VALUE;
+ ChunkProviderServer chunkProvider = ((WorldServer)this).getChunkProvider();
+
+ int centerX = (lowerX + upperX) >> 1;
+ int centerZ = (lowerZ + upperZ) >> 1;
+ // Copied from MCUtil.getSpiralOutChunks
+ Chunk temp;
+ if ((temp = chunkProvider.getChunkAtIfLoadedImmediately(centerX, centerZ)) != null && temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ int radius = Math.max((upperX - lowerX + 1) >> 1, (upperZ - lowerZ + 1) >> 1);
+ for (int r = 1; r <= radius; r++) {
+ int ox = -r;
+ int oz = r;
+
+ // Iterates the edge of half of the box; then negates for other half.
+ while (ox <= r && oz > -r) {
+ {
+ int cx = centerX + ox;
+ int cz = centerZ + oz;
+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ &&
+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null &&
+ temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ }
+ {
+ int cx = centerX - ox;
+ int cz = centerZ - oz;
+ if (cx >= lowerX && cx <= upperX && cz >= lowerZ && cz <= upperZ &&
+ (temp = chunkProvider.getChunkAtIfLoadedImmediately(cx, cz)) != null &&
+ temp.hasEntitiesMaybe(clazz)) {
+ chunks.add(temp);
+ }
+ }
+
+ if (ox < r) {
+ ox++;
+ } else {
+ oz--;
+ }
+ }
+ }
+
+ Object[] chunkData = chunks.getRawDataArray();
+ for (int cindex = 0, clen = chunks.size(); cindex < clen; ++cindex) {
+ final Chunk chunk = (Chunk)chunkData[cindex];
+
+ chunk.getEntitiesClass(clazz, source, boundingBox, null, entities);
+
+ Object[] entityData = entities.getRawDataArray();
+ for (int eindex = 0, entities_len = entities.size(); eindex < entities_len; ++eindex) {
+ T entity = (T)entityData[eindex];
+ double distance = entity.getDistanceSquared(x, y, z);
+ // check distance first, as it's the least expensive
+ if (distance < closestDistance && condition.test(source, entity)) {
+ closest = entity;
+ closestDistance = distance;
+ }
+ }
+
+ entities.setSize(0);
+ }
+
+ return closest;
+ } finally {
+ com.tuinity.tuinity.util.CachedLists.returnTempGetChunksList(chunks);
+ }
+ } finally {
+ com.tuinity.tuinity.util.CachedLists.returnTempGetEntitiesList(entities);
+ }
+ }
+ // Tuinity end
+
@Nullable
public abstract Entity getEntity(int i);
diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
index 50f855b931dba60754fff9c7cdf5e0e744f00fdd..7c0d90552eeb6de7dab174e2ba4acfc89a7b3db0 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java
@@ -35,6 +35,13 @@ public class UnsafeList<E> extends AbstractList<E> implements List<E>, RandomAcc
iterPool[0] = new Itr();
}
+ // Tuinity start
+ @Override
+ public void sort(java.util.Comparator<? super E> c) {
+ Arrays.sort((E[])this.data, 0, size, c);
+ }
+ // Tuinity end
+
public UnsafeList(int capacity) {
this(capacity, 5);
}

View File

@ -1,273 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 27 Aug 2020 16:22:52 -0700
Subject: [PATCH] Optimise EntityInsentient#checkDespawn
Use a distance map to map out close players.
Note that it's important that we cache the distance map value per chunk
since the penalty of a map lookup could outweigh the benefits of
searching less players (as it basically did in the outside range patch).
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index cd4a36a2f0feb2df928ee5ed7f0bca6d996bad7f..9ea915101379913cf36b123088af3dfa9833c4ff 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -157,6 +157,85 @@ public class Chunk implements IChunkAccess {
}
// Tuinity end - entity slices by class
+ // Tuinity start - optimise checkDespawn
+ private boolean playerGeneralAreaCacheSet;
+ private com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> playerGeneralAreaCache;
+
+ void updateGeneralAreaCache() {
+ this.updateGeneralAreaCache(((WorldServer)this.world).getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(this.coordinateKey));
+ }
+
+ void updateGeneralAreaCache(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> value) {
+ this.playerGeneralAreaCacheSet = true;
+ this.playerGeneralAreaCache = value;
+ }
+
+ public EntityPlayer findNearestPlayer(Entity to, Predicate<Entity> predicate) {
+ if (!this.playerGeneralAreaCacheSet) {
+ this.updateGeneralAreaCache();
+ }
+
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby = this.playerGeneralAreaCache;
+
+ if (nearby == null) {
+ return null;
+ }
+
+ Object[] backingSet = nearby.getBackingSet();
+ double closestDistance = Double.MAX_VALUE;
+ EntityPlayer closest = null;
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ double distance = to.getDistanceSquared(player.locX(), player.locY(), player.locZ());
+ if (distance < closestDistance && predicate.test(player)) {
+ closest = player;
+ closestDistance = distance;
+ }
+ }
+
+ return closest;
+ }
+
+ public void getNearestPlayers(Entity source, Predicate<Entity> predicate, double range, List<EntityPlayer> ret) {
+ if (!this.playerGeneralAreaCacheSet) {
+ this.updateGeneralAreaCache();
+ }
+
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby = this.playerGeneralAreaCache;
+
+ if (nearby == null) {
+ return;
+ }
+
+ double rangeSquared = range * range;
+
+ Object[] backingSet = nearby.getBackingSet();
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ if (range >= 0.0) {
+ double distanceSquared = player.getDistanceSquared(source.locX(), source.locY(), source.locZ());
+ if (distanceSquared > rangeSquared) {
+ continue;
+ }
+ }
+
+ if (predicate == null || predicate.test(player)) {
+ ret.add(player);
+ }
+ }
+ }
+ // Tuinity end - optimise checkDespawn
+
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList<Block> ticklist, TickList<FluidType> ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer<Chunk> consumer) {
this.sections = new ChunkSection[16];
this.e = Maps.newHashMap();
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index a88521745f9f9b6935a61db52db915ea483af227..8a5e2806e68e5f4431fd9563fae780861e87632f 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -711,7 +711,13 @@ public abstract class EntityInsentient extends EntityLiving {
if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) {
this.die();
} else if (!this.isPersistent() && !this.isSpecialPersistence()) {
- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper
+ // Tuinity start - optimise checkDespawn
+ Chunk chunk = this.getCurrentChunk();
+ EntityHuman entityhuman = chunk == null || this.world.paperConfig.hardDespawnDistance >= (31 * 16 * 31 * 16) ? this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning) : chunk.findNearestPlayer(this, IEntitySelector.affectsSpawning); // Paper
+ if (entityhuman == null) {
+ entityhuman = ((WorldServer)this.world).playersAffectingSpawning.isEmpty() ? null : ((WorldServer)this.world).playersAffectingSpawning.get(0);
+ }
+ // Tuinity end - optimise checkDespawn
if (entityhuman != null) {
double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index a072208bcd92ffa9ed47757de291b82be2e71e8e..8b4ab23563a9a0c047267143dc3c6c5545d6c125 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -56,6 +56,12 @@ public class PlayerChunk {
long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location);
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
+ // Tuinity start - optimise checkDespawn
+ Chunk chunk = this.getFullChunkIfCached();
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache();
+ }
+ // Tuinity end - optimise checkDespawn
}
// Paper end - optimise isOutsideOfRange
// Paper start - optimize chunk status progression without jumping through thread pool
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 83f070229098ad31b8ae65ffcebe52886ef2884d..f4d5ff1d0f1ad34032aaab96e1077f4be43d4bf3 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -195,6 +195,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap;
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerGeneralAreaMap;
+ // Tuinity end - optimise checkDespawn
void addPlayerToDistanceMaps(EntityPlayer player) {
com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update distance maps off of the main thread"); // Tuinity
@@ -225,6 +228,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured
player.needsChunkCenterUpdate = false;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.add(player, chunkX, chunkZ, 33);
+ // Tuinity end - optimise checkDespawn
}
void removePlayerFromDistanceMaps(EntityPlayer player) {
@@ -243,6 +249,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceTickMap.remove(player);
this.playerViewDistanceNoTickMap.remove(player);
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.remove(player);
+ // Tuinity end - optimise checkDespawn
}
void updateMaps(EntityPlayer player) {
@@ -274,6 +283,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured
player.needsChunkCenterUpdate = false;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.update(player, chunkX, chunkZ, 33);
+ // Tuinity end - optimise checkDespawn
}
// Paper end
@@ -462,6 +474,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Tuinity start
this.dataRegionManager = new com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<>(this.world, RegionData.class, 2, (1.0 / 3.0), "Data");
// Tuinity end
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfCachedImmediately(rangeX, rangeZ);
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache(newState);
+ }
+ },
+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfCachedImmediately(rangeX, rangeZ);
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache(newState);
+ }
+ });
+ // Tuinity end - optimise checkDespawn
}
// Paper start - Chunk Prioritization
public void queueHolderUpdate(PlayerChunk playerchunk) {
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 1d87e7461d28d8a639fafcfdfa5496014e9180f6..93c0c3376c3cb2fe416c8ae3e740ffda5f985b78 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -123,6 +123,34 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return typeKey;
}
+ // Tuinity start - optimise checkDespawn
+ public final List<EntityPlayer> getNearbyPlayers(Entity source, double maxRange, Predicate<Entity> predicate) {
+ Chunk chunk = source.getCurrentChunk();
+ if (chunk == null || maxRange < 0.0 || maxRange > 31.0*16.0) {
+ return this.getNearbyPlayersSlow(source, maxRange, predicate);
+ }
+
+ List<EntityPlayer> ret = new java.util.ArrayList<>();
+ chunk.getNearestPlayers(source, predicate, maxRange, ret);
+ return ret;
+ }
+
+ private List<EntityPlayer> getNearbyPlayersSlow(Entity source, double maxRange, Predicate<Entity> predicate) {
+ List<EntityPlayer> ret = new java.util.ArrayList<>();
+ double maxRangeSquared = maxRange * maxRange;
+
+ for (EntityHuman player : this.getPlayers()) {
+ if ((maxRange < 0.0 || player.getDistanceSquared(source.locX(), source.locY(), source.locZ()) < maxRangeSquared)) {
+ if (predicate == null || predicate.test(player)) {
+ ret.add((EntityPlayer)player);
+ }
+ }
+ }
+
+ return ret;
+ }
+ // Tuinity end - optimise checkDespawn
+
protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, final DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 6e5a3467f92c29181d26c03ecf49d598d75a4633..b1b63a11a6585971685b9ace1b6d91643a36aa95 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -301,6 +301,10 @@ public class WorldServer extends World implements GeneratorAccessSeed {
long lastMidTickExecuteFailure;
// Tuinity end - execute chunk tasks mid tick
+ // Tuinity start - optimise checkDespawn
+ final List<EntityPlayer> playersAffectingSpawning = new java.util.ArrayList<>();
+ // Tuinity end - optimise checkDespawn
+
// Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor
@@ -659,6 +663,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void doTick(BooleanSupplier booleansupplier) {
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
+ // Tuinity start - optimise checkDespawn
+ this.playersAffectingSpawning.clear();
+ for (EntityPlayer player : this.getPlayers()) {
+ if (IEntitySelector.affectsSpawning.test(player)) {
+ this.playersAffectingSpawning.add(player);
+ }
+ }
+ // Tuinity end - optimise checkDespawn
this.ticking = true;
gameprofilerfiller.enter("world border");

View File

@ -0,0 +1,476 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 27 Aug 2020 16:22:52 -0700
Subject: [PATCH] Optimise nearby player lookups
Use a distance map to map out close players.
Note that it's important that we cache the distance map value per chunk
since the penalty of a map lookup could outweigh the benefits of
searching less players (as it basically did in the outside range patch).
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 3f6dbba68fe7331c97c4e0fe3c8ada365970577a..936c392c9faa178b5645ea79b0130e0d3e3e1368 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -111,6 +111,92 @@ public class Chunk implements IChunkAccess {
}
// Tuinity end - optimised entity slices
+ // Tuinity start - optimise checkDespawn
+ private boolean playerGeneralAreaCacheSet;
+ private com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> playerGeneralAreaCache;
+
+ public com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> getPlayerGeneralAreaCache() {
+ if (!this.playerGeneralAreaCacheSet) {
+ this.updateGeneralAreaCache();
+ }
+ return this.playerGeneralAreaCache;
+ }
+
+ void updateGeneralAreaCache() {
+ this.updateGeneralAreaCache(((WorldServer)this.world).getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(this.coordinateKey));
+ }
+
+ void updateGeneralAreaCache(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> value) {
+ this.playerGeneralAreaCacheSet = true;
+ this.playerGeneralAreaCache = value;
+ }
+
+ public EntityPlayer findNearestPlayer(double sourceX, double sourceY, double sourceZ, double maxRange, Predicate<Entity> predicate) {
+ if (!this.playerGeneralAreaCacheSet) {
+ this.updateGeneralAreaCache();
+ }
+
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby = this.playerGeneralAreaCache;
+
+ if (nearby == null) {
+ return null;
+ }
+
+ Object[] backingSet = nearby.getBackingSet();
+ double closestDistance = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange;
+ EntityPlayer closest = null;
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ double distance = player.getDistanceSquared(sourceX, sourceY, sourceZ);
+ if (distance < closestDistance && predicate.test(player)) {
+ closest = player;
+ closestDistance = distance;
+ }
+ }
+
+ return closest;
+ }
+
+ public void getNearestPlayers(double sourceX, double sourceY, double sourceZ, Predicate<Entity> predicate, double range, List<EntityPlayer> ret) {
+ if (!this.playerGeneralAreaCacheSet) {
+ this.updateGeneralAreaCache();
+ }
+
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby = this.playerGeneralAreaCache;
+
+ if (nearby == null) {
+ return;
+ }
+
+ double rangeSquared = range * range;
+
+ Object[] backingSet = nearby.getBackingSet();
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ if (range >= 0.0) {
+ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ);
+ if (distanceSquared > rangeSquared) {
+ continue;
+ }
+ }
+
+ if (predicate == null || predicate.test(player)) {
+ ret.add(player);
+ }
+ }
+ }
+ // Tuinity end - optimise checkDespawn
+
public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList<Block> ticklist, TickList<FluidType> ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer<Chunk> consumer) {
this.sections = new ChunkSection[16];
this.e = Maps.newHashMap();
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
index a88521745f9f9b6935a61db52db915ea483af227..a47217c020d2c2a3caddafa0549dc827373798dd 100644
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
@@ -711,7 +711,13 @@ public abstract class EntityInsentient extends EntityLiving {
if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) {
this.die();
} else if (!this.isPersistent() && !this.isSpecialPersistence()) {
- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper
+ // Tuinity start - optimise checkDespawn
+ Chunk chunk = this.getCurrentChunk();
+ EntityHuman entityhuman = chunk == null || this.world.paperConfig.hardDespawnDistance >= (PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE_SQUARED) ? this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning) : chunk.findNearestPlayer(this.locX(), this.locY(), this.locZ(), -1.0, IEntitySelector.affectsSpawning); // Paper
+ if (entityhuman == null) {
+ entityhuman = ((WorldServer)this.world).playersAffectingSpawning.isEmpty() ? null : ((WorldServer)this.world).playersAffectingSpawning.get(0);
+ }
+ // Tuinity end - optimise checkDespawn
if (entityhuman != null) {
double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index 93f2ac996904ddefed04704e554209d047faa59f..ad286848ddb7803640ef7eeea46b58473dd1d0c4 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -98,7 +98,7 @@ public interface IEntityAccess {
default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate<Entity> predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper
@Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate<Entity> predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER
- @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate<Entity> predicate) { // Paper
+ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate<Entity> predicate) { // Paper // Tuinity - diff on change, override in World - this should be "get closest player that matches predicate"
double d4 = -1.0D;
EntityHuman entityhuman = null;
Iterator iterator = this.getPlayers().iterator();
@@ -199,17 +199,17 @@ public interface IEntityAccess {
}
@Nullable
- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) {
+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition"
return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ());
}
@Nullable
- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) {
+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition"
return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, entityliving, d0, d1, d2);
}
@Nullable
- default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) {
+ default EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) { // Tuinity - diff on change, override in World - this should be "get closest player that matches path finder target condition"
return (EntityHuman) this.a(this.getPlayers(), pathfindertargetcondition, (EntityLiving) null, d0, d1, d2);
}
@@ -245,7 +245,7 @@ public interface IEntityAccess {
return t0;
}
- default List<EntityHuman> a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) {
+ default List<EntityHuman> a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { // Tuinity - diff on change, override in World - this should be "get players that matches path finder target condition"
List<EntityHuman> list = Lists.newArrayList();
Iterator iterator = this.getPlayers().iterator();
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 48976b1f07aeb0d588d0856f18b6fd07b2d18e05..a22021766b3bffa4f96d1d4ee546b12e96b5ca58 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -56,6 +56,12 @@ public class PlayerChunk {
long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location);
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
+ // Tuinity start - optimise checkDespawn
+ Chunk chunk = this.getFullChunkIfCached();
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache();
+ }
+ // Tuinity end - optimise checkDespawn
}
// Paper end - optimise isOutsideOfRange
// Paper start - optimize chunk status progression without jumping through thread pool
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 83f070229098ad31b8ae65ffcebe52886ef2884d..f9753b5ada318e39b48a7fd954afdd0e48cd091c 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -195,6 +195,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap;
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ public static final int GENERAL_AREA_MAP_SQUARE_RADIUS = 38;
+ public static final double GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE = 16.0 * (GENERAL_AREA_MAP_SQUARE_RADIUS - 1);
+ public static final double GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE_SQUARED = GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE * GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE;
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerGeneralAreaMap;
+ // Tuinity end - optimise checkDespawn
void addPlayerToDistanceMaps(EntityPlayer player) {
com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Cannot update distance maps off of the main thread"); // Tuinity
@@ -225,6 +231,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured
player.needsChunkCenterUpdate = false;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.add(player, chunkX, chunkZ, GENERAL_AREA_MAP_SQUARE_RADIUS);
+ // Tuinity end - optimise checkDespawn
}
void removePlayerFromDistanceMaps(EntityPlayer player) {
@@ -243,6 +252,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceTickMap.remove(player);
this.playerViewDistanceNoTickMap.remove(player);
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.remove(player);
+ // Tuinity end - optimise checkDespawn
}
void updateMaps(EntityPlayer player) {
@@ -274,6 +286,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured
player.needsChunkCenterUpdate = false;
// Paper end - no-tick view distance
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap.update(player, chunkX, chunkZ, GENERAL_AREA_MAP_SQUARE_RADIUS);
+ // Tuinity end - optimise checkDespawn
}
// Paper end
@@ -462,6 +477,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Tuinity start
this.dataRegionManager = new com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<>(this.world, RegionData.class, 2, (1.0 / 3.0), "Data");
// Tuinity end
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfCachedImmediately(rangeX, rangeZ);
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache(newState);
+ }
+ },
+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfCachedImmediately(rangeX, rangeZ);
+ if (chunk != null) {
+ chunk.updateGeneralAreaCache(newState);
+ }
+ });
+ // Tuinity end - optimise checkDespawn
}
// Paper start - Chunk Prioritization
public void queueHolderUpdate(PlayerChunk playerchunk) {
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index 661ad8f8e67046211e001ea40d97660d7c88f8e5..a77b1d61b9dcb0a2a27d7e50357eaf44c99a661e 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -216,7 +216,7 @@ public final class SpawnerCreature {
blockposition_mutableblockposition.d(l, i, i1);
double d0 = (double) l + 0.5D;
double d1 = (double) i1 + 0.5D;
- EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, -1.0D, false);
+ EntityHuman entityhuman = worldserver.a(d0, (double) i, d1, 576.0D, false); // Tuinity - copied from below method for range, for the love of god we do not need to fucking find the closet player outside of this range - limiting range lets us use the distance map
if (entityhuman != null) {
double d2 = entityhuman.h(d0, (double) i, d1);
@@ -288,7 +288,7 @@ public final class SpawnerCreature {
}
private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) {
- if (d0 <= 576.0D) {
+ if (d0 <= 576.0D) { // Tuinity - diff on change, copy into caller
return false;
} else if (worldserver.getSpawn().a((IPosition) (new Vec3D((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D)), 24.0D)) {
return false;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 1d87e7461d28d8a639fafcfdfa5496014e9180f6..970c1be5477a01ab9c6d79e84c519e22775564ff 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -123,6 +123,65 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return typeKey;
}
+ // Tuinity start - optimise checkDespawn
+ public final List<EntityPlayer> getNearbyPlayers(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate<Entity> predicate) {
+ Chunk chunk;
+ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) {
+ return this.getNearbyPlayersSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate);
+ }
+
+ List<EntityPlayer> ret = new java.util.ArrayList<>();
+ chunk.getNearestPlayers(sourceX, sourceY, sourceZ, predicate, maxRange, ret);
+ return ret;
+ }
+
+ private List<EntityPlayer> getNearbyPlayersSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate<Entity> predicate) {
+ List<EntityPlayer> ret = new java.util.ArrayList<>();
+ double maxRangeSquared = maxRange * maxRange;
+
+ for (EntityPlayer player : (List<EntityPlayer>)this.getPlayers()) {
+ if ((maxRange < 0.0 || player.getDistanceSquared(sourceX, sourceY, sourceZ) < maxRangeSquared)) {
+ if (predicate == null || predicate.test(player)) {
+ ret.add(player);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ private EntityPlayer getNearestPlayerSlow(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate<Entity> predicate) {
+ EntityPlayer closest = null;
+ double closestRangeSquared = maxRange < 0.0 ? Double.MAX_VALUE : maxRange * maxRange;
+
+ for (EntityPlayer player : (List<EntityPlayer>)this.getPlayers()) {
+ double distanceSquared = player.getDistanceSquared(sourceX, sourceY, sourceZ);
+ if (distanceSquared < closestRangeSquared && (predicate == null || predicate.test(player))) {
+ closest = player;
+ closestRangeSquared = distanceSquared;
+ }
+ }
+
+ return closest;
+ }
+
+
+ public final EntityPlayer getNearestPlayer(@Nullable Entity source, double sourceX, double sourceY, double sourceZ, double maxRange, @Nullable Predicate<Entity> predicate) {
+ Chunk chunk;
+ if (source == null || (chunk = source.getCurrentChunk()) == null || maxRange < 0.0 || maxRange >= PlayerChunkMap.GENERAL_AREA_MAP_ACCEPTABLE_SEARCH_RANGE) {
+ return this.getNearestPlayerSlow(source, sourceX, sourceY, sourceZ, maxRange, predicate);
+ }
+
+ return chunk.findNearestPlayer(sourceX, sourceY, sourceZ, maxRange, predicate);
+ }
+
+ @Override
+ public @Nullable EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate<Entity> predicate) {
+ return this.getNearestPlayer(null, d0, d1, d2, d3, predicate);
+ }
+
+ // Tuinity end - optimise checkDespawn
+
protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, final DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 1f7cb91cc4f8d77b2ed0ffbf3a6063fc127f3871..2eb9663a3c9cedad01cd810066d6fc06ee46290c 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -301,6 +301,107 @@ public class WorldServer extends World implements GeneratorAccessSeed {
long lastMidTickExecuteFailure;
// Tuinity end - execute chunk tasks mid tick
+ // Tuinity start - optimise checkDespawn
+ final List<EntityPlayer> playersAffectingSpawning = new java.util.ArrayList<>();
+ // Tuinity end - optimise checkDespawn
+ // Tuinity start - optimise get nearest players for entity AI
+ public final EntityPlayer getNearestPlayer(PathfinderTargetCondition condition, @Nullable EntityLiving source,
+ double centerX, double centerY, double centerZ) {
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby;
+ if (source != null) {
+ Chunk chunk = source.getCurrentChunk();
+ if (chunk != null && (MathHelper.floor(centerX) >> 4) == chunk.locX &&
+ (MathHelper.floor(centerZ) >> 4) == chunk.locZ) {
+ nearby = chunk.getPlayerGeneralAreaCache();
+ } else {
+ nearby = this.getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(MathHelper.floor(centerX) >> 4, MathHelper.floor(centerZ) >> 4);
+ }
+ } else {
+ nearby = this.getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(MathHelper.floor(centerX) >> 4, MathHelper.floor(centerZ) >> 4);
+ }
+
+ if (nearby == null) {
+ return null;
+ }
+
+ Object[] backingSet = nearby.getBackingSet();
+
+ double closestDistanceSquared = Double.MAX_VALUE;
+ EntityPlayer closest = null;
+
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ double distanceSquared = player.getDistanceSquared(centerX, centerY, centerZ);
+ if (distanceSquared < closestDistanceSquared && condition.test(source, player)) {
+ closest = player;
+ closestDistanceSquared = distanceSquared;
+ }
+ }
+
+ return closest;
+ }
+
+ @Override
+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving) {
+ return this.getNearestPlayer(pathfindertargetcondition, entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ());
+ }
+
+ @Override
+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) {
+ return this.getNearestPlayer(pathfindertargetcondition, entityliving, d0, d1, d2);
+ }
+
+ @Override
+ public EntityHuman a(PathfinderTargetCondition pathfindertargetcondition, double d0, double d1, double d2) {
+ return this.getNearestPlayer(pathfindertargetcondition, null, d0, d1, d2);
+ }
+
+ @Override
+ public List<EntityHuman> a(PathfinderTargetCondition condition, EntityLiving source, AxisAlignedBB axisalignedbb) {
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearby;
+ double centerX = (axisalignedbb.maxX + axisalignedbb.minX) * 0.5;
+ double centerZ = (axisalignedbb.maxZ + axisalignedbb.minZ) * 0.5;
+ if (source != null) {
+ Chunk chunk = source.getCurrentChunk();
+ if (chunk != null && (MathHelper.floor(centerX) >> 4) == chunk.locX &&
+ (MathHelper.floor(centerZ) >> 4) == chunk.locZ) {
+ nearby = chunk.getPlayerGeneralAreaCache();
+ } else {
+ nearby = this.getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(MathHelper.floor(centerX) >> 4, MathHelper.floor(centerZ) >> 4);
+ }
+ } else {
+ nearby = this.getChunkProvider().playerChunkMap.playerGeneralAreaMap.getObjectsInRange(MathHelper.floor(centerX) >> 4, MathHelper.floor(centerZ) >> 4);
+ }
+
+ List<EntityHuman> ret = new java.util.ArrayList<>();
+
+ if (nearby == null) {
+ return ret;
+ }
+
+ Object[] backingSet = nearby.getBackingSet();
+
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
+ Object _player = backingSet[i];
+ if (!(_player instanceof EntityPlayer)) {
+ continue;
+ }
+ EntityPlayer player = (EntityPlayer)_player;
+
+ if (axisalignedbb.contains(player.locX(), player.locY(), player.locZ()) && condition.test(source, player)) {
+ ret.add(player);
+ }
+ }
+
+ return ret;
+ }
+ // Tuinity end - optimise get nearest players for entity AI
+
// Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor
@@ -659,6 +760,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void doTick(BooleanSupplier booleansupplier) {
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
+ // Tuinity start - optimise checkDespawn
+ this.playersAffectingSpawning.clear();
+ for (EntityPlayer player : this.getPlayers()) {
+ if (IEntitySelector.affectsSpawning.test(player)) {
+ this.playersAffectingSpawning.add(player);
+ }
+ }
+ // Tuinity end - optimise checkDespawn
this.ticking = true;
gameprofilerfiller.enter("world border");

View File

@ -613,10 +613,10 @@ index f6568a54ab85bc3a682f6fbb19dda7a783625bbe..4005df5ef3dec956a54feff539db2e63
@Override
diff --git a/src/main/java/net/minecraft/server/SensorNearestPlayers.java b/src/main/java/net/minecraft/server/SensorNearestPlayers.java
index 904a6d5ac61d2ac81f1057068383e9ab432852db..c8e43a9f2a23178fdef52375b7204b90b28ac20b 100644
index 904a6d5ac61d2ac81f1057068383e9ab432852db..fa2d366ca6695c099c29469bf69a7845350b4f07 100644
--- a/src/main/java/net/minecraft/server/SensorNearestPlayers.java
+++ b/src/main/java/net/minecraft/server/SensorNearestPlayers.java
@@ -19,22 +19,30 @@ public class SensorNearestPlayers extends Sensor<EntityLiving> {
@@ -19,22 +19,31 @@ public class SensorNearestPlayers extends Sensor<EntityLiving> {
@Override
protected void a(WorldServer worldserver, EntityLiving entityliving) {
@ -627,7 +627,8 @@ index 904a6d5ac61d2ac81f1057068383e9ab432852db..c8e43a9f2a23178fdef52375b7204b90
- entityliving.getClass();
- List<EntityHuman> list = (List) stream.sorted(Comparator.comparingDouble(entityliving::h)).collect(Collectors.toList());
+ // Tuinity start - remove streams
+ List<EntityHuman> nearby = (List)worldserver.getNearbyPlayers(entityliving, 16.0, IEntitySelector.g);
+ List<EntityHuman> nearby = (List)worldserver.getNearbyPlayers(entityliving, entityliving.locX(), entityliving.locY(), entityliving.locZ(),
+ 16.0, IEntitySelector.g);
+ nearby.sort((e1, e2) -> Double.compare(entityliving.getDistanceSquared(e1), entityliving.getDistanceSquared(e2)));
BehaviorController<?> behaviorcontroller = entityliving.getBehaviorController();

View File

@ -7,10 +7,10 @@ The executor returned is finalizable and of course
that causes issues.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index f4d5ff1d0f1ad34032aaab96e1077f4be43d4bf3..caaffea1b670ddfd20bf39cbd55da1c5cf561288 100644
index f9753b5ada318e39b48a7fd954afdd0e48cd091c..83e036f74ee00afd012f237de0642ee5699d13f8 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -337,9 +337,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -340,9 +340,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.worldLoadListener = worldloadlistener;
// Paper start - use light thread

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Prevent light queue overfill when no players are online
block changes don't queue light updates (and they shouldn't)
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 0145f33f66f68a3cf03eae2128aaaa026ddc9951..9e6381a60b804a957eda5b72582d5545faebcb3e 100644
index ce0bb4d228a73d8353d67828529879e1c99682f9..18270d44185b0ec41b9b6e1d2135e7aae3b33261 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1211,7 +1211,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1221,7 +1221,7 @@ public class ChunkProviderServer extends IChunkProvider {
if (ChunkProviderServer.this.tickDistanceManager()) {
return true;
} else {
@ -18,3 +18,16 @@ index 0145f33f66f68a3cf03eae2128aaaa026ddc9951..9e6381a60b804a957eda5b72582d5545
return super.executeNext() || execChunkTask; // Paper
}
} finally {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2eb9663a3c9cedad01cd810066d6fc06ee46290c..2814846acb8b855050a865770dcc12e00fb780d1 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1164,7 +1164,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
gameprofilerfiller.exit();
timings.chunkTicksBlocks.stopTiming(); // Paper
- getChunkProvider().getLightEngine().queueUpdate(); // Paper
+ //getChunkProvider().getLightEngine().queueUpdate(); // Paper // Tuinity - no longer needed here, moved into task execution
// Paper end
}
}

View File

@ -4216,11 +4216,11 @@ index 2760b377d1f68ac5f66e7274317379e2dda8288a..829d4a7508e1656dbdc912096b7eafcf
protected final boolean c;
private final boolean[] j;
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 9ea915101379913cf36b123088af3dfa9833c4ff..68d6fb69a0c1b98b3c11b6d80783faaa58272526 100644
index 936c392c9faa178b5645ea79b0130e0d3e3e1368..8fda4702764e80dae93ef9c0eb53abc198642ab1 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -140,6 +140,52 @@ public class Chunk implements IChunkAccess {
}
@@ -98,6 +98,52 @@ public class Chunk implements IChunkAccess {
this.entitySlicesManager.getHardCollidingEntities(entity, axisalignedbb, into, predicate); // Tuinity
}
// Tuinity end - optimise hard collision handling
+ // Tuinity start - rewrite light engine
@ -4270,9 +4270,9 @@ index 9ea915101379913cf36b123088af3dfa9833c4ff..68d6fb69a0c1b98b3c11b6d80783faaa
+ }
+ // Tuinity end - rewrite light engine
// Tuinity start - entity slices by class
private final com.tuinity.tuinity.chunk.ChunkEntitiesByClass entitiesByClass = new com.tuinity.tuinity.chunk.ChunkEntitiesByClass(this);
@@ -443,6 +489,12 @@ public class Chunk implements IChunkAccess {
// Tuinity start - optimised entity slices
protected final com.tuinity.tuinity.world.ChunkEntitySlices entitySlicesManager;
@@ -405,6 +451,12 @@ public class Chunk implements IChunkAccess {
public Chunk(World world, ProtoChunk protochunk) {
this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null);
@ -5271,10 +5271,10 @@ index a22f0cccecc85b4e4fe4603bcfa213f15c23db69..6cc4a035c8b1312b59685b20039d5e82
this.d &= ~(1 << k);
if (nibblearray != null) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 8b4ab23563a9a0c047267143dc3c6c5545d6c125..ac82f1791ce07e9a23cf97ca34974ab25e26be46 100644
index a22021766b3bffa4f96d1d4ee546b12e96b5ca58..3127fc9dd87e82243e167862cae83ac87b7f4fa0 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -383,13 +383,14 @@ public class PlayerChunk {
@@ -387,13 +387,14 @@ public class PlayerChunk {
public void a(EnumSkyBlock enumskyblock, int i) {
Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
@ -5292,10 +5292,10 @@ index 8b4ab23563a9a0c047267143dc3c6c5545d6c125..ac82f1791ce07e9a23cf97ca34974ab2
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index caaffea1b670ddfd20bf39cbd55da1c5cf561288..9be1581868627b99709bcd446de6dc89c34b42d3 100644
index 83e036f74ee00afd012f237de0642ee5699d13f8..da27ccccdce7756b94e36cc92e60b96d325412b1 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1316,6 +1316,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1319,6 +1319,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Tuinity end - force competion on the main thread
}
@ -5474,12 +5474,12 @@ index 700660dd93b3090334bb3033d5f5fdd6ab684744..e3b72922e2dfad07f3452ec5ee2af379
VoxelShape[] avoxelshape = new VoxelShape[]{VoxelShapes.a()};
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index b1b63a11a6585971685b9ace1b6d91643a36aa95..c448f75b22ead5a178b031d625338f92752617ec 100644
index 2814846acb8b855050a865770dcc12e00fb780d1..fda23d89da29e6a6065fc4bb57a4809f8bdb8b46 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -305,6 +305,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
final List<EntityPlayer> playersAffectingSpawning = new java.util.ArrayList<>();
// Tuinity end - optimise checkDespawn
@@ -402,6 +402,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Tuinity end - optimise get nearest players for entity AI
+ // Tuinity start - rewrite light engine
+ /**

View File

@ -44,10 +44,10 @@ index 55fa3911703f96cf1f97c82b19d8e2d0d220016b..b92ca4a6de01f3f86367fb8dfe3591b0
Vec3D vec3d = new Vec3D(((double) pathpoint.a + this.a.locX()) / 2.0D, ((double) pathpoint.b + this.a.locY()) / 2.0D, ((double) pathpoint.c + this.a.locZ()) / 2.0D);
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 9be1581868627b99709bcd446de6dc89c34b42d3..5fe928e4511f320aef1f3b94a092d2a7d8450706 100644
index da27ccccdce7756b94e36cc92e60b96d325412b1..490f5ce6b688101e40d2dd2683c95da2b6d5e7d5 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -291,7 +291,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -294,7 +294,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Tuinity start
public static enum RegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionDataCreator<RegionData> {
@ -65,10 +65,10 @@ index 9be1581868627b99709bcd446de6dc89c34b42d3..5fe928e4511f320aef1f3b94a092d2a7
@Override
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5f629df0b 100644
index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cbca2017e4 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -873,6 +873,15 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -970,6 +970,15 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.enter("checkDespawn");
if (!entity.dead) {
entity.checkDespawn();
@ -84,7 +84,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
}
gameprofilerfiller.exit();
@@ -895,7 +904,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -992,7 +1001,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.removeEntityFromChunk(entity);
this.entitiesById.remove(entity.getId()); // Tuinity
this.unregisterEntity(entity);
@ -99,7 +99,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
gameprofilerfiller.exit();
}
@@ -1304,6 +1320,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1401,6 +1417,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
int i = MathHelper.floor(entity.locX() / 16.0D);
int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior
int k = MathHelper.floor(entity.locZ() / 16.0D);
@ -112,7 +112,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) {
// Paper start - remove entity if its in a chunk more correctly.
@@ -1313,6 +1335,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1410,6 +1432,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Paper end
@ -125,7 +125,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) {
this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY);
}
@@ -1326,6 +1354,11 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1423,6 +1451,11 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} else {
this.getChunkAt(i, k).a(entity);
}
@ -137,7 +137,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
}
this.getMethodProfiler().exit();
@@ -1788,9 +1821,96 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1885,9 +1918,96 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// Tuinity end
}
new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
@ -234,7 +234,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
private void registerEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
// Paper start - don't double enqueue entity registration
@@ -1971,9 +2091,25 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -2068,9 +2188,25 @@ public class WorldServer extends World implements GeneratorAccessSeed {
VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition);
if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) {
@ -261,7 +261,7 @@ index c448f75b22ead5a178b031d625338f92752617ec..9a8a1e05a60bca77adc904017ae70ef5
try { // Tuinity end
while (iterator.hasNext()) {
@@ -1982,10 +2118,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -2090,10 +2226,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
if (!navigationabstract.i()) {
navigationabstract.b(blockposition);
}

View File

@ -25,10 +25,10 @@ index 13d067f48647dea63ef1bf3a2a3e0868074ba75f..04afd7f285db2f281a038e0be6f557b8
this.a(Long.MAX_VALUE, i, j, flag);
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 5fe928e4511f320aef1f3b94a092d2a7d8450706..a42571cfd2c9c80df27e59db832cb64c2a64e141 100644
index 490f5ce6b688101e40d2dd2683c95da2b6d5e7d5..e6d39c98d0422a4f841cc836e2ac6a357b4db83a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -838,6 +838,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -841,6 +841,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
playerchunk = new PlayerChunk(new ChunkCoordIntPair(i), j, this.lightEngine, this.p, this);
this.dataRegionManager.addChunk(playerchunk.location.x, playerchunk.location.z); // Tuinity
}
@ -36,7 +36,7 @@ index 5fe928e4511f320aef1f3b94a092d2a7d8450706..a42571cfd2c9c80df27e59db832cb64c
this.updatingChunks.put(i, playerchunk);
this.updatingChunksModified = true;
@@ -963,7 +964,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -966,7 +967,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@ -45,7 +45,7 @@ index 5fe928e4511f320aef1f3b94a092d2a7d8450706..a42571cfd2c9c80df27e59db832cb64c
protected void unloadChunks(BooleanSupplier booleansupplier) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
@@ -1114,6 +1115,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1117,6 +1118,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null);
}
if (removed) this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z); // Tuinity
@ -53,7 +53,7 @@ index 5fe928e4511f320aef1f3b94a092d2a7d8450706..a42571cfd2c9c80df27e59db832cb64c
} finally { this.unloadingPlayerChunk = unloadingBefore; } // Tuinity - do not allow ticket level changes while unloading chunks
}
@@ -1206,6 +1208,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1209,6 +1211,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData);
chunkHolder.tasks.forEach(Runnable::run);

View File

@ -10,10 +10,10 @@ chunk future to complete. We can simply schedule to the immediate
executor to get this effect, rather than the main mailbox.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index a42571cfd2c9c80df27e59db832cb64c2a64e141..2c2becef8b56d7e5e998976222df85d2c8516c43 100644
index e6d39c98d0422a4f841cc836e2ac6a357b4db83a..61570ab947b5a153a4c2bcb5a09344f060e6052d 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1494,9 +1494,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1497,9 +1497,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
chunk.B();
return chunk;
});

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Optimize TileEntity load/unload
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 77c748ad07ee257742c4d36825bdd9e916b5d851..8285cd4b659d11d90df633cb99ab8fd36d293cc1 100644
index 4ffaf36b40b32be25bd1944d8b8ddbc342256947..64195edf7c277d581be4d726675b09bd4a263793 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -42,8 +42,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Optimize some stuff in WorldServer ticking
Replaced some streams and some array lists with glue lists
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2289c92c8933bfa0f382167fa5790a4ea17b7c75..1196b482d33e655eb4aa5ea6b66326f12c4363a4 100644
index d4672e7fa899a39bae2d9179472b22db28a58f19..cca6b3585485162e8158e43dee4f8b45d4e30bea 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -788,12 +788,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -885,12 +885,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.i, this.thunderLevel));
}
// */
@ -34,7 +34,7 @@ index 2289c92c8933bfa0f382167fa5790a4ea17b7c75..1196b482d33e655eb4aa5ea6b66326f1
if (flag != this.isRaining()) {
// Only send weather packets to those affected
for (int idx = 0; idx < this.players.size(); ++idx) {
@@ -808,11 +817,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -905,11 +914,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
}
// CraftBukkit end
@ -48,7 +48,7 @@ index 2289c92c8933bfa0f382167fa5790a4ea17b7c75..1196b482d33e655eb4aa5ea6b66326f1
long l = this.worldData.getDayTime() + 24000L;
TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (l - l % 24000L) - this.getDayTime());
if (this.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) {
@@ -1038,9 +1045,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1135,9 +1142,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
private void wakeupPlayers() {
@ -60,7 +60,7 @@ index 2289c92c8933bfa0f382167fa5790a4ea17b7c75..1196b482d33e655eb4aa5ea6b66326f1
}
// Paper start - optimise random block ticking
@@ -1840,8 +1847,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1930,8 +1937,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// Spigot start
if ( entity instanceof EntityHuman )
{
@ -71,7 +71,7 @@ index 2289c92c8933bfa0f382167fa5790a4ea17b7c75..1196b482d33e655eb4aa5ea6b66326f1
for (Object o : worldData.data.values() )
{
if ( o instanceof WorldMap )
@@ -1858,7 +1866,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1948,7 +1956,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
}
}

View File

@ -18,10 +18,10 @@ index 001ac05cf26237eec8a77c476e678ff6d0840311..7b4935dd8c54f5fcb4f26b96c270d3e4
return this.size == 0 && this.pendingTasks.isEmpty();
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 1196b482d33e655eb4aa5ea6b66326f12c4363a4..be5bf0d2ebf4723a5a892f9f51aa18ea74f82fd1 100644
index cca6b3585485162e8158e43dee4f8b45d4e30bea..68fbbcac7b6b2f24a42c3a63825f940e52f6f51a 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1826,6 +1826,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1916,6 +1916,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Paper end

View File

@ -336,10 +336,10 @@ index 0000000000000000000000000000000000000000..a5314a0396f4a8f373d855e873820ddd
+ }
+}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index fa1d559a07199bf52d8ae04b2c34261efdebdcdb..a3c86e6b56f744b340bc486b9d728114f884d28f 100644
index 0924f6b484468f3cf3c2d405101c0158c12d69e6..bcf94f13414b1e8cb7438af81448e74f42a24768 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -337,6 +337,14 @@ public class Chunk implements IChunkAccess {
@@ -298,6 +298,14 @@ public class Chunk implements IChunkAccess {
// CraftBukkit start
this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
@ -351,9 +351,9 @@ index fa1d559a07199bf52d8ae04b2c34261efdebdcdb..a3c86e6b56f744b340bc486b9d728114
+ this.sections[i2] = null;
+ }
+ } // Yatopia end
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
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index e77da341b765725771726283d3a8249b514b40da..c44333ec5b0c1914f7cb9f4b3b39626069136c22 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java

View File

@ -108,10 +108,10 @@ index 0668d383db1f3a81d1053954d72678c7ac5aecec..7b9f83e63d0f9cd83a246be33af4ab91
ChatComponentText chatcomponenttext = new ChatComponentText("Internal server error");
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 8285cd4b659d11d90df633cb99ab8fd36d293cc1..aaa9a222f755622f604e5980eb2f1c0039411fa4 100644
index 64195edf7c277d581be4d726675b09bd4a263793..bdc85c5026b9d5fe50e709cf6d5c8eb8d5f3653b 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -988,6 +988,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@@ -1019,6 +1019,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
// Paper start - Prevent tile entity and entity crashes
String msg = "TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ();
System.err.println(msg);

@ -1 +1 @@
Subproject commit 8703980b48dc20f7266c77bcbdf51f376eed6204
Subproject commit 7dc1546a25056ffef08ec6f0c7a5fb175be8d7a9

@ -1 +1 @@
Subproject commit e8696c6d78fb6773480072803cab59145daa8669
Subproject commit 586aef6305493a61736f1cd2d3858c3a67113967

@ -1 +1 @@
Subproject commit 9537c770b0820b8b7a9915a7d571de528dc5ce8c
Subproject commit 40868883d9942e998923ee576cfa118c90e9e068

@ -1 +1 @@
Subproject commit 2dfd22e41c4d1822f6e813317e64ff7afdb33e80
Subproject commit a539774b11798c5640509ee33fd84c52b936b24f

View File

@ -1 +1 @@
8703980b48dc20f7266c77bcbdf51f376eed6204
7dc1546a25056ffef08ec6f0c7a5fb175be8d7a9

View File

@ -1 +1 @@
e8696c6d78fb6773480072803cab59145daa8669
586aef6305493a61736f1cd2d3858c3a67113967

View File

@ -1 +1 @@
9537c770b0820b8b7a9915a7d571de528dc5ce8c
40868883d9942e998923ee576cfa118c90e9e068

View File

@ -1 +1 @@
2dfd22e41c4d1822f6e813317e64ff7afdb33e80
a539774b11798c5640509ee33fd84c52b936b24f

View File

@ -1,4 +1,4 @@
name=Airplane
useBlackList=False
list=server/Airplane-MC-Dev-Fixes.patch,server/Airplane-Configuration.patch,server/Remove-streams.patch,server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch,server/Simpler-ShapelessRecipes-comparison-for-Vanilla.patch,server/Queue-lighting-update-only-once.patch,server/Use-unmodifiableMap-instead-of-making-copy.patch,server/Swap-priority-of-checks-in-chunk-ticking.patch,server/Reduce-projectile-chunk-loading.patch,server/Optimize-random-calls-in-chunk-ticking.patch,server/Don-t-get-entity-equipment-if-not-needed.patch,server/Dynamic-activation-range.patch,server/Reduce-allocs-improve-perf-of-StructureManager.patch,server/Cache-palette-array.patch,server/Reduce-chunk-loading-lookups.patch,server/Reduce-memory-allocations.patch
useBlackList=True
list=server/Airplane-Branding-Changes.patch,server/Disable-Paper-timings-by-default.patch,server/Only-check-for-spooky-season-once-an-hour.patch
branch=origin/master

Some files were not shown because too many files have changed in this diff Show More